首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python中用于聚乙二醇解析器的NodeVisitor类

Python中用于聚乙二醇解析器的NodeVisitor类
EN

Stack Overflow用户
提问于 2019-03-28 19:00:13
回答 2查看 734关注 0票数 3

想象一下以下类型的字符串:

代码语言:javascript
运行
复制
if ((a1 and b) or (a2 and c)) or (c and d) or (e and f)

现在,我想得到括号中的表达式,所以我用以下语法编写了一个PEG解析器:

代码语言:javascript
运行
复制
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*"
    """)

它可以很好地分析

代码语言:javascript
运行
复制
tree = grammar.parse(string)

现在出现了一个问题:如何为这个树编写一个NodeVisitor类来只获取这些因素?我这里的问题是第二个分支,它可以被深嵌套。

我试过

代码语言:javascript
运行
复制
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的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-01 18:38:07

我怎样才能得到((a1和b)或(a2和c))、(c和d)和(e和f)作为三个部分?

当解析树中的节点是(时,您可以创建一个“侦听”访问器,其中深度变量增加,遇到)时,深度变量减少。然后,在与带括号的表达式匹配的方法中,在将其添加到要从访问者返回的表达式列表之前检查深度。

下面是一个简单的例子:

代码语言:javascript
运行
复制
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)

其中的指纹:

代码语言:javascript
运行
复制
((a1 and b) or (a2 and c))
(c and d)
(e and f)
票数 2
EN

Stack Overflow用户

发布于 2019-03-31 20:33:08

如果您只想返回每个最外层的因素,那么return就会提前返回,并且不会下降到它的子元素。

代码语言:javascript
运行
复制
def walk(node, level = 0):
    if node.expr.name == "factor":
        print(level * "-", node.text)
        return
    for child in node.children:
        walk(child, level + 1)

输出:

代码语言:javascript
运行
复制
----- ((a1 and b) or (a2 and c))
----- (c and d)
------ (e and f)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55405055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档