我想要一个深层嵌套的Python布尔表达式的PEG语法示例。 PEG语法不能“非常递归”,否则会导致堆栈溢出。支持'|','&','('和')'。
输入的例子:(a = 1 | b = 1 | c = 1 | d = 1& e = 2)&(f = 2& g = 2& h = 2 | i = 3 | j = 3 | K = 3)
答案 0 :(得分:2)
要解析典型(特别是布尔逻辑)表达式,您几乎不需要Peg解析器;从来没有真正需要回溯。选择任何解析引擎并使用它(如果你坚持的话,包括一个Peg引擎)。
这是一个适用于你的例子的语法:
EXPRESSION = DISJUNCTION ;
DISJUNCTION = CONJUNCTION ( '|' CONJUNCTION )*;
CONJUNCTION = TERM ( '&' TERM );
TERM = '~' TERM | '(' EXPRESSION ')' | CONDITION ;
CONDITION = VARIABLE '=' CONSTANT ;
如果你想使用易于编码的手写递归下降解析器来实现这个语法,请参阅我的答案,如何执行此操作:Is there an alternative for flex/bison that is usable on 8-bit embedded systems?
关于堆栈溢出:除非你的表达式嵌套了数百个级别("括号"),在大多数windows或linux系统上,可用堆栈远远大于应用于解析器的堆栈需求人们在实践中写下的表达方式。凭借巨大的表情,无论如何人们都无法阅读它们,因此它们不会发生。 OP的示例表达式需要嵌套几个堆栈条目。
如果你为一个成熟的编程语言编写语法,并且有人在该语言中编写了一个大而复杂的程序,那么你可能会冒着堆栈溢出的风险。我可以告诉你,根据我构建的编译器的经验,256(堆栈帧)的嵌套很容易适合Windows 1Mb堆栈空间,这足以编译200万行程序与每个奇怪的构造和深度嵌套的词法范围人类已知的特技。
答案 1 :(得分:1)
这是一个支持上面简单布尔表达式(以及更多)的PEG语法,假设AND应该比OR更紧密地绑定:
expr = multiOR !.
multiOR = multiAND (_wsp opOR _wsp multiAND)*
multiAND = comparison (_wsp opAND _wsp comparison)*
comparison = varOrNum _wsp opCOMP _wsp varOrNum
/ '!'? var
/ '!'? '(' multiOR ')'
varOrNum = var / num
var = [a-z]i [a-z0-9_]i*
num = '-'? [0-9]+ ('.' [0-9]+)?
opOR = '|' '|'?
opAND = '&' '&'?
opCOMP = [<>=] '='? / [≤≥≠] / '!='
_wsp = [ \t]*
在这里,您可以看到将此PEG应用于您的输入的结果:
显然,比较运算符有点过分,它支持布尔运算符|
/ &
和||
/ &&
。随意修改。