NodeVisitor class for PEG parser in Python

佐手、 提交于 2019-11-28 14:02:00

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)

which prints:

((a1 and b) or (a2 and c))
(c and d)
(e and f)

If you only want to return each outermost factor, return early and do not descend into its children.

def walk(node, level = 0):
    if node.expr.name == "factor":
        print(level * "-", node.text)
        return
    for child in node.children:
        walk(child, level + 1)

Output:

----- ((a1 and b) or (a2 and c))
----- (c and d)
------ (e and f)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!