我有一个简单的语法。实际上,我使用的语法更复杂,但这是说明我的问题的最小子集。
Expr ::= Value Suffix
| "(" Expr ")" Suffix
Suffix ::= "->" Expr
| "<-" Expr
| Expr
| epsilon
Value
匹配标识符、字符串、数字等。该Suffix
规则用于消除左递归。这匹配表达式,例如:
a -> b (c -> (d) (e))
也就是说,一个图a
同时出现b
和 的结果(c -> (d) (e))
,并c
出现d
和e
。我正在尝试为这些表达式生成一个抽象语法树,但我遇到了困难,因为所有运算符都可以在每一侧接受任意数量的操作数。我宁愿将生成 AST 的逻辑保留在递归下降解析方法中,因为它避免了重复提取表达式的逻辑。我目前的策略如下:
如果
Value
出现 a,将其推送到输出。如果出现
From
或To
:输出分隔符。
得到下一个
Expr
。创建一个
Link
节点。将输出中的第一组操作数弹出到 中,
Link
直到出现分隔符。擦除发现的分隔符。
将第二组操作数弹出到
Link
直到分隔符中。推
Link
到输出。
如果我在不遵循步骤 2.3-2.7 的情况下运行它,我会得到一个值和分隔符列表。对于上面引用的表达式,a -> b (c -> (d) (e))
,输出应该是:
A sep_1 B sep_2 C sep_3 D E
然后应用该To
规则将产生:
A sep_1 B sep_2 (link from C to {D, E})
随后:
(link from A to {B, (link from C to {D, E})})
需要注意的重要一点是sep_2
,对于分隔第二个 的左侧操作数至关重要的->
,没有出现,因此解析器认为表达式实际上是这样写的:
a -> (b c -> (d) (e))
为了用我当前的策略解决这个问题,我需要一种在相邻表达式之间产生分隔符的方法,但前提是当前表达式是括号中的From
or表达式。To
如果这是可能的,那么我只是没有看到它,答案应该很简单。但是,如果有更好的方法来解决这个问题,请告诉我!