marcioAlmada / yay

Yay is a high level PHP preprocessor
https://github.com/marcioAlmada/yay
MIT License
572 stars 35 forks source link

Optional split operator in grammar "list" method #39

Closed SerafimArts closed 6 years ago

SerafimArts commented 7 years ago

It's not entirely clear how to make a comma optional in the list method.

Like this:

field: Value, // <---- trailing comma here
field2: Value2 // <--- no comma
field3: Value3

Grammar:

    ·comma? {
        '','' | T_WHITESPACE
    }
    ·fields {
        list(·field, ·comma)
    }

Error:

Unexpected '{' on line 26, expected '?'.
Unexpected T_STRING(·comma) on line 27, expected T_CONSTANT_ENCAPSED_STRING('').
Unexpected T_LIST(list) on line 27, expected '?' or T_LIST() or T_STRING() or T_VARIABLE() or T_CONSTANT_ENCAPSED_STRING('') or '!'.
marcioAlmada commented 6 years ago

Try combining with optional(). I guess this would work as you'd expect:

$ts = TokenStream::fromSourceWithoutOpenTag(' {a b c} ');

$parser = chain(
    token('{'),
    ls(
        label(),
        optional(token(','))
    ),
    token('}')
);

$ast = $parser->parse($ts);

var_dump($ast->unwrap());

var_dump($ts->index());

Outputs:

[
  Token { +0: "T_STRING(a)"},
  Token { +0: "T_STRING(b)"},
  Token { +0: "T_STRING(c)"},
]

object(NodeEnd) {}

And perhaps this is more elegant depending on how you want the final AST to be:

$parser = between(
    token('{'),
    ls(
        label(),
        optional(token(','))
    ),
    token('}')
);

I'm closing this one but, please, reopen if necessary.

:wink: