Comments (12)
Hi Blake,
The ability to overload parameterized rules is something I've wanted for a while, too. Wouldn't it be nice if there could be a one-parameter variant of ListOf
that assumes ","
as the separator?
BuiltInRules {
...
ListOf<elem, sep> = ...
ListOf<elem> = ListOf<elem, ",">
...
}
I've already got a plan for how this will manifest in the semantics, and how it will be implemented. I'll do my best to commit it in the next week or two.
Thanks for filing!
Cheers,
Alex
from ohm.
Hello Alex!
I think the assumption of a comma as the default ListOf separator makes sense. It would certainly reduce a little bit of clutter in the syntax definition I'm currently working on.
I started taking a look at the code to see how it might be implemented, but I think I'll leave it to you as you've already been thinking about it and know this code base much better than myself :)
Looking forward to it!
from ohm.
Sounds good! I'll try to post some details here in the next couple of days, that way you can tell me if there's a better way :)
from ohm.
My guess is that the simplest implementation is just concatenating the
parameter arity to the rule name. You may need some 'escaping' mechanism
however, so that you don't conflict with a user-defined name.
On Jan 31, 2016 9:09 PM, "Alessandro Warth" [email protected]
wrote:
Sounds good! I'll try to post some details here in the next couple of
days, that way you can tell me if there's a better way :)—
Reply to this email directly or view it on GitHub
#57 (comment).
from ohm.
Right, that's where I was headed, too. My idea was to use Prolog-style names for the rules, e.g.,
ListOf/2
is the two-parameter version ofListOf
, andListOf/1
is the one-argument version.
Every rule will have this /n
suffix. For most rules, it will be /0
. You'll never have to write these suffixes in a grammar, because it's clear from the application. But it's a different story on the semantics side. To make it more convenient for folks to write semantic actions, you'll be able to write the name of the rule without the /n
so long as it's not ambiguous, i.e., so long as there's only one rule in the grammar with that name. If it is ambiguous, you'll get an error at the time you define the operation / attribute / whatever.
Back to preparing for tomorrow's lecture!!
from ohm.
I'm a bit concerned that this will add additional complexity to the API, without providing a whole lot of benefit. The ListOf/2
syntax will complicate writing semantic actions, because the slash is not a valid in a method name in most languages. It's not a problem for the current JavaScript API, but in other host languages it may make sense to write semantic actions as methods in a class.
I'm also not sure how the "so long as it's not ambiguous" would work. Say today that someone has a grammar that uses ListOf/2, and they name the semantic action ListOf
. Then I extend that grammar, and add a new ListOf<x>
rule. Then, if I want to extend an operation/attribute, I need to write an action for my new ListOf/1
rule. But what if I also want to override the the parent grammar's ListOf/2
rule? Would I name it ListOf
(as it is named in the parent operation) or ListOf/2
?
Since you can always deal with the lack of ListOf/1
by giving it another name (e.g., CommaSeparatedListOf
), I'm not sure the benefit is worth the additional complexity.
from ohm.
Hi Pat, you make good points, and we should think about this carefully. First, it's useful to separate what we want -- the ability to provide default values for rule parameters -- from the mechanisms that might support it, e.g., overloading for rules.
I'm also not sure how the "so long as it's not ambiguous" would work. Say today that someone has a grammar that uses
ListOf/2
, and they name the semantic actionListOf
.
This wouldn't be allowed, because it's ambiguous! This is because every grammar inherits from the BuiltInRules
grammar, which would have definitions for both ListOf/1
and ListOf/2
. So in this case, you would have to write a semantic action for ListOf/2
explicitly.
Then I extend that grammar, and add a new
ListOf<x>
rule. Then, if I want to extend an operation/attribute, I need to write an action for my newListOf/1
rule. But what if I also want to override the the parent grammar'sListOf/2
rule? Would I name it ListOf (as it is named in the parent operation) orListOf/2
?
In grammars, you would never have to write the /n
. But in the semantic actions, you would have to, for any rule that's been overloaded either in the grammar you are writing, or in one of its supergrammars.
Anyway, I agree that we have to think about this a little more. To be continued.
from ohm.
This wouldn't be allowed, because it's ambiguous! This is because every grammar inherits from the BuiltInRules grammar, which would have definitions for both ListOf/1 and ListOf/2. So in this case, you would have to write a semantic action for ListOf/2 explicitly.
But what if we didn't add a new ListOf/1
rule to BuiltInRules
?
Forget about ListOf -- say I have the following grammar:
G {
...
quoted<exp, quoteChar> = quoteChar exp quoteChar
}
I write an attribute for this grammar, and since there is only one rule named quoted
, I name the semantic action quoted
, and not quoted/1
.
Then, someone else extends my grammar:
G2 <: G {
...
quoted<exp, openQuote, closeQuote> = openQuote exp closeQuote
}
Now, they want to extend the attribute that I wrote before. Since quoted
is now ambiguous, they would have to write an action named quoted/3
for their new rule. But what if they also want to override the handling of the supergrammar's quoted
rule? I would think that they'd have to name the action quoted/2
, but it seems confusing that the parent attribute has no action named quoted/2
-- only quoted
.
Now, not to say that this is a major problem, but I think it could be confusing.
from ohm.
Since ECMAScript is one of the current major examples for an Ohm grammar and it is a grammar where ES2015 could make use of a lot of rules from ES5 (as currently hinted at in es6.ohm) here is another good use case where some kind of overloading could make sense:
ES2015 introduces a Yield
parameter in almost all rules (in addition to e.g. Return
and Default
). The current
PrimaryExpression = this
| identifier
| literal
| ArrayLiteral
| ObjectLiteral
| "(" Expression<withIn> ")" -- parenExpr
for example could not be reused as something like this would be necessary:
PrimaryExpression<allowYield> = this
| identifier<allowYield>
| literal
| ArrayLiteral<allowYield>
| ObjectLiteral<allowYield>
| // ... further extensions
Note: That the grammar used in the spec has an interesting approach to that issue and expands
PrimaryExpression[Yield] :
this
IdentifierReference[?Yield]
...
to
PrimaryExpression:
this
IdentifierReference
...
PrimaryExpression_Yield : // respectively PrimaryExpression<allowYield>
this
IdentifierReference_Yield // respectively IdentifierReference<allowYield>
...
from ohm.
Hi Pat,
Now, they want to extend the attribute that I wrote before. Since quoted is now ambiguous, they would have to write an action named quoted/3 for their new rule. But what if they also want to override the handling of the supergrammar's quoted rule? I would think that they'd have to name the action quoted/2, but it seems confusing that the parent attribute has no action named quoted/2 -- only quoted.
Now, not to say that this is a major problem, but I think it could be confusing.
Right, it could be a little confusing for now but I'm not super worried about it. (See the last part of my comment.)
In any semantics for G
-- the original grammar -- you should be able to write a semantic action for the quoted
rule, which takes 2 parameters, using either the name quoted
or quoted/2
. The former is just a shorthand for the latter, which is the "canonical" name of the rule.
Suppose someone comes along later and writes a grammar G2
, which extends G1
and overloads quoted
by declaring a rule with that name that takes three arguments. If they want to extend a semantics that was originally written for G
and override the semantic action for the two-parameter quoted
rule in an operation or an attribute, they would have to use the name quoted/2
. (I.e., they wouldn't be able to use the shorthand for that rule.)
Coming back to the confusion thing: these names are only part of the verbose and clunky "assembly language" interface for Ohm grammars that we're exposing and using right now. My hope is that soon enough we'll have an editor for semantic actions, and this clunky interface will become an implementation detail that programmers don't ever have to see. Not only will this avoid confusion, but it will also eliminate some of the portability problems you mentioned earlier.
Cheers,
Alex
from ohm.
Sorry to go slightly off-topic, but...
My hope is that soon enough we'll have an editor for semantic actions
Is there more information about the editor anywhere?
from ohm.
Is there more information about the editor anywhere?
Hehe, unfortunately not yet. But "soon enough" :)
from ohm.
Related Issues (20)
- Type definitions for parameterized rules are inconsistent with behavior HOT 1
- Semantic action '[...]' has the wrong arity: expected 3, got 0 HOT 5
- Semantic actions for comments defined under the space rule HOT 1
- Add ability to type operation parameters & return values HOT 11
- CLI: Line endings in generated files vary across systems and platforms HOT 1
- cli.js is reading incorrect package.json file for version HOT 2
- Typescript example causes error HOT 1
- space with applySyntactic causes failure
- `toAST` incorrectly makes some nodes intermediate nodes HOT 1
- Indentation-sensitive grammar forgets consumed dedents HOT 1
- Syntax error handling? HOT 2
- Indentation-sensitive parsing: dedent not working? HOT 3
- Typescript example fails to compile HOT 1
- "Built-in Rules" section of syntax reference docs are incorrectly formatted
- No indication of stack size exceeded
- Do we get comments from ohm? HOT 6
- Idiomatic way to do partial (prefix) parses
- NPM release behind latest commit
- Partially parse grammar
- Odd behavior: Alternation fails instead of trying second alternative
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ohm.