
[英]How do I construct abstract syntax trees from a list of tokens using a context-free grammar?
[英]Understanding ETF grammar and abstract syntax trees
这是一个粗心的问题。 没有理由先验为什么ETF语法需要对应于任何特定的AST。 的确,对于基于EFT语法的解析器而言,构建具有常规优先级规则的AST最简单。 而且确实如此,这样的左递归语法使在AST中实现左联想运算最容易。
但是,这些大假设是应该明确指出问题的前提。 要完全指定问题,您需要提供一个生成AST的属性语法 ,而不仅仅是一个简单的语法。
属性语法将指定AST节点的构建方式:
E_a -> E_b + T { E_a.ast = makeNode('+', E_b.ast, T.ast) }
E -> T { E.ast = T.ast }
...
F -> i { F.ast = makeLeaf(i) }
因此,如果我们假设典型的属性文法,那么EFT文法的结构就意味着运算的优先级。
语法“顶部”的运算符(直接从起始符号得出)对应于最低优先级。 您可以这样想:
E -> E + T | T
扩展到一个或多个列表T
相隔ERMS +
运算符。
E -> T + ... + T
这意味着属性语法构造了术语( T
s)的左偏树。 “在T
s内”发生的所有事情的优先级都更高。 这些东西“绑定在一起”,而不考虑周围的+
。
相应的AST如下所示:
+
| \
+ T
| \
+ T
|
.
.
.
+
| \
T T
换句话说,该表达式是前面项(根下的左子树)加到最后一项(右子树)的总和。 连续添加从左到右。 这称为左关联操作。 某些操作(例如,通常是幂运算)使树以另一种方式倾斜,因此从右到左评估操作。 2^3^2
表示“ 2升至9的幂” = 512而不是“ 8平方” = 64。
现在,您可以扩展条款。 在您的例子,第一项终于扩展到a
。 第二个扩展到F / F
,最后扩展到b / c
。 (这假定*
规则也适用于/
。)第三项扩展为d
。 所以你最终
+
| \
+ T
| \
T T
这变成
+__
| \
+ d
| \
a /
|\
b c
b/c
运算的优先级比+
高,因为它离树的叶子更近。
括号会覆盖此自然优先级。 表达方式
(a + b) / c
最初只用一个学期就可以扩展!
E -> T
-> T / F
-> F / F
第二个因素是c
。 直观地讲,树的形式为:
/
| \
F c
现在扩展F
的关键属性语法规则是
F -> ( E ) { F.ast = E.ast }
所以我们真的有
/_______
| \
( E ) c
现在( E )
本身就扩展为a + b
的AST
/_______
| \
+ c
| \
a b
请注意+
如何更接近叶子。 括号的优先级高于/
!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.