编译器构造/语义分析
外观
< 编译器构造
这大致相当于检查用自然语言(例如英语)写的一些普通文本是否真的有意义(无论它是否具有预期意义)。
语义分析的目的是检查我们是否有有意义的标记序列。注意,一个序列可以在没有正确的情况下有意义;在大多数编程语言中,短语“x + 1”将被认为是有意义的算术表达式。但是,如果程序员真的想写“x - 1”,那么它就不正确了。
是时候认真阅读Aho & Ullman/龙书了。
语义分析是编译器确定各种值的类型、这些类型如何在表达式中交互以及这些交互在语义上是否合理的活动。例如,你不能合理地将字符串乘以类名,尽管没有任何编辑器会阻止你写
"abc" * MyClass
为此,编译器必须首先识别声明和作用域,并且通常将此步骤的结果记录在一组符号表中。这告诉它特定标识符在特定上下文中的含义。它还必须确定各种文字常量的类型;“abc”与 12.2e-5 的类型不同。
然后,它必须访问所有使用标识符和文字的位置,并验证标识符/文字的使用以及计算的结果是否与语言定义兼容(如上面的示例所示)。
至于如何做到这一点:通常对源代码进行解析,构建程序的某种表示(语法树非常流行),然后逐元素遍历(“访问”)该表示以收集/验证语义信息。符号表通常只是一组与表示作用域的语法树关联的哈希表,从标识符散列到包含类型声明的结构。
在静态类型语言中,紧随解析阶段之后是类型检查阶段。这尝试根据类型理论来捕捉编程错误。实际上,这是检查诸如声明为字符串的变量是否未在需要整型的表达式中使用之类的事情。
在动态类型语言中,不执行类型检查(实际上它被推迟到运行时)。