Python 循环语法中的自动构建AST
我正在为过程演算开发一个解析器。我正在使用自动创建带有已解析对象的AST树 我的问题是,由于语法在结果树中的递归性质,我得到了解析文本中不存在的对象(AST节点) i、 e 对于Python 循环语法中的自动构建AST,python,parsing,python-3.x,pyparsing,Python,Parsing,Python 3.x,Pyparsing,我正在为过程演算开发一个解析器。我正在使用自动创建带有已解析对象的AST树 我的问题是,由于语法在结果树中的递归性质,我得到了解析文本中不存在的对象(AST节点) i、 e 对于A=A.b我得到 [Procdef:{'rest':([Choice:{'lhs':([Prefix:{'lhs':(['a'],{}),'rhs':([Prefix:{'lhs':(['b'],{}),'rhs':([],{}]),{},{}),'rhs':([],{}),'proc':'a'> 但我希望这是: [Pr
A=A.b
我得到
[Procdef:{'rest':([Choice:{'lhs':([Prefix:{'lhs':(['a'],{}),'rhs':([Prefix:{'lhs':(['b'],{}),'rhs':([],{}]),{},{}),'rhs':([],{}),'proc':'a'>
但我希望这是:
[Procdef:{'rest':([Prefix:{'lhs':(['a'],{}),'rhs':([Prefix:{'lhs':(['b'],{}),'rhs':([],{}]),{}),'proc':'a'>
这里的区别在于缺少选择
节点。在我过去的项目中,我使用自己的AST结构和传递给setParseAction
的函数,然后我只需检查rhs是否为null并传递令牌。当物体经过时,我不知道怎么做
简化代码如下:
#!/usr/bin/env python
from pyparsing import *
class ASTNode(object):
def __init__(self, tokens):
self.tokens = tokens
self.assignFields()
def __str__(self):
return self.__class__.__name__ + ":" + str(self.__dict__)
__repr__ = __str__
class Procdef(ASTNode):
def assignFields(self):
self.proc, self.rest = self.tokens
del self.tokens
class Choice(ASTNode):
def assignFields(self):
self.lhs, self.rhs = self.tokens
del self.tokens
class Prefix(ASTNode):
def assignFields(self):
self.lhs, self.rhs = self.tokens
del self.tokens
class RasParser(object):
def grammar(self):
prefix_op = Literal('.').suppress()
choice_op = Literal('+').suppress()
lpar = Literal('(').suppress()
rpar = Literal(')').suppress()
define = Literal('=').suppress()
Ident = Word(alphas.upper(), alphanums + "_")
ident = Word(alphas.lower(), alphanums + "_")
choice = Forward()
prefix = Forward()
process = ident | lpar + choice + rpar
prefix << Group(process) + Group(ZeroOrMore(prefix_op + prefix))
choice << Group(prefix) + Group(ZeroOrMore(choice_op + prefix))
rmdef = Ident + define + Group(choice)
rmdef.setParseAction(Procdef)
prefix.setParseAction(Prefix)
choice.setParseAction(Choice)
ras = ZeroOrMore(rmdef)
return ras
def parse(self, string):
oo = self.grammar().parseString(string, parseAll=True).asList()
print(oo)
if __name__ == "__main__":
p = RasParser()
model = "A = a.b"
print(model)
p.parse(model)
#/usr/bin/env python
从pyparsing导入*
类节点(对象):
定义初始化(自我,令牌):
self.tokens=令牌
self.assignFields()
定义(自我):
返回self.\uuuuu类\uuuuu.\uuuuu名称\uuuuuuuu+“:”+str(self.\uuuuu dict)
__repr\uuuuu=\uuuuuu str__
类Procdef(ASTNode):
def分配字段(自):
self.proc,self.rest=self.tokens
del self.tokens
类选择(ASTNode):
def分配字段(自):
self.lhs,self.rhs=self.tokens
del self.tokens
类前缀(ASTNode):
def分配字段(自):
self.lhs,self.rhs=self.tokens
del self.tokens
类分析器(对象):
定义语法(self):
前缀_op=Literal('.')。suppress()
choice_op=Literal(“+”).suppress()
lpar=Literal(“(”).suppress()
rpar=Literal(')。suppress()
define=Literal('=')。suppress()
Ident=单词(alphas.upper(),alphanums+“”)
ident=单词(alphas.lower(),alphanums+“”)
选择=前进()
前缀=转发()
进程=标识| lpar+choice+rpar
前缀实际上,这些元素在表达式中,它们只是退化版本(没有运算符的单操作数)。递归定义意味着单个进程将被解析为退化前缀(不带运算符的前缀),而反过来又被解析为退化选择(不带运算符的选择)
您已经以右关联的方式定义了前缀。如果您的意思是左联想,那么它应该是:前缀
choice = infixNotation(process,
[
('.', 2, opAssoc.LEFT, Prefix),
('+', 2, opAssoc.LEFT, Choice),
]
rmdef = ident("destination") + define + choice("rhs")