据我理解,语法分析器由词汇、句法和语义分析三个阶段组成。
0
123+100-0
-> 123
+
100
-
我遇到的问题是理解最后阶段的“语义分析”,以及它如何区分到第二阶段的“句法分析”。据我理解,“语义解析”的最后阶段也验证了通过“语法分析”验证的标记,然后输出输出。
发布于 2020-07-01 21:03:23
一般来说,语法分析的目标是将标记流(由词法分析生成)转换为程序“含义”的某种结构化表示。例如,在语法分析中,您会期望令牌a
、/
和b
被转换成“a
和b
的商数”。通常,语法分析的输出是抽象语法树,它是编码程序结构的树结构。
语义分析的任务是确保语法分析步骤生成的表示实际上是“有意义的”。例如,假设语法分析器已经将a
、/
和b
转换为“a
和b
的商数”。在语法分析器这样做的时候,它可能不知道a
和b
的类型;更有可能的是,语法分析器只是看到这可以被解释为一个数学表达式,并在此留下一些东西。然而,这完全有可能不是一个定义明确的操作。例如,如果a
是字符串,而b
是布尔值,那么a / b
是无意义的操作,编译器应该报告错误。
更详细的例子是,假设您正在实现一个Java编译器,并且您看到了令牌public
、class
、A
、extends
、B
、{
、}
。您可以在语法分析期间将其解释为类定义,因为它是一个语法上有效的类。但是,如果文件后面定义的B
不是一个类呢?或者,如果根本没有定义B
怎么办?在这种情况下,代码是不正确的。它在语法上是有效的,因为它可以被认为是合法的代码,但在语义上是不正确的,因为找不到类B
。因此,语法分析器将生成一个完全有效的AST,而语义分析器在发现B
不存在之后将拒绝代码。
我们没有必要将这两个步骤分开的根本原因,事实上,一些编译器将这两个步骤结合在一起。这样做的主要原因是实际的--我们有一些构建语法分析器(LR解析器、LL解析器等)的很好的工具,它们通过解释标记序列来工作,而没有过多地考虑它们的含义。然后编译器作者可以指定该语言的一般语法,然后编写一个语义分析器作为第二次遍历,检查AST并确定它是否有效。这使得解析器生成器可以自动完成的任务与程序员为更干净编写代码所需的任务分离开来。
希望这能有所帮助!
发布于 2020-07-01 21:08:56
从理论上讲,句法分析决定语言的一个实例是否“形成良好”,并分析其语法结构,而语义分析则分析它的意义和它是否“有意义”。
基本上,句法分析可能取决于单词的类型,而不是它们的意义。语义分析依赖于语义。“我喜欢绿番茄”和“我填充摇摆不定的思想”具有相同的句法结构,都是很好的形式,但后者在语义上没有任何意义。
这一理论上的区别实际上有点模糊,因为将一个词的“类型”与“意义”分开涉及到一些任意的选择。
然而,在编译器开发的实践中,区别是明确的:语法分析由解析器执行,由语法驱动,取决于标记的类型。语义分析从以代码编写的动作开始,这些动作与语法中的规则相连。基本上,任何需要查找实际标识符或计算字面值的实际值的东西,都是语义分析。
有些语言需要将语义分析的结果反馈到解析器中,以帮助语法分析。这破坏了句法分析和语义分析之间的理论区别,但实际上我们只是认识到这是一种欺骗,并继续将解析代码称为语法。
https://stackoverflow.com/questions/62678079
复制相似问题