![](https://csdnimg.cn/release/download_crawler_static/88617535/bg4.jpg)
W. Cazzola
等人
/
理论计算机科学电子笔记
322
(
2016
)
119
用引号。每次生产之前都可以有标签(例如,可以在语义操作中使用的,以
引用产生式非终结符。在我们的示例评估中,每个角色都与一个名称相关
联。语义动作写在中间。{和}。符号
.
一个动作通过一个先于其定义的标签与
其生产相关联。清单
1
中的示例有一个与语法中唯一的产生式关联的语义操
作。
给定一组模块,
Neverlang
为实现的语言构建一个基于树的解释器
/
编译
器。对于一个给定的输入程序,解释器将构造它的语法树,并按照一个单独
的配置文件中指定的顺序为每个角色遍历它。每当访问节点
n
时
,运行时系
统将执行与用于构建以
n.
在我们的示例中,每当访问表示头非终结符
Exp
的节点时,都会执行标记为
IF
的操作。在遍历过程中,树可以用动态附加到树节点的任意属性
语义动作代码可以通过使用以下语法$label[offset]引用关联生产的所有
非终结符,其中
label
是标识关联生产的标签头部非终结符的
o
值设置为
0
。
所以在上面的例子中,头非终结符可以用$IF[0]或简单的$IF来引用。表示
if-
then-else
表达式的条件部分的第二个非终结符可以由$IF[1]引用,依此类
推。
语 义 动 作 首 先 遍 历 表 示
if-then-else
构 造 的 条 件 部 分 的 子 树
(eval$IF[1])。这种遍历可以在由$IF[1]表示的节点中定义新的属性。这
些属性可能来自实现
Exp
非终结符的其他模块。根据
$IF[1].val
属性的值,我
们继续遍历
if-then-else
构造的一个分支(eval$IF[2]或eval$IF[3])。在这两
个分支中,我们将分支的val属性复制到当前节点。
问题陈述。由于
Neverlang
中属性的性质是动态的,因此在需要时可能不会定
义属性。基本上有两个原因。首先,只有当遵循特定的计算路径时,属性才
可能被定义。例如,让我们假设清单
1
中的
else
分支遗漏了
$IF.val = $IF[3].val;
语句。在这种情况下,在语义动作执行结束时,属性
$IF.val可能不会被定义。另一方面,由于不同的命名约定或仅仅是分散注意
力,具有相同目标的属性可能在不同的模块
/
语义动作中被标记为不同的名称
让我们考虑清单
2
,其中定义了整数和浮点数。这两个规则分别定义正则表达
式匹配整数和双精度。因此,当解析器匹配一个数字时,它将构建一个以Exp
为根的子树,子树中包含匹配的值。语义操作只是提取匹配的数字(由词法
分析器存储在#0.text中)并将其值放入属性中。
double-labeled by
DBL
-
的语义
动作定义了一个名为
value
而不是
val
的属性。因此,语言不能保证
Exp
非终结
符
总是
具有val或value属性。当编写由不同团队开发的实现的编程特性时,