Python Zephyr ASDL(抽象语法描述语言)

Python Zephyr ASDL(抽象语法描述语言),python,syntax,compiler-construction,definition,asdl,Python,Syntax,Compiler Construction,Definition,Asdl,问题: Zephyr ASDL是什么?它与其他编译器技术(如lexer和解析器生成器)有何关联 (如果您能合理地完成,我将不胜感激,但当它变得相当技术化时,请在网上指向其他参考资料,因为我所知道的关于编译器的大部分知识都来自于使用yacc和flex,用C编写一个简单的Maximum munch lexer,以及在线查找和阅读资料) 问题背景: 我一直在阅读,我遇到了以下几行: AST节点的规范是使用Zephyr指定的 抽象语法定义语言(ASDL) 我根据底部的引文找到: 我对这篇文章的第一次阅

问题:

Zephyr ASDL是什么?它与其他编译器技术(如lexer和解析器生成器)有何关联

(如果您能合理地完成,我将不胜感激,但当它变得相当技术化时,请在网上指向其他参考资料,因为我所知道的关于编译器的大部分知识都来自于使用yacc和flex,用C编写一个简单的Maximum munch lexer,以及在线查找和阅读资料)

问题背景:

我一直在阅读,我遇到了以下几行:

AST节点的规范是使用Zephyr指定的 抽象语法定义语言(ASDL)

我根据底部的引文找到:


我对这篇文章的第一次阅读相当混乱,我希望在再次尝试之前,我能首先更好地理解ASDL的目的(在编译过程中)。Lexer和Parser生成器接受词素和语法的描述,并生成实现相应工件的代码。Lex需要一个正则表达式来描述标记。解析器生成器采用各种扩展的BNF符号

您引用的论文非常清楚,IMHO:ASDL是一种抽象描述一组树节点(它们的类型和签名)的小语言。使用这种语言,人们可以编写(论文作者也这样做了)一个工具,将这些描述转换为一组记录类型,您需要实现与解析器一起使用的树。所以ADSL有点像Regexes和BNF,因为它的目的是提供给产生编译器一部分的代码生成器

一种广泛的观点是,编译器是一种非常容易理解的技术,应该能够从各种片段的描述中生成它们。Regex/BNF/ADSL是解析阶段的关键

理想情况下,您需要目标指令集的描述语言、流分析、从抽象树到目标指令集的转换(您提到的maximalmunch),以及描述优化的方法。然后为每一部分使用相应的工具,您可以根据“规范”构建整个编译器。有 实际上在这方面做了很多工作;人们分别和共同完成了所有这些工作。不足为奇的是,其中一些来自以前普林斯顿大学的“西风”项目(那里的西风网站现在似乎已经死了),其目标就是做这类事情


无论如何,请尝试在Google Scholar下查找“编译器生成器”。

当您需要在模块中生成树并在其他模块中输入相同的树(或几乎相同的树,经过某种优化)时,将使用ASDL

为此,您需要具有构造功能(最好是使用类型检查器),打印树的功能,以便可视化树,确保正确生成树

ASDL将一些树作为输入,这些树的语法与代数数据类型的语法(如haskell或ml)或BNF中的语法几乎相同,但要简单得多,并且自动生成所有构造函数,从树的简单描述开始打印函数

例如,如果您有一个词素分析器,它将必须生成具有类型的词素。您还需要查看词素的输出流(这是线性形式,因此是一个非常简单的树)。不是编写用于打印、构造词素的函数,而是这样定义它们

   lexeme=
       ID(STRING)
     | INT(num_integer)
     | FLOAT(num_float)
     attributes(int coord_x, int coord_y)
   num_integer:
     ....
   num_float:
     ....
expr:  SUM(expr, expr)
      |PRODUCT(expr, expr)
      |number
number: num_integer
从lexer调用构造函数ID、INT、FLOAT等。ASDL将在您需要的所有函数中转换此简单语法,用于为AST构造节点、打印或任何您需要的功能。ASDL不会对生成的代码施加限制

如果将
属性
添加到某个类型,例如标记的坐标,则此类属性将附加到该类型的每个构造函数的参数中

由解析器创建的更复杂的树如下所示

   lexeme=
       ID(STRING)
     | INT(num_integer)
     | FLOAT(num_float)
     attributes(int coord_x, int coord_y)
   num_integer:
     ....
   num_float:
     ....
expr:  SUM(expr, expr)
      |PRODUCT(expr, expr)
      |number
number: num_integer
在这种情况下,asdl将检查解析器对SUM()的调用是否会传递给使用expr的一个构造函数创建的SUM节点
num_integer
是外部定义的,可能是由lexer的asdl树定义的

请注意,不允许定义包含正则表达式的构造函数,例如
number:[0-9]+
。ASDL比EBNF简单

这些构造函数将被定义为,为了构建您所需要的以及更多的内容,它们将键入check,以确保您的lexer/parser/code生成器输出符合asdl定义的语言的树


为了更好地理解ASDL,您需要编写3-4个解析器,并查看它们生成的代码中的共同点。这个公共部分实际上是ASDL,因此这是对解析器输出的一个抽象。

您的问题是关于具体语法和抽象语法之间的区别

  • 当您使用编程语言时,具体语法是您知道并需要尊重的语法。解析器也会验证这种具体语法,检查您是否尊重语法语言。解析器还有第二个角色,对程序员来说是隐藏的:在内存中构建一个专用的数据结构,代表您的输入源。许多算法将应用于此数据结构。这种数据结构被命名为“抽象语法树”
  • 抽象语法:这是一组类(在面向对象的范例中或在函数范例中是类型),AST是从这些类中详细阐述的。例如,您可能有一个名为“Program”的类,它捕获了程序组成的本质。您还可以有一个“If”类,它表示“If”语句的结构(由一个条件、一个规则体和可能的第二个“else”部分组成)
像西风一样的ASDL