假设我有一个简单的语法,例如:
X -> number
T -> X
T -> T + X
因此,例如3 + 4 + 5
将解析为:
+
/ \
+ 5
/ \
3 4
+
这具有“内置”语法的左右关联性。
它是微不足道的 LR(1),但是假设我想做一个手写的自上而下的解析。
我不能这样做,因为它是递归的,所以让我们离开它:
X -> number
T -> X T'
T' -> + X T'
T' -> e // empty
如果我现在为它编写一个解析器(伪代码):
parse_X:
if lookahead is number
return pop_lookahead
parse_T:
return (parse_X, parse_T')
parse_T':
if lookahead is +
pop_lookahead
return (parse_X, parse_T')
else
return ();
然后,当我调用parse_T
输入时,3 + 4 + 5
我会返回如下跟踪:
parse_T
(parse_X, parse_T')
(3, parse_T')
(3, (parse_X, parse_T'))
(3, (4, parse_T'))
(3, (4, (parse_X, parse_T')))
(3, (4, (5, ())))
看看解析是如何“向后”的。从这样的解析“天真地”构建的树看起来像:
+
/ \
3 +
/ \
4 5
哪个具有错误的关联性。
任何人都可以清除这个吗?一般来说,我如何编写一个手写的自上而下的解析器来保留语法中内置的关联性?