据我了解,Parser由词法分析、句法分析和语义分析三个阶段组成。
-
Lexical:它将我的输入分割成标记。例子:123+100-0
-> 123
+
100
-
0
-
语法:它将研究标记并检查它们是否彼此有意义。
我遇到的问题是理解最后阶段的“语义解析”以及它与第二阶段“句法分析”的区别。据我了解,最后阶段“语义解析”还会验证已通过“语法分析”验证的标记,然后打印输出。
一般来说,语法分析的目标是将标记流(由词法分析生成)转换为程序“含义”的某种结构化表示。例如,在语法分析中,您期望标记a
, /
, and b
被转换成“的商”a
and b
。”通常,语法分析的输出是抽象语法树,它是编码程序结构的树结构。
语义分析的工作是确保语法分析步骤生成的表示实际上“有意义”。例如,假设语法分析器已将a
, /
, and b
代入“商”a
and b
” 当语法分析器执行此操作时,它可能不知道什么类型a
and b
是;更有可能的是,语法分析器只是看到这可以解释为数学表达式,然后就这样了。然而,这完全有可能不是一个定义明确的操作。例如,如果a
是一个字符串并且b
是一个布尔值,那么a / b
是无意义的操作,编译器应该报告错误。
对于更详细的示例,假设您正在实现 Java 编译器并且您看到了标记public
, class
, A
, extends
, B
, {
, }
。您可以在语法分析期间将其解释为类定义,因为它是语法上有效的类。但如果B
,它在文件后面定义,不是一个类吗?或者如果B
根本没有定义吗?在这种情况下,代码是不正确的。它是语法上有效的从某种意义上说,它可能是合法的代码,但它是语义上不正确因为没有班级B
被发现。因此,语法分析器会生成一个完全有效的 AST,而语义分析器会在发现以下情况后拒绝该代码:B
不存在。
我们没有什么根本原因have将这两个步骤分开,事实上一些编译器将这两个步骤融合在一起。这样做的主要原因是实用 - 我们有一些很棒的工具用于构建语法分析器(LR 解析器、LL 解析器等),它们通过解释标记序列来工作,而无需过多考虑它们的含义。然后,编译器作者可以指定该语言的一般语法,然后编写语义分析器作为第二遍,检查 AST 并确定它是否有效。这使得解析器生成器可以自动执行的操作与程序员需要编写更清晰的代码的操作分开。
希望这可以帮助!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)