想象一下以下类型的字符串:
if ((a1 and b) or (a2 and c)) or (c and d) or (e and f)现在,我想得到括号中的表达式,所以我用以下语法编写了一个PEG解析器:
from parsimonious.grammar import Grammar
grammar = Grammar(
r"""
program = if expr+
expr = term (operator term)*
term = (factor operator factor) / factor
factor = (lpar word operator word rpar) / (lpar expr rpar)
if = "if" ws
and = "and"
or = "or"
operator = ws? (and / or) ws?
word = ~"\w+"
lpar = "("
rpar = ")"
ws = ~"\s*"
""")它可以很好地分析
tree = grammar.parse(string)现在出现了一个问题:如何为这个树编写一个NodeVisitor类来只获取这些因素?我这里的问题是第二个分支,它可以被深嵌套。
我试过
def walk(node, level = 0):
if node.expr.name == "factor":
print(level * "-", node.text)
for child in node.children:
walk(child, level + 1)
walk(tree)但没有效果,真的(因素大量涌现)。
注意:这个问题是基于https://stackoverflow.com/questions/55383691/get-all-parts-of-a-parenthesisfull-expression/55384114#55384114 on StackOverflow的。
发布于 2019-04-01 18:38:07
我怎样才能得到((a1和b)或(a2和c))、(c和d)和(e和f)作为三个部分?
当解析树中的节点是(时,您可以创建一个“侦听”访问器,其中深度变量增加,遇到)时,深度变量减少。然后,在与带括号的表达式匹配的方法中,在将其添加到要从访问者返回的表达式列表之前检查深度。
下面是一个简单的例子:
from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
grammar = Grammar(
r"""
program = if expr+
expr = term (operator term)*
term = (lpar expr rpar) / word
if = "if" ws
and = "and"
or = "or"
operator = ws? (and / or) ws?
word = ~"\w+"
lpar = "("
rpar = ")"
ws = ~"\s*"
""")
class ParExprVisitor(NodeVisitor):
def __init__(self):
self.depth = 0
self.par_expr = []
def visit_term(self, node, visited_children):
if self.depth == 0:
self.par_expr.append(node.text)
def visit_lpar(self, node, visited_children):
self.depth += 1
def visit_rpar(self, node, visited_children):
self.depth -= 1
def generic_visit(self, node, visited_children):
return self.par_expr
tree = grammar.parse("if ((a1 and b) or (a2 and c)) or (c and d) or (e and f)")
visitor = ParExprVisitor()
for expr in visitor.visit(tree):
print(expr)其中的指纹:
((a1 and b) or (a2 and c))
(c and d)
(e and f)发布于 2019-03-31 20:33:08
如果您只想返回每个最外层的因素,那么return就会提前返回,并且不会下降到它的子元素。
def walk(node, level = 0):
if node.expr.name == "factor":
print(level * "-", node.text)
return
for child in node.children:
walk(child, level + 1)输出:
----- ((a1 and b) or (a2 and c))
----- (c and d)
------ (e and f)https://stackoverflow.com/questions/55405055
复制相似问题