文章原稿
https://gitee.com/fakerlove/fundamentals-of-compiling

文章目录

  • 7. 语法制导的语义计算
    • 7.1 基本概念
      • 1) 属性文法
      • 2)两种属性:
        • 1. 综合属性
        • 2. 继承属性
      • 3) 带标注语法分析树
        • S-属性文法
        • L-属性文法
      • 4) 语义计算模型
    • 7.2 基于属性文法的语义计算
      • 7.2.1 语义子程序
        • 1) 作用
        • 2) 写法
        • 3) 语义值
        • 4) 语义栈
        • 5) 例题
      • 7.2.2 依赖图
      • 7.2.3 树遍历
        • 树遍历算法
        • 树遍历示例
      • 7.2.4 一遍扫描
        • 抽象语法树AST
        • 建立表达式的抽象语法树
    • 总结

7. 语法制导的语义计算

7.1 基本概念

语义分析是上下文有关的,目前较为常见的是用属性文法来描述程序语言语义,并采用语法制导翻译的方法完成对语法成分的翻译工作。

1) 属性文法

  • 属性文法,也称属性翻译文法
  • Knuth在1968年提出
  • 以上下文无关文法为基础

在文法G[S]的基础上,为文法符号关联有特定意义的属性,并为产生式关联相应的语义动作或条件谓语,称之为属性文法,并称文法G[S]为之的基础文法。

属性文法AG是一个四元式,即AG = (G, A, R, B):G是上下文无关文法,A是属性的有限集合,R是语义规则式的有限集合,B是样式的有限集合。

例子:

产生式 语义动作
S -> ABC {B.in_num := A .num; C.in_num := A .num; if (B.num=0 and (C.num=0) then print(“Accepted!” ) else print(“Refused!” ) }
A -> A1a { A.num := A1.num + 1 }
A -> ε { A.num := 0 }
B -> B1b { B1.in_num := B.in_num; B.num := B1.num-1 }
B -> ε { B.num := B.in_num }
C -> C1c { C1.in_num := C.in_num; C.num := C1.num-1 }
C -> ε { C.num := C.in_num }

2)两种属性:

1. 综合属性

用于“自下而上”传递信息
对关联于产生式 A -> α 的语义规则 b:=f(c1, c2, …, ck) ,如果 b 是 A的某个属性, 则称 b 是 A 的一个综合属性 。

  • 自下而上传递信息
  • 语法规则:根据右部候选式中的符号的属性计算左部被定义符号的综合属性
  • 语法树:根据子结点的属性和父结点自身的属性计算父结点的综合属性

2. 继承属性

用于“自上而下”传递信息
对关联于产生式 A-> α 的语义规则b:=f(c1, c2, …, ck),如果 b 是产生式右部某个文法符号 X 的某个属性,则称 b 是文法符号 X 的一个继承属性。

例子:

在上例的属性文法中A .num,B.num 和 C.num 是综合属性值,而B.in_num 和 C.in_num 是继承属性值。比如在产生式C -> C1c中,C1.in_num 是产生式右部符号C1的属性,由产生式左部符号C的in_num 属性确定,所以它是继承属性,“自上而下”的传递信息;C.num 是产生式左部符号C的属性,由产生式右部符号C1的num属性确定,所以它是综合属性,“自下而上”的传递信息。

3) 带标注语法分析树

即在语法树的基础上,将原来的非终结符结点修改为综合属性的赋值。

下面是一个简单表达式文法G[S]的一个仅含综合属性的属性文法(开始符号为S)
S→E{print(E.val)}
E→E1+T{E.val:=E1.val+T.val}
E→T{E.val:=T.val}
T→T1∗F{T.val:=T1.val×F.val}
T→F{T.val:=F.val}
F→(E){F.val:=E.val}
F→d{F.val:=d.lexval}

其中d.lexvald.lexval表示数值,E.val,T.val,F.val都为综合属性
现在要给表达式3∗(5+4)构造语法树和带标注语法分析树:

下面则是一个包含综合属性、继承属性的属性文法:
E→TR{R.in:=T.val;E.val:=R.val}
R→+TR1{R1.in:=R.in+T.val;R.val:=R1.val}
R→−TR1{R1.in:=R.in−T.val;R.val:=R1.val}
R→ε{R.val:=R.in}
T→num{T.val:=lexval(num)}
其中lexval(num)表示从词法分析程序得到的常数值。
可见E.val,T.val,R.val都为综合属性,R.in为继承属性
现在要给表达式3+4−5构造语法树和带标注语法分析树:

