Syntax 语法导向翻译是什么意思?

Syntax 语法导向翻译是什么意思?,syntax,language-agnostic,compiler-construction,Syntax,Language Agnostic,Compiler Construction,谁能简单地解释一下“语法导向翻译”是什么意思?我开始读龙书中的主题,但不明白。这也没有帮助。简单地说,“语法导向翻译”意味着使用语法识别器(解析器)驱动整个编译(翻译)过程 从概念上讲,编译程序(将其从源代码转换为机器代码)的过程从生成解析树的解析器开始,然后通过一系列树或图形转换(每个转换在很大程度上是独立的)转换该解析树,最终生成一个简化的树或图形,通过该树或图形生成机器代码 这个视图虽然在理论上很好,但有一个缺点,即如果您试图直接实现它,则需要足够的内存来保存整个树或图形的至少两个副本。当

谁能简单地解释一下“语法导向翻译”是什么意思?我开始读龙书中的主题,但不明白。这也没有帮助。

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

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

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

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

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

如今,记忆并没有这么贵,所以把所有东西都塞进一个关卡的压力就小了。相反,您通常只在前端使用语法直接翻译,解析语法,执行类型检查和其他语义检查,以及一些简单的转换,所有这些都来自解析器,并生成一些内部形式(三个地址码、树或某种DAG)然后拥有独立的优化和后端过程(因此不受语法指导)。即使在这种情况下,您也可能会声称这些后续过程至少部分是语法定向的,因为编译器可能被组织为对大块输入(例如整个函数或模块)进行操作,在继续下一段输入之前,将所有过程都推过


像yacc这样的工具是围绕着语法导向翻译的思想设计的——该工具生成一个语法识别器,在识别产品(解析树的片段)时直接运行代码片段(“操作”),而不创建实际的“树”。这些操作可以直接调用编译器中稍后逻辑传递的内容,然后返回继续解析。驱动所有这一切的命令式主循环是解析器的令牌读取状态机。

事实上不是。历史上,在《龙书》之前,有语法导向编译器。在20世纪60年代末参加ACM SEGPlan会议时,我学到了几种类型的定向翻译。文中还讨论了树定向翻译和图定向翻译。虽然我从未拥有过龙书,但我认为这些在龙书中被混淆了。我最喜欢的书是索尔·罗森的《编程系统与语言》。这是一本关于编译器、操作系统和计算机系统的论文集。我将尝试解释早期的语法定向编译器解析器编程语言。后来生成树的语言与树导向的代码生成语言相结合

早期的语法定向编译器,将源代码直接转换为堆栈机器代码。借用B5000 ALGOL编译器就是一个例子

A*(B+C)->A、B、C、添加MPY

Schorre在20世纪60年代开发的META II领域特定解析器编程语言compiler compiler就是语法导向编译器的一个例子。你可以在ACM档案中找到原始的META II论文。META II使用$postfix零或更多序列运算符和()分组避免左递归

EXPR = TERM $('+' TERM .OUT 'ADD'|'-' TERM .OUT 'SUB');
后来,基于Schorre的元语言编译器使用基于堆栈的树转换运算符转换为树:and

除了使用[]而不是!的TREEMETA之外!。上面的EXPR公式基本上与META II EXPR相同,只是我们考虑了操作符+和-识别,创建相应的节点并将节点推到节点堆栈上。然后识别正确的术语树构造函数!2创建一棵树,从节点堆栈弹出顶部2个解析堆栈和顶部节点,以形成一棵树:

    ADD    or    SUB
   /   \        /   \
TERM   TERM  TERM   TERM
令牌由提供的识别器.ID.NUMBER和.STRING识别。随后替换为标记“.”和字符类“:”CWIC中的公式:

id .. let $(leter|dgt|+'_');
树导向编译器语言和语法导向编译器结合起来生成代码。系统开发公司开发的CWIC编译器包括一种基于LISP2的树定向生成器语言。《化学武器公约》的一篇短文可在ACM档案中找到

在解析器编程语言中,您正在编程一种递归解析器。当您使用CWIC时,今天所有归因于递归解析器的问题都被消除了。不存在左递归问题,因为$0或更多构造和编程树构造消除了左递归的需要。你可以控制树的构造。一个循环结构被用于t
id .. let $(leter|dgt|+'_');
program = $declarations;
declarations = linkage_decl | data_decl | code_decl;
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|+'_');