语法分析
(2)
--------
自顶向下的语法分析
(2)
语法分析程序除了采用递归的预测分析方法外, 还有非递归的预测分析方法, 也就是LL(1)分析. 与递归的预测分析方法类似, LL(1)分析也是使用first集合follow集合以及select集合为制导构建程序, 但是它显式的维护一个分析栈, 通过栈来进行语法分析.
一. LL(1)模型及过程.
如图:
在该模型中分析程序使用栈顶元素和输入的记号作为输入, 通过查询分析表M来计算状态边产生输出.
具体过程是这样的(参看龙书):
1. 如果栈顶元素X和当前输入记号a相当且等于#, 既 X = a = #, 则分析成功并停止.
2. 如果X = a != # 则X和a匹配成功, 弹出X 并获得下一个输入记号.
3. 如果X是非终结符, 通过分析表M查询产生式M[X, a], 如果M[X, a]是一个X的产生式如: M[X, a] = X-> UVW, 则弹出X将WVU(产生式的反序)压入展中. 否则出现了语法错误.
在进行分析之前必须先初始化分析表M和栈, 在初始化栈时首先将结束符#压入展中,再把文法开始符压入栈中.
其中分析表M是这个程序中最关键的部分, 但是分析表M的建立非常容易, 它就是前面提到的select集合.
如下:
select(PROGRAM-> STMT-SEQUENCE) = {if, repeat, identifier, read, write}
select(STMT-SEQUENCE-> STATEMENT STMT-SEQUENCE') =
{if, repeat, identifier, read, write}
select(STMT-SEQUENCE'-> ; STATEMENT STMT-SEQUENCE') = {;}
select(STMT-SEQUENCE'-> $
) = {#, else, end, until}
select(STATEMENT-> IF-STMT) = {if}
select(STATEMENT-> REPEAT-STMT) = {repeat}
select(STATEMENT-> ASSIGN-STMT) = {identifier}
select(STATEMENT-> READ-STMT) = {read}
select(STATEMENT-> WRITE-STMT) = {write}
select(IF-STMT-> if EXP then STMT-SEQUENCE ELSE-STMT end) = {if}
select(ELSE-STMT-> else STMT-SEQUENCE) = {else}
select(ELSE-STMT-> $
) = {end}
select(REPEAT-STMT-> repeat STMT-SEQUENCE until EXP) = {repeat}
select(ASSIGN-STMT-> identifier := EXP) = {identifier}
select(READ-STMT-> read identifier) = {read}
select(WRITE-STMT-> write EXP) = {write}
select(EXP-> SIMPLE-EXP EXP') = {(, number, identifier}
select(EXP'-> COMPARISON-OP SIMPLE-EXP) = {<, =}
select(EXP'-> $
) = {then, ), ;, #, else, end, until}
select(COMPARISON-OP-> <) = {<}
select(COMPARISON-OP-> =) = {=}
select(SIMPLE-EXP-> TERM SIMPLE-EXP') = {(, number, identifier}
select(SIMPLE-EXP'-> ADDOP TERM SIMPLE-EXP') = {+, -}
select(SIMPLE-EXP'-> $
) = {<, =, then, ), ;, #, else, end, until}
select(ADDOP-> +) = {+}
select(ADDOP-> -) = {-}
select(TERM-> FACTOR TERM') = {(, number, identifier}
select(TERM'-> MULOP FACTOR TERM') = {*, /}
select(TERM'-> $
) = {+, -, <, =, then, ), ;, #, else, end, until}
select(MULOP-> *) = {*}
select(MULOP-> /) = {/}
select(FACTOR-> (EXP)) = {(}
select(FACTOR-> number) = {number}
select(FACTOR-> identifier) = {identifier}
其中M[X, a]即使其中的一条产生式, 例如X 为
STMT-SEQUENCE, a为
read时
M[X, a]就为
select(STMT-SEQUENCE-> STATEMENT STMT-SEQUENCE') =
{if, repeat, identifier, read, write}
这是就可以将非终结符
STMT-SEQUENCE替换成
STATEMENT STMT-SEQUENCE'
根据TINY 的语法有一个小例子:
sample.tny(<<编译原理与实践>>中的例子
{
Sample program in TINY language -
computes factorial
}
read x ; { input an integer }
if x<0 then
fact := 1;
repeat
fact := fact * x;
x := x - 1;
y := y + 3;
z := z + 4;
w := w + 7
until x = 0;
write fact { output factorial of x }
else
if (x+3) = 100 then
read x;
write x+2*128
else
read y;
write x*128 + 2
end
end
{
The end of sample.tny
}
根据上面的过程和分析表M(既select集合)可以得到分析过程中栈的情况(自左向右是从栈底到栈顶, 其中有换行的地方);
# PROGRAM
# STMT-SEQUENCE
# STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' READ-STMT
# STMT-SEQUENCE' identifier read
# STMT-SEQUENCE' identifier
# STMT-SEQUENCE'
# STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' IF-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP if
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP COMPARSION-OP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP <
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' ASSIGN-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP := identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP :=
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' REPEAT-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE repeat
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' ASSIGN-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP := identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP :=
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR MULOP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR *
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' ASSIGN-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP := identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP :=
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM ADDOP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM -
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' ASSIGN-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP := identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP :=
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM ADDOP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM +
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' ASSIGN-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP := identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP :=
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM ADDOP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM +
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' ASSIGN-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP := identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP :=
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM ADDOP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM +
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP until
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP COMPARSION-OP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP =
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' WRITE-STMT
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP write
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE'
# STMT-SEQUENCE' end ELSE-STMT
# STMT-SEQUENCE' end STMT-SEQUENCE else
# STMT-SEQUENCE' end STMT-SEQUENCE
# STMT-SEQUENCE' end STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end STMT-SEQUENCE' IF-STMT
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP if
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP (
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM ADDOP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM +
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' ) EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM' )
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP COMPARSION-OP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP =
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE then
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' READ-STMT
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' identifier read
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' identifier
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' WRITE-STMT
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP write
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM ADDOP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM +
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR MULOP
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR *
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT STMT-SEQUENCE'
# STMT-SEQUENCE' end STMT-SEQUENCE' end ELSE-STMT
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE else
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' READ-STMT
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' identifier read
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' identifier
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE'
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' STATEMENT ;
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' STATEMENT
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' WRITE-STMT
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP write
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' identifier
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR MULOP
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR *
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM ADDOP
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM +
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' FACTOR
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM' number
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP' TERM'
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP' SIMPLE-EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE' EXP'
# STMT-SEQUENCE' end STMT-SEQUENCE' end STMT-SEQUENCE'
# STMT-SEQUENCE' end STMT-SEQUENCE' end
# STMT-SEQUENCE' end STMT-SEQUENCE'
# STMT-SEQUENCE' end
# STMT-SEQUENCE'
#
二. 错误处理
这里的错误处理算法很简单, 主要是使用follow集合为同步集合将它添加到分析表M
中并设置标志为SYNCH(参考龙书).
具体算法是, 当M[X, a]为空, 则跳过当前输入记号a, 当M[X, a]为SYNCH则弹出当前栈定符号X.
三. 在LL(1)分析中构造语法树.
龙书中并没有介绍在LL(1)分析程序中构造语法树, 在<<编译原理与实践>>的4.2.4节中只是稍微提到了一点, 非常简单, 但是它并不能使用TINY语言的LL(1)分析程序. 所以我将这个算法扩展成TINY的LL(1)分析适用的算法(参考<<编译原理与实践>>).
LL(1)中构造语法树的主要困难在于当使用分析表M中的产生式替换非终结符X的时候是这个产生式匹配的开始, 但是我们并不知道什么时候这个产生式匹配结束, 可是只有当产生式匹配结束时我们才能收集到该产生式的所有的信息,才可以生成语法树结点. <<编译原理与实践>>中介绍了一种方法. 在产生式的后面加上一个”动作标记”, 这个”动作标记”来指示该产生式匹配完毕, 这是就可以生成语法树结点了. 但是对于TINY来说这个算法还不完整. 因为对于所有的产生式都使用一种”动作标记”, TINY中有很多产生式, 这样会产生混淆, 分不清楚哪个”动作标记”是哪个产生式的结束标记. 所以对于TINY中的每一个非终结符都添加相应的结束标记. 光使用结束标记还不够, 还要使用开始标记, 因为LL(1)中构造语法树时要使用栈, 但结点有多个子结点, 或STMT-SEQUENCE中连续的STATEMENT时无法判断栈中有多少是有效的, 尤其是这种情况嵌套发生时更是难以区分.
依据以上原因, 具体算法如下:
1.在select集合中为每一个非终结符天结开始标记和结束标记, 消除左递归和提取公因之时
新增加的非终结符除外.
添加后的select结合如下(原select结合间语法分析1):
select(PROGRAM->
BEGIN-STMT-SEQUENCE STMT-SEQUENCE END-STMT-SEQUENCE) =
{if, repeat, identifier, read, write}
select(STMT-SEQUENCE-> BEGIN-STATEMENT STATEMENT END-STATEMENT STMT-SEQUENCE') =
{if, repeat, identifier, read, write}
select(STMT-SEQUENCE'->
; BEGIN-STATEMENT STATEMENT END-STATEMENT STMT-SEQUENCE') =
{;}
select(STMT-SEQUENCE'-> $) = {#, else, end, until}
select(STATEMENT-> BEGIN-IF-STMT IF-STMT END-IF-STMT) = {if}
select(STATEMENT-> BEGIN-REPEAT-STMT REPEAT-STMT END-REPEAT-STMT) =
{repeat}
select(STATEMENT-> BEGIN-ASSIGN-STMT ASSIGN-STMT END-ASSIGN-STMT) =
{identifier}
select(STATEMENT-> BEGIN-READ-STMT READ-STMT END-READ-STMT) = {read}
select(STATEMENT-> BEGIN-WRITE-STMT WRITE-STMT END-WRITE-STMT) =
{write}
select(IF-STMT->
if BEGIN-EXP EXP END-EXP
then BEGIN-STMT-SEQUENCE STMT-SEQUENCE END-STMT-SEQUENCE
BEGIN-ELSE-STMT ELSE-STMT END-ELSE-STMT end) = {if}
select(ELSE-STMT->
else BEGIN-STMT-SEQUENCE STMT-SEQUENCE END-STMT-SEQUENCE) =
{else}
select(ELSE-STMT-> $) = {end}
select(REPEAT-STMT->
repeat BEGIN-STMT-SEQUENCE STMT-SEQUENCE END-STMT-SEQUENCE
until BEGIN-EXP EXP END-EXP) = {repeat}
select(ASSIGN-STMT-> identifier := BEGIN-EXP EXP END-EXP) = {identifier}
select(READ-STMT-> read identifier) = {read}
select(WRITE-STMT-> write BEGIN-EXP EXP END-EXP) = {write}
select(EXP-> BEGIN-SIMPLE-EXP SIMPLE-EXP END-SIMPLE-EXP EXP') =
{(, number, identifier}
select(EXP'->
BEGIN-COMPARISON-OP COMPARISON-OP END-COMPARISON-OP
BEGIN-SIMPLE-EXP SIMPLE-EXP END-SIMPLE-EXP) = {<, =}
select(EXP'-> $) = {then, ), ;, #, else, end, until}
select(COMPARISON-OP-> <) = {<}
select(COMPARISON-OP-> =) = {=}
select(SIMPLE-EXP-> BEGIN-TERM TERM END-TERM SIMPLE-EXP') =
{(, number, identifier}
select(SIMPLE-EXP'->
BEGIN-ADDOP ADDOP END-ADDOP BEGIN-TERM TERM END-TERM
SIMPLE-EXP') = {+, -}
select(SIMPLE-EXP'-> $) = {<, =, then, ), ;, #, else, end, until}
select(ADDOP-> +) = {+}
select(ADDOP-> -) = {-}
select(TERM-> BEGIN-FACTOR FACTOR END-FACTOR TERM') =
{(, number, identifier}
select(TERM'->
BEGIN-MULOP MULOP END-MULOP
BEGIN-FACTOR FACTOR END-FACTOR TERM') = {*, /}
select(TERM'-> $) = {+, -, <, =, then, ), ;, #, else, end, until}
select(MULOP-> *) = {*}
select(MULOP-> /) = {/}
select(FACTOR-> (BEGIN-EXP EXP END-EXP)) = {(}
select(FACTOR-> number) = {number}
select(FACTOR-> identifier) = {identifier}
2. 除了分析栈外还需要四个栈:
child_stack: 保存当前结点以及其子结点的栈.
parent_stack: 保存当前结点的上一级结点的栈.
id_num_stack: 在解析运算符时保存id和number结点的栈.
operator_stack: 在解析运算符时保存运算符结点的栈.
此外在分析过程中还要为每一个产生式生成一个标记结点放在child_stack中, 用于标记该产生式的开始.
3. 分析过程中生成语法树具体过程:
1) 当分析栈顶和当前记号匹配且为文件结束符号时, 弹出child_stack中的结点(此时栈中只有一个结点, 其他三个栈为空), 这个结点即为语法树的根结点.
2) 如果分析栈顶和当前记号匹配且不为文件结束符号时, 如果分析栈顶为id或number时则生成相应的结点, 并压入child_stack中, 如果为id和number以外的终结符则生成相应的结点, 并压入parent_stack中, 弹出栈顶符号, 并获得下一个记号.
3) 当分析栈顶非终结符为普通非终结符时(不是开始标记也不是结束标记), 查找分析表M并替换栈顶非终结符, 获得下一个记号.
4) 当分析栈顶的非终结符为开始标记时(如
BEGIN-EXP)则生成一个与之相关的标记结点压入child_stack中, 弹出分析栈中的开始标记.
5) 当分析栈顶的非终结符为结束标记(如
END-EXP)则依据后面语法树结点生成规则处理.
循环执行该算法直到处理结束.
语法树结点生成规则:
对于TINY语法来说通过不同的产生式生成语法树结点的方法也不同, 这里介绍的规则是当分析栈顶元素为结束标记时各个产生式生成语法树结点的方法:
a>
END-STMT-SEQUENCE:
表示STMT-SEQUENCE产生式结束, 这个产生式是用来描述单个语句之间的关系的, 在语法树中, 语句与语句之间是并列的关系如:
read x;
write x+23
在语法树中因该表示:
遇到
END-STMT-SEQUENCE时栈child_stack中的情况和处理后的情况如图:
将child_stack中stmt-sequence标记结点(前面4中生成的, 以下同)前面的所有语句弹出, 并连接(都是并列语句的关系), 其中语句A时第一条语句, 向上依次是第二条, 第三条等等.
将stmt-sequence标记结点弹出, 然后将语句A(语句序列开始的语句)压入栈中.
b>
END-STATEMENT
STATEMENT 用来描述所用的语句, 它分为许多具体的语句.
当遇到
BEGIN-STATEMENT时child_stack栈中的情况和处理后的情况如图:
处理只是将statement标记结点从child_stack栈中弹出. 首先弹出语句A然后弹出statement标记结点, 在压入语句A.
c>
END-IF-STMT
表示if-stmt语句的结束, if语句可能有两个或者三个子结点(取决与是否有else语句), 遇到
END-IF-STMT时child_stack栈中的情况如图:
处理时使用id_num_stack作为临时栈, 将child_stack中if-stmt标记结点前面的结点依次判处并压入到id_num_stack中, 然后将if-stmt标记结点弹出如图:
然后弹出parent_stack中的if结点(前面2中在匹配if关键字时生成的结点), 依次弹出
id_num_stack中的结点作为if结点的子结点, 并将if结点压入child_stack栈中如图:
d>
END-ELSE-STMT
else语句只是if语句的一个子结点, 对else不需要太多的处理, 只是去掉else标记结点就可以了如图:
e>
END-REPEAT-STMT
repeat结点有两个子结点, repeat和until间的stmt-sequence和until后面的exp.
当遇到
END-REPEAT-STMT时栈中的情况和处理后栈中的情况如图:
处理的过程是将repeat结点从parent_stack栈中弹出, 然后将child_stack中的两个结点依次
弹出, 注意在child_stack中exp结点在上面, stmt-sequence结点在下面. 然后弹出repeat-stmt结点, 再将repeat结点压入child_stack中.结果如图:
f>
END-ASSIGN-STMT
assign-stmt的形式如x := 1 中x是作为assign结点的一个属性存在的, 所以assign结点只有一个id的子结点. 但是在LL(1)分析中按照上面的规则2)我们会为x和1都生成结点并保存在child_stack中, 但在匹配:= 记号时生成assign结点并保存在parent_stack中, 但是在这时assign结点的属性并不是x, 当遇到
END-ASSIGN-STMT时栈中的情况:
处理过程是将assign结点从parent_stack栈弹出, 然后将NUM(1)结点从child_stack栈弹出并作为assign结点的子结点, 然后将ID(x)的属性x复制给assign结点, 弹出ID(x)和
assign-stmt标记结点, 将assign结点压入到child_stack中. 结构如图:
g>
END-READ-STMT
read语句如 read x没有子结点, x作为read结点的一个属性存在, 所以read结点的产生过程和处理过程与assign结点相似, 当遇到
END-READ-STMT时栈中的情况如图:
处理过程先将read结点从parent_stack中弹出, 将child_stack中ID(x)属性x复制到read结点, 然后弹出ID(x)结点和read-stmt标记结点, 再将read结点压入child_stack中, 结果如图:
h>
END-WRITE-STMT
write语句有一个子结点, 这个子结点是表达式EXP, 当遇到
END-WRITE-STMT时栈中的情况如图:
处理过程将write结点从parent_stack中弹出, 弹出child_stack中的EXP作为write结点的子结点, 然后弹出write-stmt标记结点, 再将write结点压入child_stack中, 结果如图:
i>
END-EXP
EXP是对表达式的描述, 具体的说, EXP负责描述关系表达式和单个标识符或数字常量.如x < 0 或 y 或 78或其他结点等. 所以EXP最后的结果可能是一个关系运算符结点下面
有两个子结点, 或者是单一一个其他的结点.当parent_stack栈顶为关系运算符结点时如图:
处理过程, 将关系运算符结点从parent_stack中弹出, 依次将结点B, 结点A弹出child_stack,
作为关系运算符的第二个子结点和第一个字结点, 弹出exp标记结点, 再将关系运算符压入到child_stack中, 结果如图:
如果parent_stack的栈顶不为关系运算符结点时表示EXP表示单一的结点, 遇到
END-EXP时栈中的情况如图:
处理过程只是将结点A从child_stack中弹出, 再弹出exp标记结点, 然后将结点A再压入栈child_stack中.
j>
END-COMPARISON-OP
comparison-op只是描述关系运算符, 不是关系表达式, 但就关系运算符来讲它没有任何子结点, 也不会产生什么动作, 所以遇到
END-COMPARISON-OP只是将前面child_stack中的comparison-op标志记号删除, 如图:
k>
END-SIMPLE-EXP
simple-exp是描述加减法关系的产生式, 但是它与exp描述的关系运算不同, exp不能出现连续的关系运算如 a < b = c, 但是可以连续的加减如a+b-c等, 但是解析simple-exp是返回的结点必须是最后一个执行的运算符的结点, 例如a+b-c最后的结点就是减号结点. 所以我们使用了两个辅助的栈id_num_stack和operator_stack, 当遇到
END-SIMPLE-EXP时栈的情况以a+b-c为例:
处理过程是将simple-exp标记结点之前的结点弹出并压入id_num_stack中, 再将parent_stack中加减运算符结点弹出并压入operator_stack中, 弹出的加减运算符数量是有限制的并不是所有的加减运算符都要弹出, 运算符数量是操作数数量减一. 然后弹出simple-exp标记结点. 然后弹出operator_stack中的栈顶运算符结点, 弹出id_num_stack中两个操作数, 作为运算符结点的第一子结点和第二子结点, 然后把运算符结点压入到id_num_stack中, 循环执行, 直到operator_stack空位置, 这是id_num_stack中必定只剩下一个结点, 将这个结点弹出并压入到child_stack中.结果如图:
l>
END-ADDOP
addop 只表示加减运算符, 不表示加减表达式, 所以遇到
END-ADDOP时栈中并没有数据结点, 只需要将addop标记结点弹出child_stack就行了, 这与
END-COMPARISON-OP的处理相同.
m>
END-TERM
term表示乘除关系的表达式, 处理与
END-SIMPLE-EXP相同.
n>
END-MULOP
处理与
END-ADDOP和
END-COMPARISON-OP相同.
o>
END-FACTOR
factor表示常量, 标识符或括号表达式, factor只是表示单一节点, 所以遇到
END-FACTOR时将节点A弹出, 再将factor标记节点弹出, 然后再将节点A压入栈中, 处
理前栈中的情况和处理后的情况如图:
以上就是在LL(1)时生成语法树的全部过程.
四: LL(1)分析程序代码
包括了LL(1)分析, 错误处理和生成语法树.
TreeNode* parse_ll1(void)
{
TokenType token;
int i = 0;
int count = 0;
AnalyseNode* node = NULL;
TreeNode* tree = NULL;
TreeNode* temp = NULL;
/* init the token stack and analyse table*/
init_analyse_table();
init_stack();
token = get_token();
for(;;)
{
#ifdef TRACE_PARSE_STACE
trace_stack();
trace_tree_node_stack();
print_token(token, token_string);
#endif
switch(stack_top())
{
/* begin of non end symbol */
case BEGIN_STMT_SEQUENCE:
temp = new_oper_node(KIND_STMT_SEQUENCE);
child_stack_push(temp);
pop();
break;
case BEGIN_STATEMENT:
temp = new_oper_node(KIND_STATEMENT);
child_stack_push(temp);
pop();
break;
case BEGIN_IF_STMT:
temp = new_oper_node(KIND_IF_STMT);
child_stack_push(temp);
pop();
break;
case BEGIN_ELSE_STMT:
temp = new_oper_node(KIND_ELSE_STMT);
child_stack_push(temp);
pop();
break;
case BEGIN_REPEAT_STMT:
temp = new_oper_node(KIND_REPEAT_STMT);
child_stack_push(temp);
pop();
break;
case BEGIN_ASSIGN_STMT:
temp = new_oper_node(KIND_ASSIGN_STMT);
child_stack_push(temp);
pop();
break;
case BEGIN_READ_STMT:
temp = new_oper_node(KIND_READ_STMT);
child_stack_push(temp);
pop();
break;
case BEGIN_WRITE_STMT:
temp = new_oper_node(KIND_WRITE_STMT);
child_stack_push(temp);
pop();
break;
case BEGIN_EXP:
temp = new_oper_node(KIND_EXP_STMT);
child_stack_push(temp);
pop();
break;
case BEGIN_SIMPLE_EXP:
temp = new_oper_node(KIND_SIMPLE_EXP);
child_stack_push(temp);
pop();
break;
case BEGIN_COMPARISON_OP:
temp = new_oper_node(KIND_COMPARISON_OP);
child_stack_push(temp);
pop();
break;
case BEGIN_TERM:
temp = new_oper_node(KIND_TERM);
child_stack_push(temp);
pop();
break;
case BEGIN_ADDOP:
temp = new_oper_node(KIND_ADDOP);
child_stack_push(temp);
pop();
break;
case BEGIN_MULOP:
temp = new_oper_node(KIND_MULOP);
child_stack_push(temp);
pop();
break;
case BEGIN_FACTOR:
temp = new_oper_node(KIND_FACTOR);
child_stack_push(temp);
pop();
break;
/* end of non end symbol */
case END_STMT_SEQUENCE:
temp = NULL;
while((child_stack_top()->node_kind != KIND_OPERATOR) ||
(child_stack_top()->kind.oper != KIND_STMT_SEQUENCE))
{
child_stack_top()->sibling = temp;
temp = child_stack_pop();
}
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
case END_STATEMENT:
temp = child_stack_pop();
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_STATEMENT));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
case END_IF_STMT:
assert((parent_stack_top()->node_kind == KIND_STMT) &&
(parent_stack_top()->kind.stmt == KIND_IF));
temp = parent_stack_pop();
count = 0;
while((child_stack_top()->node_kind != KIND_OPERATOR) ||
(child_stack_top()->kind.oper != KIND_IF_STMT))
{
count++;
id_num_stack_push(child_stack_pop());
}
destroy_tree_node(child_stack_pop());
assert((count == 2) || (count == 3));
for(i = 0; i < count; i++)
temp->child[i] = id_num_stack_pop();
assert(is_id_num_stack_empty());
child_stack_push(temp);
pop();
break;
case END_ELSE_STMT:
if((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_ELSE_STMT))
{
destroy_tree_node(child_stack_pop());
}
else
{
temp = child_stack_pop();
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_ELSE_STMT));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
}
pop();
break;
case END_REPEAT_STMT:
assert((parent_stack_top()->node_kind == KIND_STMT) &&
(parent_stack_top()->kind.stmt == KIND_REPEAT));
temp = parent_stack_pop();
temp->child[1] = child_stack_pop();
temp->child[0] = child_stack_pop();
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_REPEAT_STMT));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
case END_ASSIGN_STMT:
assert((parent_stack_top()->node_kind == KIND_STMT) &&
(parent_stack_top()->kind.stmt == KIND_ASSIGN));
temp = parent_stack_pop();
temp->child[0] = child_stack_pop();
temp->attr.name = copy_string(child_stack_top()->attr.name);
destroy_tree_node(child_stack_pop());
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_ASSIGN_STMT));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
case END_READ_STMT:
assert((parent_stack_top()->node_kind == KIND_STMT) &&
(parent_stack_top()->kind.stmt == KIND_READ));
temp = parent_stack_pop();
temp->attr.name = copy_string(child_stack_top()->attr.name);
destroy_tree_node(child_stack_pop());
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_READ_STMT));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
case END_WRITE_STMT:
assert((parent_stack_top()->node_kind == KIND_STMT) &&
(parent_stack_top()->kind.stmt == KIND_WRITE));
temp = parent_stack_pop();
temp->child[0] = child_stack_pop();
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_WRITE_STMT));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
case END_EXP:
if(((parent_stack_top()->node_kind == KIND_EXP) &&
(parent_stack_top()->kind.exp == KIND_OP) &&
(parent_stack_top()->attr.op == LT)) ||
((parent_stack_top()->node_kind == KIND_EXP) &&
(parent_stack_top()->kind.exp == KIND_OP) &&
(parent_stack_top()->attr.op == EQ)))
{
temp = parent_stack_pop();
temp->child[1] = child_stack_pop();
temp->child[0] = child_stack_pop();
}
else
{
temp = child_stack_pop();
}
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_EXP_STMT));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
case END_SIMPLE_EXP:
count = 0;
while((child_stack_top()->node_kind != KIND_OPERATOR) ||
(child_stack_top()->kind.oper != KIND_SIMPLE_EXP))
{
count++;
id_num_stack_push(child_stack_pop());
}
destroy_tree_node(child_stack_pop());
for(i = 0; i < count-1; i++)
{
assert(((parent_stack_top()->node_kind == KIND_EXP) &&
(parent_stack_top()->kind.exp == KIND_OP) &&
(parent_stack_top()->attr.op == PLUS)) ||
((parent_stack_top()->node_kind == KIND_EXP) &&
(parent_stack_top()->kind.exp == KIND_OP) &&
(parent_stack_top()->attr.op == MINUS)));
operator_stack_push(parent_stack_pop());
}
while(is_operator_stack_empty() == FALSE)
{
temp = operator_stack_pop();
temp->child[0] = id_num_stack_pop();
temp->child[1] = id_num_stack_pop();
id_num_stack_push(temp);
}
temp = id_num_stack_pop();
assert(is_operator_stack_empty() && is_id_num_stack_empty());
child_stack_push(temp);
pop();
break;
case END_COMPARISON_OP:
/* temp = child_stack_pop(); */
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_COMPARISON_OP));
destroy_tree_node(child_stack_pop());
/* child_stack_push(temp); */
pop();
break;
case END_TERM:
count = 0;
while((child_stack_top()->node_kind != KIND_OPERATOR) ||
(child_stack_top()->kind.oper != KIND_TERM))
{
count++;
id_num_stack_push(child_stack_pop());
}
destroy_tree_node(child_stack_pop());
for(i = 0; i < count-1; i++)
{
assert(((parent_stack_top()->node_kind == KIND_EXP) &&
(parent_stack_top()->kind.exp == KIND_OP) &&
(parent_stack_top()->attr.op == MULT)) ||
((parent_stack_top()->node_kind == KIND_EXP) &&
(parent_stack_top()->kind.exp == KIND_OP) &&
(parent_stack_top()->attr.op == DIV)));
operator_stack_push(parent_stack_pop());
}
while(is_operator_stack_empty() == FALSE)
{
temp = operator_stack_pop();
temp->child[0] = id_num_stack_pop();
temp->child[1] = id_num_stack_pop();
id_num_stack_push(temp);
}
temp = id_num_stack_pop();
assert(is_operator_stack_empty() && is_id_num_stack_empty());
child_stack_push(temp);
pop();
break;
case END_ADDOP:
/* temp = child_stack_pop(); */
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_ADDOP));
destroy_tree_node(child_stack_pop());
/* child_stack_push(temp); */
pop();
break;
case END_MULOP:
/* temp = child_stack_pop(); */
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_MULOP));
destroy_tree_node(child_stack_pop());
/* child_stack_push(temp); */
pop();
break;
case END_FACTOR:
temp = child_stack_pop();
assert((child_stack_top()->node_kind == KIND_OPERATOR) &&
(child_stack_top()->kind.oper == KIND_FACTOR));
destroy_tree_node(child_stack_pop());
child_stack_push(temp);
pop();
break;
default:
if(stack_top() == token) /* end symbol */
{
if(token == END_FILE)
{
destroy_analyse_table();
tree = child_stack_pop();
assert(is_child_stack_empty() &&
is_parent_stack_empty() &&
is_id_num_stack_empty() &&
is_operator_stack_empty());
return tree;
}
else
{
switch(token)
{
/* new stmt and exp node */
case KEY_IF:
temp = new_stmt_node(KIND_IF);
parent_stack_push(temp);
break;
case KEY_REPEAT:
temp = new_stmt_node(KIND_REPEAT);
parent_stack_push(temp);
break;
case ASSIGN:
temp = new_stmt_node(KIND_ASSIGN);
parent_stack_push(temp);
break;
case KEY_READ:
temp = new_stmt_node(KIND_READ);
parent_stack_push(temp);
break;
case KEY_WRITE:
temp = new_stmt_node(KIND_WRITE);
parent_stack_push(temp);
break;
case LT:
case EQ:
case PLUS:
case MINUS:
case MULT:
case DIV:
temp = new_exp_node(KIND_OP);
temp->attr.op = token;
parent_stack_push(temp);
break;
/* new id and number node */
case ID:
temp = new_exp_node(KIND_ID);
temp->attr.name = copy_string(token_string);
child_stack_push(temp);
break;
case NUM:
temp = new_exp_node(KIND_CONST);
temp->attr.val = atoi(token_string);
child_stack_push(temp);
break;
default:
break;
}
pop();
token = get_token();
}
}
else /* non end symbol */
{
if((node = search_analyse_table(stack_top(), token)) == NULL)
{
fprintf(stderr, "syntax error at line %d :"
" unwanted symbol: %s!/n",
line_no, token_string);
token = get_token();
}
else
{
if(node->node[0] == SYNCH)
{
fprintf(stderr, "syntax error at line %d :"
" wanted some symbol!/n",
line_no);
pop();
}
else
{
pop();
if(node->node[0] != EMPTY)
for(i = node->node_count-1; i >= 0; i--)
push(node->node[i]);
}
}
}
break;
}
}
}