Python – pyparsing Does it know the depth of the recursive expression when parsing?

pyparsing Does it know the depth of the recursive expression when parsing?… here is a solution to the problem.

pyparsing Does it know the depth of the recursive expression when parsing?

I

like the ability to define parseAction using pyarsing, but I run into roadblocks for specific use cases. Get the input string and the following simple syntax:

from pyparsing import *

line = "[[one [two [three] two [three [four]]] one] zero]"
token = Word(alphas)

# Define the simple recursive grammar
grammar = Forward()
nestedBrackets = nestedExpr('[', ']', content=grammar) 
grammar << (token | nestedBrackets)

P = grammar.parseString(line)
print P

I hope it turns out:

[('one',1), [('two',2), [('three',3)], ('two',2), [('three',3), [('four',4)]]] one], ('zero',0)]

That is, each token is parsed and a tuple containing the token and depth is returned. I know this can be done after parsing, but I’m wondering if it can be done using parseAction. This is my wrong attempt with global variables :

# Try to count the depth
counter = 0
def action_token(x):
    global counter
    counter += 1
    return (x[0],counter)
token.setParseAction(action_token)

def action_nest(x):
    global counter
    counter -= 1
    return x[0]
nestedBrackets.setParseAction(action_nest)

Give:

[('one', 1), ('two', 2), ('three', 3), ('two', 3), ('three', 4), ('four', 5), ('one', 3), ('zero', 3)]

Solution

Do this (keep the rest):

def openB(s, l, t):
    global count
    count += 1
def closeB(s, l, t):
    global count
    count -= 1

opener = Literal("[").setParseAction(openB)
closer = Literal("]").setParseAction(closeB)

nestedBrackets = nestedExpr(opener, closer, content=grammar) 

The problem is that nesting does not depend on the number of nested groups matched, but on the number of open parentheses matched and the number of closed brackets matched. Therefore, you need to adjust the count when parsing open/close parentheses, not when parsing the group. Therefore, you need to set parseAction on the group delimiter, not the group itself.

Also, your example is nested one layer (at least in my opinion). “Zero” should actually be one, because it’s inside a layer of parentheses, and again, everything else should be moved up one by one. If you really want the outermost “zero” to have a zero level and so on, you need to initialize the count to -1.

Related Problems and Solutions