【发布时间】:2018-02-04 04:06:03
【问题描述】:
因此,在我
举个例子(只做加减的解析器):
扫描仪:
%%
[0-9]+ {return NUMBER;}
%%
解析器:
%%
/* Left */
expression:
NUMBER
| expression '+' NUMBER { $$ = $1 + $3; }
| expression '-' NUMBER { $$ = $1 - $3; }
;
/* Right */
expression:
NUMBER
| NUMBER '+' expression { $$ = $1 + $3; }
| NUMBER '-' expression { $$ = $1 - $3; }
;
%%
对于 1+5-2 的示例,似乎使用左递归,解析器从词法分析器接收到 '1' 并看到 '1' 匹配 expression: NUMBER 并将值 1 的表达式推送到解析器堆栈。它看到 + 并推动。然后它看到 5 和表达式 (1),+ 和 5 匹配 expression: expression '+' NUMBER,所以它弹出两次,进行数学运算并将值 6 的新表达式压入堆栈,然后重复减法。在任何一点,堆栈上最多有 3 个符号。所以它就像一个就地计算,从左到右运行。
使用正确的递归,我不确定为什么它必须加载堆栈上的所有符号,但我将尝试描述为什么会出现这种情况。它看到 1 并匹配 expression: NUMBER,因此它将值为 1 的表达式压入堆栈。它将“+”压入堆栈。当它看到 5 时,我的第一个想法是 5 本身可以匹配 expression: NUMBER 并因此成为值 5 的表达式,然后它加上堆栈上的最后两个符号可以匹配 expression: NUMBER '+' expression 但我的假设是因为expression 位于规则的右侧,它不能急于求成并将 5 作为表达式评估为 NUMBER,因为使用 LALR(1),它已经知道更多符号即将到来,因此它必须等到它命中列表的末尾?
TL;DR;
有人可以详细解释一下 Bison 如何管理其解析堆栈,以及它如何使用解析器语法规则进行移位/归约?欢迎使用愚蠢/人为的例子!
【问题讨论】:
标签: recursion bison flex-lexer yacc lex