我已经使用显式堆栈以非递归方式实现了LL1解析器。
以下算法来自Dragon Book:
set zp to point to the first symbol of w;
set X to the top stack symbol;
while ( X != $ ) { /* stack is not empty */
if ( X is a )
pop the stack and advance zp;
else if ( X is a terminal )
error();
else if ( M[X, a] is an error entry )
error();
else if ( M[X,a] = X -+ Y1Y2 Yk ) {
output the production X -+ YlY2 - . Yk;
pop the stack;
push Yk, Yk-1,. . . , Yl onto the stack, with Yl on top;
set X to the top stack symbol;
}
这本书说:
解析器由一个程序控制,该程序考虑X,即符号 堆栈顶部和a,当前输入符号。如果X是 非终结者,解析器通过参考条目选择X生成 解析表IM的M [X,a]。 (可以执行附加代码 这里,例如,用于在解析树中构造节点的代码。) 否则,它检查终端X和当前之间的匹配 输入符号a。
但是我需要更多关于如何在这种方法下构造表达式树节点的信息。我有一个UnaryOperator,BinaryOperator等的节点层次结构,但不知道在哪里实例化。
然而我还没有找到任何这方面的简单例子(例如算术语言)。
答案 0 :(得分:0)
我一直在搜索相同的信息 - 如何使用LL(1)表驱动的非递归解析创建一个解析树 - 并且发现很少。
刚才我发现了这些讲义https://parasol.tamu.edu/~rwerger/Courses/434/lec7.pdf,其中提出对于每个终端或非终端,相应的解析树节点也被推入堆栈。不过,它确实看起来很浪费。以下是伪代码中提出的算法:
TOS ← 0
Stack[tos++] ← eof
Stack[tos++] ← *root node*
Stack[tos++] ← *Start Symbol*
token ← next_token()
X ← Stack[tos]
repeat
if X is a terminal or eof then
if X = token then
pop X
token ← next_token()
*pop and fill in node*
else error()
else /* X is a non-terminal */
if M[X,token] = X → Y1Y2...Yk then
pop X
*pop node for X
build node for each child and
make it a child of node for X*
push nk,Yk,nk-1,Yk-1...n1,Y1
else error()
until X = eof