简体   繁体   中英

Ambiguous grammar when parsing boolean expressions with Peg.js

I'm writing a parser that generates an abstract syntax tree from boolean expressions.

I have the following Peg.js grammar that supports ^ and , as & and | respectively:

start
  = operation

// optional whitespace
_  = [ \t\r\n]*

operation "operation"
  = "("? _ left:(operand / operation) _ operator:operator _ right:(operand / operation) _  ")"?
  {
    return {
      operation: operator,
      between: [ left, right ]
    };
  }

operator "operator"
  = operator:["&"|"|"]  
  {
    return operator;
  }

operand "operand"
  = operand:[a-z]
  { 
    return { operand: operand };
  }

It successfully parses expressions like a & b and a & (b | c) , however it fails if the expression starts with an operation:

(a | b) & c
Line 1, column 8: Expected end of input but " " found.

The expression gets parsed correctly if I surround it with parenthesis:

((a | b) & c)

My guess is that Peg.js is only taking (a | b) as an operation, instead of an operand of the parent operation, thus failing when seeing the & c .

What am I missing?

Your operation rule says the brackets are optional but having one does not enforce the other to be there. Eg, (a & b is parsed successfully.

You need to break it up into smaller parts. The separate rules for and and or are to allow operator precedence to do its trick.

Try this:

start
  = sentence

sentence
  = orSentence

orSentence
  = lhs:andSentence __ '|' __ rhs:orSentence { return { operation: '|', between: [lhs, rhs] }; }
  / andSentence

andSentence
  = lhs:primarySentence __ '&' __ rhs:andSentence { return { operation: '&', between: [lhs, rhs] }; }
  / primarySentence

primarySentence
  = '(' _ sentence:sentence _ ')' { return sentence; }
  / operand

operand
  = operand:[a-z] { return { operand: operand }; }

_ "optionalWhiteSpace"
  = whiteSpace *

__ "mandatoryWhiteSpace"
  = whiteSpace +

whiteSpace
  = [ \t\n\r]+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM