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.