S-属性文法

只包含综合属性的属性文法。

L-属性文法

可以包含综合属性,也可以包含继承属性。但产生式右端某文法符号的继承属性的计算只取决于该符号左边文法符号的属性(对于产生式左边文法符号,只能是继承属性)。

4) 语义计算模型

  • 属性文法:侧重于语义计算规则的定义
  • 翻译模式:侧重于语义计算过程的定义

7.2 基于属性文法的语义计算

按照语义规则进行属性计算的3种方法

  • 依赖图
  • 树遍历
  • 一遍扫描

7.2.1 语义子程序

1) 作用

用来描述一个产生式所对应的翻译工作。

– 如:改变某些变量的值;查填各种符号表;发现并报告源程序错误;产生中间代码等。

• 注:这些翻译工作很大程度上决定了要产生什么形式的中间代码。

2) 写法

语义子程序写在该产生式后面的花括号内。X →α {语义子程序1}

注:在一个产生式中同一个文法符号可能出现多次,

但他们代表的是不同的语义值,要区分可以加上角标。

如:E →E(1)+E (2)

3) 语义值

为了描述语义动作,需要为每个文法符号赋予不同的语义值:类型、地址、代码值等

4) 语义栈

  • 各个符号的语义值放在语义栈中

    当产生式进行归约时,需对产生式右部符号的语义值进行综合,其结果作为左部符号的语义值保存到语义栈中。

  • 下推栈包含3部分:

    状态栈、符号栈和语义栈

    注:语义栈与状态栈和符号栈是同步变化的。

5) 例题

