繁体   English   中英

语法定向翻译是什么意思?

[英]What does syntax directed translation mean?

谁能简单解释一下“语法定向翻译”是什么意思? 我开始从龙书上读题目,但看不懂。 维基文章也没有帮助。

简单来说,“语法定向翻译”意味着使用语法识别器(解析器)驱动整个编译(翻译)过程。

从概念上讲,编译程序(将其从源代码翻译成机器代码)的过程从一个生成解析树的解析器开始,然后通过一系列树或图变换来变换该解析树,每个变换在很大程度上都是独立的,生成最终的简化树或图形,遍历该树或图形以生成机器代码。

这种视图虽然理论上很好,但有一个缺点,即如果您尝试直接实现它,则需要足够的内存来保存整个树或图的至少两个副本。 回到《龙之书》写成时(当很多这个理论被散列时),计算机内存以千字节为单位,64K 是很多。 所以编译大型程序可能会很棘手。

使用语法定向翻译,您可以围绕解析器识别解析树的顺序组织所有图转换。 您的解析器不是生成完整的解析树,而是构建它的一小部分,然后将这些位提供给编译器的后续传递,最终生成一小段机器代码,然后继续解析过程以构建下一段解析树。 由于任何时候都只存在少量的解析树(或后续图),因此需要的内存要少得多。 由于语法识别器是控制所有这些(决定事情发生的顺序)的主音序器,因此这称为语法定向翻译。

由于这是一种减少内存使用的有效方法,人们甚至重新设计了语言以使其更容易实现——理想的情况是拥有一个“单程”编译器,它实际上可以完成从解析到机器代码生成的整个过程一次通过。

如今,内存并不那么珍贵,因此将所有内容强制执行一次的压力较小。 相反,您通常只在前端使用语法直接翻译,解析语法,进行类型检查和其他语义检查,以及一些来自解析器的简单转换并生成一些内部形式(三个地址代码、树或某种类型的 dag ),然后进行独立的优化和后端传递(因此不受语法指导)。 即使在这种情况下,您可能会声称这些后面的传递至少部分是语法指导的,因为编译器可能会被组织为对输入的大块(例如整个函数或模块)进行操作,在继续执行之前推送所有传递下一段输入。

yacc 之类的工具是围绕语法定向翻译的思想设计的——该工具生成一个语法识别器,它在识别产品(解析树的片段)时直接运行代码片段(工具用语中的“动作”),而无需创建一棵真正的“树”。 这些动作可以直接调用编译器中逻辑后面的pass,然后返回继续解析。 驱动所有这些的命令式主循环是解析器的令牌读取状态机。

实际上没有。在龙书之前,历史上有语法指导的编译器。 在 1960 年代后期参加 ACM SEGPlan 会议时,我了解到几种类型的定向翻译。 还讨论了树有向和图有向翻译。 虽然我从来没有拥有过之书,但我认为这些在龙之书中被混为​​一谈。 我最喜欢的书是 Saul Rosen 的 Programming Systems and Languages。 它是关于编译器、操作系统和计算机系统的论文集。 我将尝试解释早期的语法导向编译器解析器编程语言。 后来产生树的与树定向代码生成语言相结合。

早期的语法导向编译器,将源代码直接翻译成堆栈机器代码。 Borrows B5000 ALGOL 编译器就是一个例子。

A*(B+C) -> A,B,C, ADD , MPY

Schorre 于 1960 年代开发的 META II 域特定解析器编程语言编译器编译器是语法定向编译器的一个示例。 您可以在 ACM 档案中找到原始 META II 论文。 META II 使用 $ 后缀零或多个序列运算符和 ( ) 分组避免左递归。

EXPR = TERM $('+' TERM .OUT 'ADD'|'-' TERM .OUT 'SUB');

后来基于 Schorre 的元语言编译器使用基于堆栈的树转换运算符:< node name > 和 !< number > 翻译成树。

EXPR = TERM $(('+':ADD|'-':SUB) TERM!2);

除了使用 [< number >] 而不是 !< number > 的 TREEMETA。 上面的 EXPR 公式与 META II EXPR 基本相同,只是我们已经分解了运算符 + 和 - 识别创建相应的节点并将节点推送到节点堆栈上。 然后在识别正确的 TERM 时,树构造函数 !2 创建一棵树,从节点堆栈中弹出顶部 2 个解析堆栈 < TERM > 和顶部节点以形成树:

    ADD    or    SUB
   /   \        /   \
TERM   TERM  TERM   TERM

令牌由提供的识别器 .ID .NUMBER 和 .STRING 识别。 后来在 CWIC 中被标记“..”和字符类“:”替换:

id .. let $(leter|dgt|+'_');

树定向编译器语言与语法定向编译器相结合以生成代码。 Systems Development Corporation 开发的 CWIC 编译器编译器包括基于 LISP 2 的树定向生成器语言。 可以在 ACM 档案中找到 CWIC 中的一篇简短论文。

在解析器编程语言中,您正在编写一种递归体面的解析器。 当您使用 CWIC 时,所有今天归因于递归体面解析器的问题都被消除了。 没有左递归问题,因为 $ 零或多个构造和编程树构造消除了左递归的需要。 您控制树的构造。 循环构造用于生成左手树和尾递归生成右手树。 尽管解析公式可能根本不会生成树:

program = $declarations;

在上面的 $ 零个或多个循环运算符前面的声明指定声明将被重复调用,只要它返回成功。 正在编译的输入源代码由任意数量的声明组成。 然后声明公式将定义声明的类型。 您可能需要外部链接声明、数据声明、函数或过程代码声明。

declarations = linkage_decl | data_decl | code_decl;

每个声明的类型都是一个单独的公式。 语法语言控制何时发生语义处理和代码生成。 上面的程序和声明公式不会生成树。 它们只是控制何时解析什么语言结构。 这些既不是LL oe LR 解析器sears。 提供无限制(仅受可用内存限制)编程回溯。 它们提供程序化的前瞻和峰值前瞻测试。

作为最后一个示例,包含标记和字符类公式的以下示例说明了生成左手树和右手树。 特别是使用尾递归求幂。

assign = id '=' expr ';' :ASSIGN!2 arith_gen[*1];
expr   = term $(('+':ADD | '-':SUB) term !2);
term   = factor $(('*':MPY | '//' :REM | '/':DIV) factor!2);
factor = ( id ('(' +[ arg $(',' arg ]+ ')' :CALL!2 | .EMPTY)
         | number 
         | '(' expr ')'
         )  ('^' factor:EXP!2 | .EMPTY);

bin: '0'|'1';
oct: bin|'2'|'3'|'4'|'5'|'6'|'7';
dgt: oct|'8'|'9';
hex: dgt|'A'|'B'|'C'|'D'|'E'|'F'|'a'|'b'|'c'|'d'|'e'|'f';
upr: 'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|
     'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z';
lwr: 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'| 
     'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'x'|'y'|'z';
alpha:    upr|lwr;
alphanum: alpha|dgt;

number .. dgt $dgt MAKENUM[];
id .. alpha $(alphanum|+'_');

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM