如何从ParseResults获取抽象语法树

时间:2015-11-06 16:56:19

标签: python pyparsing

我正在开发一个翻译器,用于将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的叶子的例子?或类似的东西...

提前致谢

1 个答案:

答案 0 :(得分:2)

您当前的解析器只会为您提供已解析令牌的平面列表,因为这是pyparsing中的默认值。目的是这样,无论你如何构建解析器,无论是小块还是将它们放在一起,或者只是在一个巨大的语句中,你从解析中得到的标记都是相同的结构化(或非结构化)。要获得类似于AST的东西,您需要使用pyparsing的Group类定义您想要的结构(我建议也使用结果名称)。例如,如果您将语句更改为:

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

然后你的输出将更加可预测 - 每个解析的语句将有3个顶级元素 - 目标标识符(可以作为result.lhs寻址),&#39; =&#39;运算符和源表达式(可作为result.rhs寻址)。源表达式可能具有进一步的结构,但总体而言,在每个语句中最高级别总是会有这3个。

要确保在评估expr时保留RHS表达式中的括号组,请再次使用组:

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

您可以浏览已解析结果的层次结构,就像您正在遍历嵌套列表列表一样。

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