Python中PEG解析器的NodeVisitor类 [英] NodeVisitor class for PEG parser in Python
问题描述
想象一下以下类型的字符串:
Imagine the following types of strings:
if ((a1 and b) or (a2 and c)) or (c and d) or (e and f)
现在,我想用括号括起来,所以我用以下语法编写了PEG
解析器:
Now, I'd like to get the expressions in parentheses, so I wrote a PEG
parser with the following grammar:
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
类以仅获取因数?我的问题是可以深度嵌套的第二个分支.
我尝试过
Now the question arises: how to write a NodeVisitor
class for this tree to get only the factors? My problem here is the second branch which can be deeply nested.
I tried with
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)
但实际上无济于事(因素重复出现).
注意:此问题基于 另一个一个 .
but to no avail, really (factors bubble up in duplicates).
Note: This question is based on another one on StackOverflow.
推荐答案
我将如何获得((a1和b)或(a2和c)),(c和d)以及(e和f)三个部分?
How would I go about it to get ((a1 and b) or (a2 and c)), (c and d) and (e and f) as three parts?
您可以创建一个访问者,该访问者在分析树中的节点为(
时会监听",其中深度变量会增加,而遇到)
时会降低深度变量.然后,在与括号表达式匹配的调用方法中,在将深度添加到表达式列表以从访问者返回之前,先检查深度.
You could create a visitor that "listens" when a node in the parse tree is a (
, in which a depth-variable is increased, and when a )
is encountered, the depth-variable is decreased. Then in the method that is called that matches a parenthesised expression, you inspect the depth before adding it to your list of expressions to return from the visitor.
这里是一个简单的例子:
Here a is a quick example:
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)
这篇关于Python中PEG解析器的NodeVisitor类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!