句法分析和语义分析有何区别?

What differentiates syntax analysis and semantic analysis?

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

  1. 词法:它将我的输入拆分为标记。示例:123+100-0 -> 123 + 100 - 0

  2. 句法:它将查看标记并检查它们之间是否有意义。

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

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

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

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

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

希望对您有所帮助!

从理论上讲,句法分析确定语言实例是否“格式正确”并分析其语法结构,而语义分析则分析其含义以及是否“有意义”。

基本上,句法分析可能取决于单词的类型,而不是它们的含义。语义分析取决于意义。 "I like green tomatoes" 和 "I fill wiggly thoughts" 具有相同的句法结构,并且都是格式正确的,但后者在语义上没有任何意义。

这种理论上的区别实际上有点模糊,因为将单词的“类型”与其“含义”分开涉及一些任意选择。

然而,在编译器开发的实践中,区别很明显:句法分析由解析器执行,由语法驱动,具体取决于标记的类型。语义分析从用代码编写的、附加到语法规则的动作开始。基本上任何需要查找实际标识符或评估文字值的实际值的东西都是语义分析。

有些语言需要将语义分析的结果反馈给解析器,以帮助进行句法分析。这破坏了句法分析和语义分析之间的理论区别,但实际上我们只是认为这是一种作弊,并继续将解析代码称为句法。