> rule(:logicalOrExpression) { logicalAndExpression >>
> logicalOrExpressionTail.repeat }
> rule(:logicalOrExpressionTail) { space? >>
> logicalOrOperator.as(:binop) >> space? >> logicalAndExpression.as(:op) }
> rule(:logicalOrOperator) { str('||') }
>
> rule(:logicalAndExpression) { inclusiveOrExpression >>
> logicalAndExpressionTail.repeat }
> rule(:logicalAndExpressionTail) { space? >>
> logicalAndOperator.as(:binop) >> space? >> inclusiveOrExpression.as(:op) }
> rule(:logicalAndOperator) { str('&&') }
>
> etc etc
>
> This is a common idiom for refactoring to avoid left recursion (which is
> a big no-no in PEGs), although it can be somewhat counter-intuitive. I
> found that studying grammars for other parsers very helpful; Spirit (for
> c++/boost) has some good examples, as does ANTLR. You can translate
> these into parslet without too much difficulty.
To add a really not well thought out remark: Could this kind of code be
eliminated through a single meta rule? Like one that says:
expression_of(term, [%w(&& ||), %w(* /), %w(+ -)])
The expression_of method would take term and build a hierarchy of binary
rules that encode precedence in PEG-style. It would be so much easier to
read... Left recursion elimination in the engine seems suddenly less
elegant to me.
But maybe such a thing cannot be created for reasons not obvious to me
right now. Anyone biting?
k