我正在尝试在空闲时间进行解析,并且我想为一个非常简单的语法实现一个 shift-reduce 解析器。我已经阅读了许多在线文章,但我仍然对如何创建解析树感到困惑。这是我想做的一个例子:
语法:
Expr -> Expr TKN_Op Expr
Expr -> TKN_Num
这是一个示例输入:
1 + 1 + 1 + 1
在标记化之后,变成:
TKN_Num TKN_Op TKN_Num TKN_Op TKN_Num TKN_Op TKN_Num
我明白那个:
- 移位意味着将第一个输入令牌压入堆栈并将其从输入中删除
- 减少意味着用语法元素替换堆栈上的一个或多个元素
所以,基本上,这应该发生:
Step 1:
Stack:
Input: TKN_Num TKN_Op TKN_Num TKN_Op TKN_Num TKN_Op TKN_Num
What: Stack is empty. Shift.
Step 2:
Stack: TKN_Num
Input: TKN_Op TKN_Num TKN_Op TKN_Num TKN_Op TKN_Num
What: TKN_Num can be reduced to Expr. Reduce.
Step 3:
Stack: Expr
Input: TKN_Op TKN_Num TKN_Op TKN_Num TKN_Op TKN_Num
What: Cannot reduce. Shift.
Step 4:
Stack: Expr TKN_Op
Input: TKN_Num TKN_Op TKN_Num TKN_Op TKN_Num
What: Cannot reduce. Shift.
Step 5:
Stack: Expr TKN_Op TKN_Num
Input: TKN_Op TKN_Num TKN_Op TKN_Num
What: TKN_Num can be reduced to Expr. Reduce.
// What should I check for reduction?
// Should I try to reduce incrementally using
// only the top of the stack first,
// then adding more stack elements if I couldn't
// reduce the top alone?
Step 6:
Stack: Expr TKN_Op Expr
Input: TKN_Op TKN_Num TKN_Op TKN_Num
What: Expr TKN_Op Expr can be reduced to Expr. Reduce.
Step 7:
Stack: Expr
Input: TKN_Op TKN_Num TKN_Op TKN_Num
What: ...
// And so on...
除了“要减少什么?” 怀疑,我不知道如何正确构建解析树。树应该看起来像这样:
1 + o
|
1 + o
|
1 + 1
我应该在减少时创建一个新节点吗?
什么时候应该将子节点添加到新创建的节点/什么时候应该创建一个新的根节点?