我正在尝试使用柠檬解析器生成器生成解析器表,但运行.out
时生成的lemon grammar.y
文件仅包含自动机的状态。
有没有办法同时获取非终端的goto表,而不仅仅是自动机的状态? 或者这只能通过阅读生成的代码来完成? 还有其他工具可以生成动作和转到表吗?
PS:
简单语法的.out
文件(由lemon生成)如下所示:
State 0:
start ::= * e
e ::= * e PLUS t
e ::= * t
t ::= * t MUL f
t ::= * f
f ::= * LPAR e RPAR
f ::= * ID
LPAR shift 1
ID shift 4
start accept
e shift 11
t shift 6
f shift 5
State 1:
e ::= * e PLUS t
e ::= * t
t ::= * t MUL f
t ::= * f
f ::= * LPAR e RPAR
f ::= LPAR * e RPAR
f ::= * ID
LPAR shift 1
ID shift 4
e shift 10
t shift 6
f shift 5
State 2:
e ::= e PLUS * t
t ::= * t MUL f
t ::= * f
f ::= * LPAR e RPAR
f ::= * ID
LPAR shift 1
ID shift 4
t shift 9
f shift 5
State 3:
t ::= t MUL * f
f ::= * LPAR e RPAR
f ::= * ID
LPAR shift 1
ID shift 4
f shift 8
State 4:
(6) f ::= ID *
$ reduce 6 f ::= ID
PLUS reduce 6 f ::= ID
MUL reduce 6 f ::= ID
RPAR reduce 6 f ::= ID
State 5:
(4) t ::= f *
$ reduce 4 t ::= f
PLUS reduce 4 t ::= f
MUL reduce 4 t ::= f
RPAR reduce 4 t ::= f
State 6:
(2) e ::= t *
t ::= t * MUL f
$ reduce 2 e ::= t
PLUS reduce 2 e ::= t
MUL shift 3
RPAR reduce 2 e ::= t
State 7:
(5) f ::= LPAR e RPAR *
$ reduce 5 f ::= LPAR e RPAR
PLUS reduce 5 f ::= LPAR e RPAR
MUL reduce 5 f ::= LPAR e RPAR
RPAR reduce 5 f ::= LPAR e RPAR
State 8:
(3) t ::= t MUL f *
$ reduce 3 t ::= t MUL f
PLUS reduce 3 t ::= t MUL f
MUL reduce 3 t ::= t MUL f
RPAR reduce 3 t ::= t MUL f
State 9:
(1) e ::= e PLUS t *
t ::= t * MUL f
$ reduce 1 e ::= e PLUS t
PLUS reduce 1 e ::= e PLUS t
MUL shift 3
RPAR reduce 1 e ::= e PLUS t
State 10:
e ::= e * PLUS t
f ::= LPAR e * RPAR
PLUS shift 2
RPAR shift 7
State 11:
(0) start ::= e *
e ::= e * PLUS t
$ reduce 0 start ::= e
PLUS shift 2
----------------------------------------------------
Symbols:
0: $:
1: PLUS
2: MUL
3: LPAR
4: RPAR
5: ID
6: error:
7: start: LPAR ID
8: e: LPAR ID
9: t: LPAR ID
10: f: LPAR ID
答案 0 :(得分:3)
Lemon将动作表和goto表输出到一个块中。 goto函数看起来像shift操作,除了前瞻是非终端而不是终端。
所以如果我们采取国家0:
LPAR shift 1
ID shift 4
start accept
e shift 11
t shift 6
f shift 5
前两行分别是读取LPAR和ID的操作。其余行是goto函数,当reduce操作通过弹出堆栈显示此状态时使用。 (与传统的LR机器不同,在Lemon中,accept
动作在goto表中,而不是在输入结束伪终端的动作表中。)
虽然LR解析器的大多数描述都区分了动作表和goto表,但是" shift"之间的区别很小。行动和"转到"减少行动的一部分。这两个都将当前状态编号和符号推送到解析器堆栈。不同之处在于减少动作(例如reduce 6
,这意味着"减少使用生产6" - 它与状态6无关)首先弹出指示的右侧生成离开堆栈并在执行shift / goto之前将当前状态设置为堆栈顶部的新显示状态。 (另一个区别是,在移位操作之后,有必要读取新的超前令牌,而reduce操作不会消耗输入。)