我正在阅读面向模式的软件架构中的管道和过滤器架构模式。在这里,我不必了解编译器设计,但作者给出了编译器设计的示例。我遵循了大部分内容,但我很难理解以下内容。
在编译器设计中,我们有不同的阶段,如扫描程序,解析器,语义分析,中间代码生成和后端(MIPS后端,Intel后端......)。
这里作者提到了前端阶段,解析器,语义分析,中间代码生成。后端是MIPS后端。
以下是文字摘要
我们决定不显式构造抽象语法树,从解析器传递到语义分析器。相反,我们将语义分析器(sa)和代码生成器(cg)的调用嵌入到yacc的语法规则中:
addexpr : team
| addexpr '+' term
{ sa.checkCompat($1,$3); cg.genAdd($1,$3);}
| addexpr '-' term
{ sa.checkCompat($1,$3); cg.genSub($1,$3);}
我对上述文字的疑问 1.作者的意思是“不要明确地构建抽象树”? 我只需要理解上面的语法规则它做了什么?由于我没有设计语言,我必须了解模式。如果我对上面的例子有很好的理解,我可以有效地遵循模式吗?
感谢您的时间和帮助。
答案 0 :(得分:1)
我相信@MortenJensen回答了你的第一个问题。
如果您进行了一些Web开发,可能您已经知道什么是管道。试想一下您在Web服务器处理请求的过程。有一系列独立的模块可以解析它们的输入(它是一行中前一个模块的输出),最后一个模块生成输出http响应。 (tcp包转换为http请求,转换为服务器对象,请求被解析并创建响应服务器对象,对象呈现为html,html包装成http响应,包装成tcp包)。
关于编译器也是如此。它获取了您的源代码,经过几次后续转换后,您将获得可执行文件。这是管道模式的非常好的样本,但可能没有这些细节可能会分散您对主要问题的注意力。
答案 1 :(得分:1)
我认为Morten Jensen回答了关于语法解释的问题。此外, 我在猜测:
作者指出的主要内容是在解析阶段调用编译,SA和CG的“下一个”阶段。换句话说,它不会等待在“语义分析和代码生成”之前生成整个解析器树。
答案 2 :(得分:0)
此示例类似于yacc-lex / bison-flex等词法解析器的语法规则。像您所描述的那样的规则是一种分层语法规则,例如BNF。
您发布的'代码'告诉语法规则一种名为“addexpr”的表达式。
addexpr := term | addexpr + term | addexpr - term
这类似于:
add-expression是一个术语或另一个add-expression +一个术语或另一个add-expression - 一个术语。
您可以使用这些递归语法规则来构建语言表示。代码{ sa.checkCompat($1,$3); cg.genAdd($1,$3);}
看起来像是在$ 1和$ 3上进行输入验证 - 如在参数1和3中那样,在“X + Y”中$ 1将是'X',$ 2 ='+'和$ 3 ='Y ”。
对cg.genAdd
的调用可能是一个函数调用,它将“add”表达式添加到抽象语法树中。
这意味着您在解析源代码时,一次生成一个元素的抽象语法树。