Javascript 使用Peg.js解析布尔表达式时语法不明确
我正在编写一个解析器,它从布尔表达式生成一个抽象语法树 我有以下支持^和^的Peg.js语法∨, 分别为&和|:Javascript 使用Peg.js解析布尔表达式时语法不明确,javascript,peg,Javascript,Peg,我正在编写一个解析器,它从布尔表达式生成一个抽象语法树 我有以下支持^和^的Peg.js语法∨, 分别为&和|: start = operation // optional whitespace _ = [ \t\r\n]* operation "operation" = "("? _ left:(operand / operation) _ operator:operator _ right:(operand / operation) _ ")"? { return
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 };
}
它成功解析a&b和a&b | c等表达式,但如果表达式以操作开始,则会失败:
(a | b) & c
Line 1, column 8: Expected end of input but " " found.
如果用括号将表达式括起来,则可以正确解析表达式:
((a | b) & c)
我猜想Peg.js只是将a | b作为一个操作,而不是父操作的操作数,因此在看到&c时失败
我遗漏了什么?您的操作规则说括号是可选的,但有一个括号并不强制另一个括号在那里。例如,a&b解析成功 你需要把它分成更小的部分。and和or的单独规则是允许运算符优先级发挥作用 试试这个:
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]+
你的操作规则说括号是可选的,但有一个括号并不强制另一个括号在那里。例如,a&b解析成功 你需要把它分成更小的部分。and和or的单独规则是允许运算符优先级发挥作用 试试这个:
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]+