语法分析和语义分析有什么区别?

Abh*_* SB 3 language-agnostic compiler-construction parsing

据我了解,Parser由词法分析、句法分析和语义分析三个阶段组成。

  1. Lexical:它将我的输入分割成标记。示例:123+100-0->123 + 100 - 0

  2. 语法:它将研究标记并检查它们是否彼此有意义。

我遇到的问题是理解最后阶段的“语义解析”以及它与第二阶段“句法分析”的区别。据我了解,最后阶段“语义解析”还会验证已通过“语法分析”验证的标记,然后打印输出。

tem*_*def 9

一般来说,语法分析的目标是将标记流(由词法分析生成)转换为程序“含义”的某种结构化表示。例如,在语法分析中,您希望将标记a/和转换为“与 的b商”。通常,语法分析的输出是抽象语法树,它是编码程序结构的树结构。ab

语义分析的工作是确保语法分析步骤生成的表示实际上“有意义”。例如,假设语法分析器已将a/、 和转换为“与 的b商”。当语法分析器执行此操作时,它可能不知道和 的类型是什么;更有可能的是,语法分析器只是看到这可以解释为数学表达式,然后就这样了。然而,这完全有可能不是一个定义明确的操作。例如,如果是一个字符串并且是一个布尔值,那么是一个无意义的操作,编译器应该报告错误。abababa / b

对于更详细的示例,假设您正在实现 Java 编译器并且您看到标记public, class, A, extends, B, {, }。您可以在语法分析期间将其解释为类定义,因为它是语法上有效的类。但是B,如果文件后面定义的 不是类怎么办?或者如果B根本没有定义怎么办?在这种情况下,代码是不正确的。它在语法上是有效的,因为它可能是合法的代码,但它在语义上是不正确的,因为没有B找到一个类。因此,语法分析器会生成一个完全有效的 AST,而语义分析器会在发现该代码B不存在后拒绝该代码。

我们没有必要将这两个步骤分开,事实上,一些编译器将这两个步骤融合在一起。这样做的主要原因是实用 - 我们有一些很棒的工具用于构建语法分析器(LR 解析器、LL 解析器等),它们通过解释标记序列来工作,而无需过多考虑它们的含义。然后,编译器作者可以指定该语言的一般语法,然后编写语义分析器作为第二遍,检查 AST 并确定它是否有效。这使得解析器生成器可以自动执行的操作与程序员需要编写更清晰的代码的操作分开。

希望这可以帮助!