On Mon, May 2, 2011 at 4:02 PM, Thiel Chang <[email protected]> wrote:
> Hi Anton,
>
> Anton?! ;)
> Many thanks for your advice. I have enclosed my grammar rules:
>
*snip*
Your 'term' rule contains factor, which will insert (:integer => '1') when
it matches. But the 'term' rule also includes 'term_acc', which includes
'term'....which will insert (:integer => '2') when it matches.....but you've
already got one of those, which is why Parslet complains. If you investigate
the ".as(:foo)" stuff, you'll be able to get some hierarchy into your parse
tree. For example changing your term rule to:
rule(:term) { factor >> space? >> term_acc.as('foo') }
will cause the parse to succeed.
Actually, this should be a simple grammar for parsing arithmetic
> expressions.
>
Haha, that's never easy in a PEG ;) I've just done something very similar to
a C expression parser, I ended up with a big chain of rules that follow this
format:
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.
But I am still struggling :-)
>
Good luck!
ant