我使用狡猾与Python一起分析具有相对简单语法的文本。我想分析的字符串包含来自某个系统的信号名,组合使用AND或or语句。也就是说,有点像,"(SIG1 OR SIG2 OR SIG3 OR SIG4 OR SIG5) AND SIG6"。
这些数据的一个特点是,它将被长长的信号列表所主导。到目前为止,我构建的解析器(见下文)只将OR或操作符理解为二进制,因此输出嵌套的元组,如下所示:('AND', ('OR', ('OR', ('OR', ('OR', 'SIG1', 'SIG2'), 'SIG3'), 'SIG4'), 'SIG5'), 'SIG6')
给定语句或编辑的列表,最好将这些语句组合在任意长度的OR语句中:('AND', ('OR', 'SIG1', 'SIG2', 'SIG3', 'SIG4', 'SIG5'), 'SIG6')
我想我必须编辑Parser,但我想不出如何编辑,并且希望您能给我任何提示。
class BoolLexer(Lexer):
tokens = { ID, LPAREN, RPAREN, AND, OR }
ignore = ' \t\n'
ID = r'[a-zA-Z_\.][a-zA-Z0-9_\.]*'
LPAREN = r'\('
RPAREN = r'\)'
ID['AND'] = AND
ID['OR'] = OR
class BoolParser(Parser):
tokens = BoolLexer.tokens
@_('expr AND term')
def expr(self, p):
return ('AND', p.expr, p.term)
@_('expr OR term')
def expr(self, p):
return ('OR', p.expr, p.term)
@_('term')
def expr(self, p):
return p.term
@_('ID')
def term(self, p):
return p.ID
@_('LPAREN expr RPAREN')
def term(self, p):
return p.expr发布于 2019-04-10 01:58:25
你可以用几种方式做到这一点。如果您想要捕获所有情况(例如,"(SIG1 OR SIG2) OR (SIG3 OR SIG4)"),最直接的方法是先构建一个AST,然后递归地遍历AST,简化每个节点。
您也可以在创建AST节点时进行简化,但这不会捕捉到上面提到的情况:
@_('expr OR term')
def expr(self, p):
if (isinstance(expr, tuple) and expr[0] is "OR"):
return p.expr + (p.term,)
else:
return ('OR', p.expr, p.term)但是,由于第3行的测试,我发现这很难看。一个更干净的解决方案是将语法中的大小写分开。(注意:与您的语法一样,下面给出的AND和OR具有同等的优先级,只需将左向右关联。这不是通常编写布尔表达式的方法。)
@_('and_expr',
'or_expr',
'term)
def expr(self, p):
return p[0]
@_('term OR term')
def or_expr(self, p):
return ('OR', p.term0, p.term1)
@_('or_expr OR term')
def or_expr(self, p):
return p.or_expr + (p.term,)
@_('term AND term')
def and_expr(self, p):
return ('AND', p.term0, p.term1)
@_('and_expr AND term')
def and_expr(self, p):
return p.and_expr + (p.term,)(我从来没有用过诡计,也没有检查过上面的任何代码。如果不管用,请告诉我。)
https://stackoverflow.com/questions/55601228
复制相似问题