-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement syntax for importing rules #292
Conversation
Could you please set the branch with ranges as base to this PR, so that it shows only the relevant diff? |
@@ -46,16 +46,42 @@ | |||
// ---- Syntactic Grammar ----- | |||
|
|||
Grammar | |||
= __ topLevelInitializer:(@TopLevelInitializer __)? initializer:(@Initializer __)? rules:(@Rule __)+ { | |||
= __ imports:(@Import __)* topLevelInitializer:(@TopLevelInitializer __)? initializer:(@Initializer __)? rules:(@Rule __)+ { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imports, top-level initializer and initializer have to be in strict order, and it might be not that obvious, what it is. Can we just consider all of the things mentioned in this rule as top-level statements, and parse them in no particular order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, it is possible, although I would still not use such flexibility and would not recommend that anyone do this. Current order reflects order in which statements will be executed:
- importing grammars (in specified order)
- running global initializer
- running per-parse initializer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume the imported grammars effectively go at the end of the AST? You usually don't want them to be the default start rule, and if you do, you write a pass-through rule as your first rule.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current PR defines only syntax, not semantics. You are free to choose what to do with that AST. Currently AST only contains information, that it referenced to some external grammar. The pass that will deal with that information is to be written.
One of possible implementation of imports (which, for example, I've made for myself almost ten years ago) is to include them into one big AST; of course it is better to logically include new rules at the end of AST.
src/parser.pegjs
Outdated
topLevelInitializer, | ||
initializer, | ||
rules, | ||
location: location() | ||
}; | ||
} | ||
|
||
Import | ||
= 'import' __ | ||
'{' __ rules:ImportedRule|.., __ ',' __| (__ ',')? __ '}' __ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imagine a situation where you have a grammar that defines an expression
rule (for example, this exact grammar) that imports another grammar with expression
rule (ecmascript grammar for actions). Even though reexporting it as EcmaExpression
might be fine, prefixing every imported name might be quite tedious.
I think it would be best just to reuse the whole import
rule from JS, and emit it verbatim into generated file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be best just to reuse the whole import rule from JS, and emit it verbatim into generated file.
I deliberately chose to support only that subset of JS import
clause where the rule names are explicitly indicated. This will allow us to make basic checks (e.g. that the rules we refer to exist, or that we do not have two rules with the same name from different imports -- you will need to rename one of them using as
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that all rules are exported from every .peggy file? There's no way to mark something private
, or to explicitly export?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is the question, that should be investigated; yes, without annotations we have no way to mark what we should export, and what not (at least, inside the grammar).
Unfortunately, this is impossible, because branch |
… in the compiler: ``` import { rule1, rule2 as alias2, ..., ruleN } from '<string with path to the .peggy file>'; ``` Import clauses expected before (top) initializer code block. All import clauses appeared in the `grammar` AST node in the `imports` node property. This property contains array of AST `import` nodes with the`rules` and `path` properties. `rules` contains array of the `imported_rule` AST nodes.
I think #417 is kind of the inverse of this approach. it defines semantics, but no syntax. One of the problems I've got with the import syntax is that either the core peggy code needs to know how to read files and do path munging, or you need to pass in primitives that do so. In node, you'd use I wonder if we actually need syntax for this, or if #417's approach of passing in an array in the same shape that |
Fixed in #456 |
Draft that implements syntax for importing rules. Does not implement actual importing. Design questions should be discussed in the #239 first.
I open this PR so anyone can experiment with implementing importing.