如何从ParseResults获取抽象语法树。

3

我正在开发一个翻译器,将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个回答

3
您当前的解析器仅会给您提供一个已解析标记的平面列表,因为在pyparsing中这是默认设置。其目的是无论您如何构建解析器,无论是将其分成较小的部分然后将它们全部组合在一起,还是只用一个巨大的语句,您从解析中获得的标记都是结构化(或非结构化)相同的。要获得类似于AST的东西,您需要使用pyparsing的Group类来定义您想要的结构位置(我建议也使用结果名称)。例如,如果您将语句更改为:
statement = Group(ident("lhs") + '=' + Group(expr)("rhs"))

那么你的输出将更加可预测-每个解析的语句都将有3个顶层元素-目标标识符(可以作为result.lhs访问),'='运算符和源表达式(可以作为result.rhs访问)。源表达式可能具有进一步的结构,但总体上,在每个语句的最顶层始终会有这3个元素。

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

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

你可以像遍历嵌套列表一样浏览解析结果的分层结构。
但我也鼓励您查看pyparsing维基上的SimpleBool示例。在这个示例中,各种解析表达式被呈现为类的实例,然后可以使用访问者或迭代器处理每个类,并且每个类都可以实现自己的特殊逻辑以发出您的字节码。想象一下,您编写了一个典型的解析器来生成AST,然后遍历AST创建CodeGenerator对象,该对象子类化为AssignmentCodeGenerator或IfCodeGenerator或PrintCodeGenerator类,然后遍历此结构以创建您的字节码。相反,您可以在pyparsing中定义赋值、if-then-else或打印语句表达式,让pyparsing直接创建类,然后遍历类以创建字节码。最终,您的代码被整理成不同的语句类型,并且每种类型封装了它应该输出的字节码类型。

非常感谢!SimpleBool是我需要查看的代码的很好的示例。infixNotation是定义表达式的绝佳解决方案。 此外,我不是Python的专家,因此运算符的函数对象对我来说是一种洞察力。 - Mtr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接