问题:
什么是Zephyr ASDL以及它如何与词法分析器和解析器生成器等其他编译器技术相关?
(我很感激你,如果你是相当完整的,但是当它变得技术性时指向其他在线参考,因为我对编译器的大部分知识来自于使用yacc和flex,在C中编写一个简单的最大munch lexer ,在网上查阅和阅读内容)
问题背景:
我一直在阅读http://docs.python.org/devguide/compiler.html,我遇到了以下几行:
使用Zephyr指定AST节点的规范 抽象语法定义语言(ASDL)。
我按照底部的引文查找: http://www.cs.princeton.edu/research/techreps/TR-554-97
我对文章的第一次阅读相当混乱,我希望在再次尝试之前,我可以先了解ASDL的目的(在编译过程的背景下)。
答案 0 :(得分:7)
Lexer和Parser生成器接受词位和语法的描述,并生成实现相应工件的代码。 Lex需要一个正则表达式来描述令牌。解析器生成器采用各种扩展的BNF表示法。
你引用的论文非常清楚恕我直言:ASDL是一种用于抽象地描述一组树节点(它们的类型和签名)的语言。使用这种语言,人们可以编写(并且论文的作者这样做)一个工具,将这些描述转换为您需要实现与解析器一起使用的树所需的记录类型集。所以ADSL有点像Regexes和BNF,因为它的目的是提供给生成编译器一部分的代码生成器。
一个广阔的观点是,编译器是一种非常容易理解的技术,并且应该能够从各种部分的描述中生成它们。 Regex / BNF / ADSL是解析阶段的关键。
您理想地喜欢目标指令集的描述语言,流分析,从抽象树到目标指令集的翻译(您提到的最大munch),以及描述优化的方法。然后使用每个部分的相应工具,您可以从“规范”构建整个编译器。有 实际上在这方面做了很多工作;人们已经分开并一起完成了所有这些。不出所料,其中一些来自以前出自普林斯顿的“Zephyr”项目(似乎Zephyr网站现在已经死了),其目标是做这种事情。
无论如何,请尝试在Google Scholar下查找“编译器生成器”。
答案 1 :(得分:1)
当您需要在模块中生成树并在其他模块(或几乎相同的树中,以某种方式进行优化)中输入相同的树时,使用ASDL。
为此,您需要具有构造功能(理想情况下使用类型检查器),打印树的功能,以便可视化它,确保您正确生成它。
ASDL将一些树的语法编写为几乎与代数数据类型的语法相似(如haskell或ml),或者BNF中的语法更简化,并自动生成所有的构造函数,打印函数从树的简单描述开始。
例如,如果您有词法分析器,则必须生成具有类型的词法。您还需要查看lexemes的输出流(这是线性形式,因此是一个非常简单的树)。不是编写用于打印的函数,而是构造lexemes,而是将它们定义为类似
lexeme=
ID(STRING)
| INT(num_integer)
| FLOAT(num_float)
attributes(int coord_x, int coord_y)
num_integer:
....
num_float:
....
并从词法分析器中调用构造函数ID,INT,FLOAT等。 ASDL将在您需要的所有函数中转换这个简单的语法,要么为AST构建节点,要么打印,或者您需要的任何东西。 ASDL不对生成的代码施加限制。
如果将attributes
添加到某个类型(例如标记的坐标),则会将此类属性附加到该类型的每个构造函数的参数中。
由解析器创建的更复杂的树看起来像
expr: SUM(expr, expr)
|PRODUCT(expr, expr)
|number
number: num_integer
在这种情况下,asdl将检查解析器对SUM(_ _)的调用是否将传递给使用expr的一个构造函数创建的求和节点。 num_integer
在外部定义,可能是词法分析器的asdl树。
请注意,不允许定义包含正则表达式的构造函数,例如number: [0-9]+
。 ASDL比EBNF简单。
这些构造函数将被定义为构建您需要的东西,而不仅仅是它们,它们键入check,以确保您的词法分析器/解析器/代码生成器输出符合asdl定义的语言的树。
为了更好地理解ASDL,您需要编写3-4个解析器,并查看它们生成的代码中的常见内容。这个公共部分实际上是ASDL,因此这是解析器输出的抽象。
答案 2 :(得分:0)
您的问题是关于具体语法和抽象语法之间的区别。
像 Zephyr 一样的 ASDL 是关于如何为抽象语法描述这组类,而不是语法本身。
一旦类集被完全描述(甚至生成),它就可以在解析器中使用,从而详细说明 AST。