如何从 ParseResults 获取抽象语法树

How to acquire Abstract Syntax Tree from ParseResults

我正在开发一个翻译器,用于将 PC 上的简单脚本翻译成一些字节码,以便在微控制器上执行它(字节码)。

我已经使用 lex 和 re2c 在 C++ 中开发了翻译器,但我正在考虑切换到 pyparsing。

为了将我的脚本语句转换为字节码中的几个操作,我需要获取该语句的抽象语法树。

即这个脚本:

X = 1 - 2;

应翻译成二进制等价物:

register1 <- 1
register2 <- 2
register3 <- register1 - register2
x <- register3

我有这个 python 代码:

integer = Combine( number )
ident = Word(alphas,alphanums) 

expr = Forward()
atom = ( integer | 
         ( lpar + expr.suppress() + rpar )
       )
expr << ( atom + (addop | multop) + atom )

statement = ident + assign + expr


L = statement..parseString( line )

有没有访问L中AST的叶子的例子?或者类似的东西...

提前致谢

您当前的解析器只会给您一个已解析标记的简单列表,因为这是 pyparsing 中的默认设置。这样做的目的是,无论您如何构建解析器,无论是分成较小的部分然后将它们全部放在一起,还是只放在一个巨大的语句中,您从解析中获得的标记都是结构化的(或非结构化的)。要获得类似于 AST 的东西,您需要使用 pyparsing 的组 class 定义您想要的结构(我也建议使用结果名称)。因此,例如,如果您将语句更改为:

statement = Group(ident("lhs") + '=' + Group(expr)("rhs"))

那么您的输出将更加可预测 - 每个解析的语句都会有 3 个顶级元素 - 目标标识符(可寻址为 result.lhs),'=' 运算符和源表达式(可寻址如 result.rhs)。源表达式可能有更多的结构,但总的来说,在每个语句的最顶层总是有这 3 个。

为确保在计算 expr 时保留 RHS 表达式中的括号组,请再次使用组:

atom = (integer | Group(lpar + expr + rpar))

您可以在解析结果的层次结构中导航,就好像您在嵌套列表中行走一样。

但我也鼓励您查看 SimpleBool example on the pyparsing wiki。在这个例子中,各种解析的表达式被渲染成 classes 的实例,然后可以使用访问者或迭代器进行处理,然后每个 class 可以实现自己的特殊逻辑来发出你的字节码.想象一下,您已经编写了一个典型的解析器来生成 AST,然后遍历 AST 以创建 CodeGenerator 对象,这些对象子 class 进入 AssignmentCodeGenerator 或 IfCodeGenerator 或 PrintCodeGenerator classes,然后遍历此结构以创建您的字节码.相反,您可以在 pyparsing 中定义赋值、if-then-else 或打印语句表达式,让 pyparsing 直接创建 classes,然后遍历 classes 以创建字节码。最后,你的代码被整齐地组织成不同的语句类型,每种类型都封装了它应该输出的字节码类型。