编译原理之美
宫文学
北京原点代码 CEO
46197 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 45 讲
开篇词 (1讲)
编译原理 · 期中考试周 (1讲)
编译原理之美
15
15
1.0x
00:00/00:00
登录|注册

12 | 语义分析(下):如何做上下文相关情况的处理?

属性计算
左值和右值
引用消解
类型系统
作用域
属性的作用
需要计算的属性
思考上下文处理工作
语义分析的任务
属性计算和属性文法的应用
语义分析的重要性
AnnotatedTree类的结构
语义分析过程的拆分
S属性、I属性和L属性
计算顺序的重要性
语法分析过程中或者形成AST后进行计算
计算动作
语义规则的定义
基于语法规则
语法制导的定义(SDD)和语法制导的翻译(SDT)
属性文法(Attribute Grammar)
计算AST节点的属性
属性计算是语义分析的一种算法
表达式生成合格左值的判断
判断左值的情况
右值:通常的值
左值:变量地址或引用
复杂性:函数引用、面向对象编程语言、C++中的自动转换、命名空间
IDE中的跳转和重构功能
确定符号指代的定义位置
语义分析处理上下文相关情况
词法分析和语法分析阶段处理上下文无关
一课一思
课程小结
如何做属性计算
属性计算的特点
属性计算
左值和右值
引用消解
上下文相关情况处理
语义分析

该思维导图由 AI 生成,仅供参考

我们知道,词法分析和语法分析阶段,进行的处理都是上下文无关的。可仅凭上下文无关的处理,是不能完成一门强大的语言的。比如先声明变量,再用变量,这是典型的上下文相关的情况,我们肯定不能用上下文无关文法表达这种情况,所以语法分析阶段处理不了这个问题,只能在语义分析阶段处理。语义分析的本质,就是针对上下文相关的情况做处理。
我们之前讲到的作用域,是一种上下文相关的情况,因为如果作用域不同,能使用的变量也是不同的。类型系统也是一种上下文相关的情况,类型推导和类型检查都要基于上下文中相关的 AST 节点。
本节课,我们再讲两个这样的场景:引用的消解、左值和右值,然后再介绍上下文相关情况分析的一种方法:属性计算。这样,你会把语义分析就是上下文处理的本质掌握得更清楚,并掌握属性计算这个强大的方法。
我们先来说说引用的消解这个场景。

语义分析场景:引用的消解

