pythonparsingparsimonious

Parsimonious ParseError


Digging deeper into grammars and PEG in special, I wanted to have a DSL with the following syntax:

a OR (b AND c)

I am using parsimonious here with the following grammar:

from parsimonious.grammar import Grammar
grammar = Grammar(
    """
    expr            = (term operator term)+
    term            = (lpar term rpar) / (variable operator variable)
    operator        = and / or
    or              = _? "OR" _?
    and             = _? "AND" _?
    variable        = ~r"[a-z]+"
    lpar            = "("
    rpar            = ")"
    _               = ~r"\s*"
    """
)
print(grammar.parse('a OR (b AND c)'))

However, this fails for the above text with

parsimonious.exceptions.ParseError: Rule 'variable' didn't match at '(b AND c)' (line 1, column 6).

Why? Haven't I specified term as ( term ) or term ?
Why does it choose the rule for variable instead (which of course fails) ?


Solution

  • The first thing in expr is a term, so that's what the parser looks for.

    A term in your grammar is either

    ( term )
    

    or

    variable operator variable
    

    And the input is

    a OR (b AND c)
    

    That doesn't start with a ( so the only way it can be a term is if it matches variable operator variable. a is a variable; OR is an operator. So the next thing to match is variable.


    Perhaps what you want is:

    expr = term (operator term)*
    term = (lpar expr rpar) / variable