3

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) ?

sophros
  • 14,672
  • 11
  • 46
  • 75
Jan
  • 42,290
  • 8
  • 54
  • 79

1 Answers1

3

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
rici
  • 234,347
  • 28
  • 237
  • 341