在程序里使用变量、函数、类等符号时,我们需要知道它们指的是谁,要能对应到定义它们的地方。下面的例子中,当使用变量 a 时,我们需要知道它是全局变量 a,还是 fun() 函数中的本地变量 a。因为不同作用域里可能有相同名称的变量,所以必须找到正确的那个。这个过程,可以叫引用消解。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了语义分析中的上下文相关情况处理,强调了属性计算和属性文法在语义分析中的重要性。作者首先介绍了属性计算的概念,指出属性计算是对AST节点的某个属性进行计算,从而实现对上下文相关情况的处理。随后,文章详细讨论了属性文法的应用,以及在语法分析过程中如何进行属性计算。作者还提到了语义分析的重要性,指出语义分析是对上下文相关情况进行处理,能够完成词法分析和语法分析无法实现的任务。此外,文章还介绍了在实际语义分析过程中的多次遍历任务,包括类型和作用域解析、类型的消解、引用的消解和类型检查等。最后,作者总结了语义分析的重要性,并指出对于想深入了解语义分析的读者具有很高的参考价值。 文章通过深入的技术讨论,为读者提供了对语义分析的全面了解,尤其对于想要深入研究语义分析的读者具有很高的参考价值。文章内容涵盖了属性计算、属性文法的应用,以及在语义分析过程中的多次遍历任务,为读者呈现了语义分析的重要性和复杂性。通过本文,读者可以深入了解语义分析的技术细节,从而更好地理解和应用语义分析的相关知识。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《编译原理之美》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(8)

  • 最新
  • 精选
  • 老师,您好。语义分析有没有工具可以使用? 另外,对于C语言的语义分析,都需要分析哪些内容?有没有一个列表?(我想实现一个C语言的前端)

    作者回复: 没有工具。原因: 语义分析的工作比较多,作用域解析、类型检查等等,比较难以统一解决。 而每个语言的个性化差异,最大的就体现在语义方面。词法差异最小,语法次之,语义差异最大。语法差异再大,但都可以用CFG表示,所有都可以统一地解决。但语义的差异,目前还不好用统一的形式化的方法去解决。 比如类型系统,每种语言的设计相差很大,很难用统一的方式来处理。 属性文法是语义分析领域从形式化的角度做得不错的工作了,所以可以基于属性文法实现一些自动的工作。

    2019-11-01
    17
  • djfhchdh
    老师请教个问题,c++模板与泛型编程在语义上怎样处理的呢?

    作者回复: C++的模板与泛型编程是一种元编程技术,就叫做模板元编程,是C++最强大的能力之一。 在第38讲,我们提到了元编程的基础知识。简单的来说,它是在编译期由程序生成另外的程序。 具体到C++的模板元编程技术,它会在编译期把模板展开,比如把某个数据类型替换成真实的类型,然后再进一步编译所形成的代码。 模板元编程技术能够让编写类库等任务变得更简单。代价是编译期的计算量变大,编译时间变长。 另外注意,C++的泛型跟Java的泛型机制是不一样的。Java的泛型比较简单,只是做类型检查,没有做新代码的生成。

    2020-01-16
    2
    11
  • 沉淀的梦想
    @Override public Object visitPrimary(PrimaryContext ctx) { Object rtn = null; //字面量 if (ctx.literal() != null) { rtn = visitLiteral(ctx.literal()); } //变量 else if (ctx.IDENTIFIER() != null) { Symbol symbol = at.symbolOfNode.get(ctx); if (symbol instanceof Variable) { rtn = getLValue((Variable) symbol); } else if (symbol instanceof Function) { FunctionObject obj = new FunctionObject((Function) symbol); rtn = obj; } } //... 读了一下老师的visitPrimary方法,感觉对于变量,返回的全部都是左值啊?老师的代码是在哪里进行左值和右值的区分的呢?

    作者回复: 是的。你看得很细:-) 我这里是偷懒了。因为左值比右值更强,所以我在示例代码里都用的是左值。 我抽空会在语义分析中加上左右值分析的代码:-)

    2019-09-09
    4
  • 二刷,终于都搞清楚了。语义分析是个体力活。。 感觉课程语义分析这里,跨度有点大,仓库那里直接就是完整特性的PlayScript解释器了。 我按课程的源码,去掉了Class相关的特性,用Python写了一版,覆盖课程08、10、11、12小节(先忽略09、13小节),可以作为一个过渡版本,方便学习: https://github.com/killua-killua/PlayScript-Compiler

    作者回复: Great!

    2021-10-19
    3
  • 皮皮侠
    “因为我们可以在语法规则的基础上制定属性文法,在解析语法的过程中或者形成 AST 之后,我们就可以根据属性文法的规则做属性计算。比如在 Antlr 中,你可以在语法规则文件中插入一些代码,在语法分析的过程中执行你的代码,完成一些必要的计算。”老师,你这里的插入代码计算,是不是类似C++里的编译期计算,比如模板等等?

    作者回复: 这个问题可以看看实际的例子,就最直观了。 比如,下面链接中是Mysql workbench中带的sql解析器的词法规则和语法规则,里面带有一些C++代码,会被加到生成的词法分析器和语法分析器中。 https://github.com/mysql/mysql-workbench/blob/8.0/library/parsers/grammars/MySQLLexer.g4 和 MySQLParser.g4

    2020-04-03
    2
  • djfhchdh
    public、protected、private等访问控制,也是在语义分析阶段处理的

    作者回复: 是的。语义分析时会去做检查。

    2020-01-16
    2
  • 炎发灼眼
    老师,这部分没怎么看懂 借上节课讲过的 S 属性和 I 属性的概念,我们把刚才说的两个情况总结成 primay 节点的两个属性,你可以判断一下,这两个属性是 S 属性还是 I 属性?属性 1:某 primary 节点求值时,是否应该求左值?属性 2:某 primary 节点求值时,能否求出左值? 这是不是说:1的情况下,如果该节点应该求左值,就是I属性,不应该求左值,就是S属性;2的情况下,能求出左值,就是S属性,不能求出左值,就是I属性,那如果属性1和属性2有交叉呢?
    2020-05-06
    1
    2
  • 潜龙勿用
    Rust语言的宏也是元编程
    2021-07-02
    1
收起评论
显示
设置
留言
8
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部