理解ETF语法和抽象语法树

时间:2016-11-02 05:02:04

标签: compiler-construction abstract-syntax-tree context-free-grammar parse-tree

我已将下面的问题附在答案上。我的问题是我无法理解。您是否可以通过派生第一个表达式来详细说明解析树和ETF语法?enter image description here

试着解释第一个表达式,a + b / c + d。我认为这并不难,但我一直无法找到合适的资源来理解这一点。你还可以提供解释ETF语法的资源吗?如果你不想给出解释,那么至少你可以指出一些资源来理解这一点会很好。作为一种策略,我认为最好先构建解析树,然后将其转换为AST。

1 个答案:

答案 0 :(得分:1)

这是一个粗心的问题。 先验没有理由为什么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运算符分隔的一个或多个+个列表的列表。

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

请注意+如何离树叶更近。括号的优先级高于/