Python 识别递归解析器的最外层调用
我需要一些代码只在对递归解析器的最外层调用中运行,但我想不出一种使用pyparsing来实现这一点的方法。这是我的密码:Python 识别递归解析器的最外层调用,python,pyparsing,Python,Pyparsing,我需要一些代码只在对递归解析器的最外层调用中运行,但我想不出一种使用pyparsing来实现这一点的方法。这是我的密码: from pyparsing import * from itertools import count L_PAR, R_PAR, = map(Suppress, '()') def process_stmt(counter): """Closure counts up when nesting occurs""" def parse_action(t
from pyparsing import *
from itertools import count
L_PAR, R_PAR, = map(Suppress, '()')
def process_stmt(counter):
"""Closure counts up when nesting occurs"""
def parse_action(tokens):
for t in tokens:
t["count"] = next(counter)
# if not outermost:
t["outermost"] = False
# if outermost:
# t["outermost"] = True
return parse_action
def outermost_true(tokens):
tokens['outermost'] = True
tokens['other'] = True
counter = count(0)
OR_stmt = Forward()
AND_stmt = Group(OneOrMore(Word("XYZ", exact=3)
^ OR_stmt))("AND*")
AND_stmt.setParseAction(process_stmt(counter))
OR_stmt <<= Group(L_PAR
+ OneOrMore(AND_stmt)
+ R_PAR)("OR*")
OR_stmt.setParseAction(process_stmt(counter))
AND_stmt.addParseAction(outermost_true)
data = "(XXXYYY)ZZZ"
AND_stmt.runTests(data)
如何将最外层的
最外层的属性设置为True
?当我看到您在过程中将最外层的设置为True
或False
时,我想我误解了您的意图。重新阅读您的问题,您希望代码只在对递归解析器的最外层调用中运行。正如我在评论中所猜测的那样,解决方案是创建一个外部转发
容器,并将解析操作附加到该容器上。这是您的代码,其中删除了对进程stmt的所有中间调用,仅对包含转发的中最外层的一个调用:
counter = count(0)
OR_stmt = Forward()
AND_stmt = Group(OneOrMore(Word("XYZ", exact=3)
^ OR_stmt))("AND*")
OR_stmt <<= Group(L_PAR
+ OneOrMore(AND_stmt)
+ R_PAR)("OR*")
outermost = Forward()
outermost <<= AND_stmt
outermost.addParseAction(outermost_true)
data = "(XXXYYY)ZZZ"
outermost.runTests(data)
如果您仍然希望为层次结构的每个级别调用解析操作,我修改了process_stmt以在每次调用时打印其进度:
def process_stmt(counter):
"""Closure counts up when nesting occurs"""
def parse_action(tokens):
for t in tokens:
t["count"] = next(counter)
# t["outermost"] = False
t["outermost"] = (False, "used to be {!r}".format(t.outermost))
tokens['outermost'] = True
print(tokens.dump())
print()
return parse_action
显示这些中间步骤-能够更好地可视化每个调用如何将内部级别最外层
重置为False,将其自身的最外层级别重置为True
[['XXX', 'YYY']]
- AND: [['XXX', 'YYY']]
[0]:
['XXX', 'YYY']
- count: 0
- outermost: (False, "used to be ''")
- outermost: True
[[['XXX', 'YYY']]]
- OR: [[['XXX', 'YYY']]]
[0]:
[['XXX', 'YYY']]
- AND: [['XXX', 'YYY']]
[0]:
['XXX', 'YYY']
- count: 0
- outermost: (False, "used to be ''")
- count: 1
- outermost: (False, 'used to be True')
- outermost: True
[[[['XXX', 'YYY']], 'ZZZ']]
- AND: [[[['XXX', 'YYY']], 'ZZZ']]
[0]:
[[['XXX', 'YYY']], 'ZZZ']
- OR: [[['XXX', 'YYY']]]
[0]:
[['XXX', 'YYY']]
- AND: [['XXX', 'YYY']]
[0]:
['XXX', 'YYY']
- count: 0
- outermost: (False, "used to be ''")
- count: 1
- outermost: (False, 'used to be True')
- count: 2
- outermost: (False, 'used to be True')
- outermost: True
如果将标记[“最外层”]=True
添加到解析操作中,会发生什么情况?这将把每个ParseResults'outermost'设置为True,直到它被封装到另一个ParseAction中,这将把它设置为False。最外层的ParseAction不会发生这种情况,因此将保留设置为True。这似乎有效。但我不明白为什么它会起作用。我的理解是,操作是按照添加的顺序执行的。预期的结果是,setParseAction将outermost设置为False,然后addParseAction将其重置为True。我在这里遗漏了什么?这种方法在每次调用中都会做一些事情,而问题是它是否可以这样做,以便只在最外层的调用中执行。这里重要的不是解析操作的顺序,而是解析执行的顺序(另外,我看不到哪里有对addParseAction
-???)的调用。与@goodahn的评论相反,您正在进行自底向上的解析,因此当每个级别的解析操作运行时,它们将其级别设置为“我是最外层的”,所有较低级别设置为“我不是最外层的”。解析顶级时,没有更高的级别将其设置为“非最外层”,因此它保持为“我是最外层”。或者创建一个outermost=Forward()
,向该级别添加一个解析操作,将“outermost”指定为True,执行outermost
def process_stmt(counter):
"""Closure counts up when nesting occurs"""
def parse_action(tokens):
for t in tokens:
t["count"] = next(counter)
# t["outermost"] = False
t["outermost"] = (False, "used to be {!r}".format(t.outermost))
tokens['outermost'] = True
print(tokens.dump())
print()
return parse_action
[['XXX', 'YYY']]
- AND: [['XXX', 'YYY']]
[0]:
['XXX', 'YYY']
- count: 0
- outermost: (False, "used to be ''")
- outermost: True
[[['XXX', 'YYY']]]
- OR: [[['XXX', 'YYY']]]
[0]:
[['XXX', 'YYY']]
- AND: [['XXX', 'YYY']]
[0]:
['XXX', 'YYY']
- count: 0
- outermost: (False, "used to be ''")
- count: 1
- outermost: (False, 'used to be True')
- outermost: True
[[[['XXX', 'YYY']], 'ZZZ']]
- AND: [[[['XXX', 'YYY']], 'ZZZ']]
[0]:
[[['XXX', 'YYY']], 'ZZZ']
- OR: [[['XXX', 'YYY']]]
[0]:
[['XXX', 'YYY']]
- AND: [['XXX', 'YYY']]
[0]:
['XXX', 'YYY']
- count: 0
- outermost: (False, "used to be ''")
- count: 1
- outermost: (False, 'used to be True')
- count: 2
- outermost: (False, 'used to be True')
- outermost: True