产生式 语义子程序
S` →E {PRINT E•VAL}
E →E(1)+E(2) {E•VAL= E (1) •VAL +E(2) •VAL }
E →E (1)*E(2) {E•VAL= E (1) •VAL *E(2) •VAL }
E →(E (1)) {E•VAL= E (1) •VAL }
E → i {E•VAL= LEXVAL }

注:LEXVAL指的是词法分析送来的机内二进制整数。

7.2.2 依赖图

通过寻找属性之间的依赖关系,来确定属性计算的先后顺序,选择相应的语义规则,完成语义计算。

  • 在一棵语法树中的结点的继承属性和综合属性之间的相互依赖关系可以由依赖图(有向图)来描述。
  • 为每一个包含过程调用的语义规则引入一个虚综合属性b,这样把每一个语义规则都写成b :=f(c 1,c 2…c k)的形式
  • 依赖图中为每一个属性设置一个结点,如果属性b依赖于属性c,则从属性c的结点用一条有向边连到属性b的结点。E→E1+E2 E.val := E1.val+E2.val[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aO72x15M-1621078687584)(picture/20200423152444984.png)]
  • 依赖图的构建算法
//第一遍循环
for (结点 n : 语法树){for(文法符号属性 a : n){在依赖图中为a建立结点;}
}
//第二遍循环
for (结点 n : 语法树){for(语义规则 b : n){//语义规则的形式为 b := f(c1,c2,...,ck)//ci为b所依赖的属性for(依赖属性 c: b){构造从 c 指向 b 的有向边;}}
}
12345678910111213141516
  • 对于属性文法:
产生式 语义规则
D→TL L.in := T.type
T → int T.type := integer
T → real T.type := real
T→T1*F T.val := T1.val*F.val
L → L1,id L1.in := L.in addtype(id.entry, L.in)
L → id addtype(id.entry, L.in)

语句 real id1,id2,id3的依赖图可以画成:

注意⑦⑨⑩是虚拟结点

  • 良定义的属性文法

    • 如果一属性文法不存在属性之间的循环依赖关系,则称该文法为良定义的
    • 一个依赖图的任何拓扑排序都给出一个语法树中结点的语义规则计算的有效顺序
  • 属性的计算次序
    • 基础文法用于建立输入符号串的语法分析树
    • 根据语义规则建立依赖图
    • 根据依赖图的拓扑排序,得到计算语义规则的顺序输入串→语法树→依赖图→语义规则计算次序

7.2.3 树遍历

通过树遍历的方法计算属性的值

  • 假设语法树已建立,且树中已带有开始符号的继承属性和终结符的综合属性
  • (不需要建立依赖图)以某种次序遍历语法树,直至计算出所有属性
  • 深度优先,从左到右的遍历输入串→语法树→遍历语法树计算属性

树遍历算法

while(还有未被计算的属性){VisitNode(S);//S 是开始符号
}//从根节点开始递归计算属性
void VisitNode(Node N){if(N是非终结符){//N的继承属性应该已经被计算出或者由编译器提供//假定当前产生式是 N-> X1 X2 ... Xm,共m项for(int i=1;i<=m;i++){if(Xi 是非结符){计算Xi 中能够计算的继承属性;VisitNode(Xi);计算Xi 中能够计算的综合属性;}}计算N中能够计算的综合属性;}
}
12345678910111213141516171819

树遍历示例

反复调用VisitNode(S)直到所有继承属性和综合属性都能被计算出来或者不再有更多的属性可以被计算为止。
第一次调用可以计算出Z.h=0Z.g=1
第二次调用可以计算出X.c=1X.d=2S.b=0
第三次调用可以计算出Y.e=0Y.f=0

请直接观看视频。

7.2.4 一遍扫描

  • 在语法分析的同时计算属性值

    • 所采用的语法分析方法
    • 属性的计算次序
  • 所谓语法制导翻译法,直观上说就是为文法中每个产生式配上一组语义规则,并且在语法分析的同时执行这些语义规则
  • 语义规则被计算的时机
    • 自上而下分析,一个产生式匹配输入串成功时
    • 自下而上分析,一个产生式被用于进行归约时
  • 在语法分析的同时计算属性值
  • 适用于 S-属性文法 / L-属性文法

抽象语法树AST

抽象语法树(Abstract Syntax Tree,AST),在语法树中去掉那些对翻译不必要的信息,从而获得更有效的源程序中间表示
3*5+4:

建立表达式的抽象语法树

函数声明 作用
mknode(op, left, right) 建立一个运算符号结点,标号是op, 两个域left和right分别指向左子树和右子树
mkleaf(id, entry) 建立一个标识符结点,标号为id, 一个域entry指向标识符在符号表中的入口
mkleaf(num, val) 建立一个数结点,标号为num, 一个域val用于存放数的值

运用以上函数,可以写出以下产生式的语义规则:

产 生 式 语 义 规 则
E→E1+T E.nptr := mknode(‘+’, E1.nptr, T.nptr ) 注意:此时我们认为E1和T已经被构建成了某一语法子树的根节点
E→E1-T E.nptr := mknode(‘-’, E1.nptr, T.nptr )
E→T E.nptr := T.nptr
T→ (E) T.nptr := E.nptr 括号对于计算是多余的
T→id T.nptr := mkleaf ( id, id.entry )
T→num T.nptr := mkleaf ( num, num.val )

显然这种抽象语法树特别适合于自下而上的属性计算。

a - 4 + c对应的抽象语法树如下:

总结

了解综合属性和继承属性。已知属性文法和输入符号串,构建语法树和带标注语法分析树。

属性 描述文法符号的类型、值等有关的一些信息,它可以被计算或传递。

语义动作 指产生式相关联的指定操作

条件谓词 指产生式关联的接受条件,或者根据该条件谓词决定做什么语义动作

语义规则集 通常是产生式关联的一组语义规则,每个语义规则可以是一个语义动作或条件谓词。

属性attatt可以与某个文法符号aa关联,用a.atta.att来表示这种关联

现有一文法:
E→T1+T2∣T1&&T2
T→num∣true∣false

将上面的文法描述为类型检查的属性文法:

E→T1+T2{T1.type=int&&T2.type=int}
E→T1&&T2{T1.type=bool&&T2.type=bool}
T→num{T.type=int
T→true{T.type=bool}
T→false{T.type=bool}

编译原理教程_7 语法制导的语义计算相关推荐

  1. 编译原理--语法制导的翻译

    前言 把一些属性附加到代表语言构造的文法符号上, 以把信息和一个语言的构造联系起来. 通过语义规则来说明文法符号的属性值如何确定. 产生式 语义规则 E -> E_{1} + T E.code ...

  2. 编译原理实验-LL1语法分析器(自动生成First集、Follow集求法)java实现

    编译原理实验-LL1语法分析器(自动生成First.Follow)java 博主在做实验时,参考众多他人代码,发现bug众多,在@moni_mm代码基础上,与伙伴把能看到的BUG都做出修正,同时增添了 ...

  3. 编译原理教程_1 引论

    文章下载地址-关注我的gitee https://gitee.com/fakerlove/fundamentals-of-compiling 文章目录 1. 引论 1.1 什么是编译原理 1.1.1 ...

  4. 【编译原理】LR语法分析器的设计与实现

    LR语法分析器的设计与实现 本文为当时编译原理实验作业,要求用设计的思想完成,小题大做,仅供参考 文章目录 LR语法分析器的设计与实现 实验要求 实现功能 输入输出 样例 一.LR语法分析器问题定义 ...

  5. 【编译原理】词法分析器语法分析器

    简单编译器设计 采用Java语言对C++语言进行编译,具体的简单编译器设计 词法分析器-扫描器的设计与实现 基本符号表 状态转换图 代码实现 import java.io.*; import java ...

  6. 编译原理 LL(1)语法分析器的设计与实现

    实验内容 针对SysY语言中简单算术表达式文法G[E]: E→TE' E'→ATE'|ε T→FT' T'→MFT' |ε F→(E) | i A → + | - M → * | / 求解相应的FIR ...

  7. 编译原理教程_8 静态语义分析和中间代码生成

    文章原稿 https://gitee.com/fakerlove/fundamentals-of-compiling 文章目录 8. 静态语义分析和中间代码生成 8.1 中间语言 8.1.1 概述 8 ...

  8. 编译原理教程_4 语法分析

    文章原稿 https://gitee.com/fakerlove/fundamentals-of-compiling 文章目录 4. 语法分析 4.1 概述 4.1.1功能 4.1.2 基本任务 4. ...

  9. 编译原理之简单语法分析器(c语言)

    语法分析是编译过程的核心部分,其基本任务是根据语言的语法规则进行语法分析,如果不存在语法错误即给出正确的语法结果,并为语义分析和代码生成做准备. 语法分析器的两种方式 语法分析器的任务主要是确定是否可 ...

最新文章

  1. RBF(Radial Basis Function Network)+径向基网络
  2. kaggle上传数据集遇到Default slug detected, please change values before uploading
  3. 广西区计算机一级考试操作题,全国高校计算机等级考试(广西考区)一级笔试试题卷.doc...
  4. 非阻塞IO与异步IO
  5. pricing data of Service order is copied from BP master data
  6. PARALLEL(并行)
  7. (多源转化成单源dijsktra)一个人的旅行
  8. 造假暴赚260亿的资本“大忽悠”,终于倒下了
  9. arcgis图像和坐标系统一致但不重合_学习ArcGIS,这62个Arcmap常用操作技巧可能帮到您...
  10. 电信 宽带 光猫 中兴 F460 V6.0.0P11T2sc 破解 telecomadmin 超级密码 的方法
  11. Markdown转Jupyter
  12. MFC界面编程基础(01):Windows 编程模型
  13. 上海市的某快递公司根据投送目的地距离公司的远近,将全国划分成5个区域: 0区 1区 2区 3区 4区 同城 临近两省 1500公里(含)以内 1500——2500公里 2500公里以上 上海 江苏
  14. CTFShow“萌心区”WP(上)
  15. pd调节规律_PD 控制规律的特点是具有超前控制功能。( )
  16. python 打印自己代码_用python打印网页源代码
  17. 是的,你的AI技能正在“贬值”
  18. 深信服校园招聘c/c++ 软件开发A卷--菜鸡落泪
  19. 计算机专业ppt答辩范文,计算机科学与技术专业论文答辩范例.ppt
  20. sku展示php,前端如何展示商品属性:SKU多维属性状态判断算法的应用

热门文章

  1. Mac关闭SIP模式 开启root
  2. 最常见的Linux用户程序异常----Segment Fault
  3. 数据清洗(根据元素匹配选取数据)
  4. ios录制视频时audio丢失
  5. Hls之TS流分离音视频
  6. access统计各职务人数_东莞各阶段学生人数统计|终于知道为什么在东莞总是学位紧缺了...
  7. Kubernetes网络策略,这一篇就够了
  8. linux 进程 异常日志,linux后台启动程序,处理nohup日志太大的问题
  9. php查询mysql数据库输出到前台_PHP读取数据库表显示到前台
  10. staruml 为类的属性指定数据类型_关于python的数据类型