Skip to content
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

Return an expression or decide how to continue #387

Closed
barsdeveloper opened this issue Mar 19, 2023 · 4 comments
Closed

Return an expression or decide how to continue #387

barsdeveloper opened this issue Mar 19, 2023 · 4 comments

Comments

@barsdeveloper
Copy link

barsdeveloper commented Mar 19, 2023

Hello, I am rewriting a grammar from Parsimmon to Peggy and I would like to encode some behavior I have in my previous grammar.
Is there any way to decide how to continue parsing using the value of some label? In Parsimmon this is the chain function but I was wondering whether this is possible in peggy.

For example let's say I have object with type information (and this is specified somewhere else). In my parsed test I do get a name and then some type following that name.

integer: 123
word: alpha

Now, I know I can create a grammar for a limited amount of those labels but let's say the labels are many (many) and the resulting types are complex and they are specified somewhere else, outside the grammar. How do I generate dynamic grammar from the value I get, decide how to continue parsing?
The following is not valid, just a concept

decide = value: word ": " {
    if (value == "integer") {
    	return integer // can't return a grammar rule
    } else if (value == "word") {
        return word // can't return a grammar rule
    } else {
        //...
    }
}
integer = [0-9]+
word = [a-z]i+

if decide is integer then it expects to parse integer, if it is word then it expects to parse a word and so on.

@Mingun
Copy link
Member

Mingun commented Mar 19, 2023

If I correctly understand your needs, you have a two ways to do that:

  • just use choice operator
    decide
      = integer
      / word
      / ...
      ;
    Remember, that order of alternatives is important! If one rule is a prefix of other (for example, = and ==) the longest should be the first
  • you need a some rule that will match your tag and then you can analyze this tag using semantic predicate:
    // returns array [tag_result, rule_result]
    decide = tag:tag (
        &{ return isInteger(tag); } @integer
      / &{ return isWord(tag); } @word
      / ...
    );
    Because probably the tags will uniquely determine the type, the order not so important, but the right order can make grammar faster. Put more expected alternatives first

@barsdeveloper
Copy link
Author

barsdeveloper commented Mar 19, 2023

Good idea, thanks.
Do you know if I can have in the grammar (I am using CLI to generate my parser at compile time throught npm run build command) a mix of static and dynamic rules?

integer = [0-9]+ // static rule
word = [a-z]i+ // static rule
entry = tag `${some generated rule that makes the grammar}` // dynamic rule generated through javascript code

I understand it is a bit fuzzy but I am new to parser generators. Thanks for the help and patience.

@Mingun
Copy link
Member

Mingun commented Mar 19, 2023

You cannot have ${some generated rule that makes the grammar} in the grammar itself, but you can generate your grammar before running the CLI. You also could write a plugin that will append necessary rules directly to the AST instead of generating grammar text. If you want, you can even write that plugin in that way, that is would read its input from the same grammar file, so technically your grammar will contain both static and dynamic rules:

{{
  // For example, you does not use top-level initializer and
  // you decide to write some code inside it for your plugin
}}
integer = [0-9]+ // static rule
word = [a-z]i+ // static rule

// dynamic rules will be injected to the AST by plugin, 
// plugin take their input from `ast.topLevelInitializer`

@hildjj
Copy link
Contributor

hildjj commented Mar 21, 2023

I'm going to close this. Please reopen if there is a concrete feature to request.

@hildjj hildjj closed this as completed Mar 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants