boostorg / spirit

Boost.org spirit module
http://boost.org/libs/spirit
392 stars 161 forks source link

possibility of detecting left recursive grammars at compile time #540

Open Xeverous opened 5 years ago

Xeverous commented 5 years ago

I have encountered the same problem multiple times.

The problem appears when the grammar is wrongly designed which causes it to be defective by design. One such example is this:

auto const subscript_expression_def = value_expression >> '[' >> value_expression >> ']';
BOOST_SPIRIT_DEFINE(subscript_expression)

auto const value_expression_def =
      literal_expression
    | array_expression
    | subscript_expression // added most recently and defined above
    | function_call
    | identifier;
BOOST_SPIRIT_DEFINE(value_expression)

The grammar for my array_expression accepts something like [0, 1, 2, 3]. Subscript will accept any expression followed by bracket-enclosed expression like foo[0], func()[0], [0, 1, 2, 3][i].

But this grammar does not actually work. When the parser encounters foo[0], it does this:

Obviously this is a bug in the design/implementation which can be fixed by different order of alternatives but I'm interested if:

Kojoley commented 5 years ago

The problem appears when the grammar is wrongly designed which causes it to be defective by design.

Those grammars are not defective, but just left recursive (as further noted by you), and Spirit being a recursive descent parser cannot parse such grammars https://en.wikipedia.org/wiki/Left_recursion#Accommodating_left_recursion_in_top-down_parsing.

Would it be possible to detect such "malformed" grammars at compile-time?

It is possible for context-free grammars, as also possible to rewrite them, though it will certainly break at least some usages.

Should Spirit have some guidance in grammar/language design on its documentation?

I do not think copying Wikipedia or any other source is a good idea, not only because of probable legal problems with such actions, but because there are different left recursion elimination algorithms and optimizations on them.

Spirit.Classic documentation has a record in FAQ about left recursion https://www.boost.org/doc/libs/master/libs/spirit/classic/doc/faq.html#left_recursion, I am not sure about its usefulness, but you can improve it.

Xeverous commented 5 years ago

Spirit.Classic documentation has a record in FAQ about left recursion https://www.boost.org/doc/libs/master/libs/spirit/classic/doc/faq.html#left_recursion, I am not sure about its usefulness, but you can improve it.

I think it is useful, it showcases examples how to deal with common left recursion problems. Could be updated and added to X3 docs.

djowel commented 4 years ago

I welcome any PR for improving the docs.