Mika
Mika

Reputation: 61

Pyparsing indentedBlock

I'm trying to use the "indentedBlock" based on the following code:

import pyparsing as pp
import pprint

class Parser(object):
def __init__(self):
    indentStack = [1]
    stmt = pp.Forward()
    start = pp.Word(pp.alphanums + "/" + "\." + "-" + ":" + "!" + "*"+" ")
    funcDecl = (pp.OneOrMore(start)+ pp.restOfLine)
    func_body = pp.indentedBlock(stmt, indentStack)
    funcDef = pp.Group(funcDecl + func_body)
    stmt << (funcDef)
    self.__parser = pp.OneOrMore(stmt)

def parse(self, line):
    try:
        res = self.__parser.parseString(line)
        pprint.pprint(res)
        print("done")
    except pp.ParseException as x:
        print(x)

After applaying i got the following error:

Expected W:(ABCD...) (at char 226), (line:6, col:37)

The main look like:

if __name__ == "__main__":
parser = Parser()

test = """first level config parameter 1-n
 second level config parameter 1-n
  thirt level config parameter 1-n
 second level config parameter 1-n
  thirt level  config parameter 1-n
first level config parameter 1-n"""

print(test)
parser.parse(test)

Any ideas what went wrong

Upvotes: 1

Views: 297

Answers (1)

PaulMcG
PaulMcG

Reputation: 63762

Whitespace-sensitive parsing is always a challenge with pyparsing, given its default behavior of skipping over whitespace. In addition, defining an expression as a Word whose valid characters include ' ' is usually asking for trouble. But since this is being wrapped in an indentedBlock (which will take care of looking for newlines in the right places), you might get away with it here.

I expanded your test string to include some blank lines and some multiple line blocks, and came up with this:

import pyparsing as pp

test = """\
first level config parameter 1-n
 second level config parameter 1-n

  thirt level config parameter 1-n
  thirt level config parameter n+1-m

 second level config parameter 1-n
  thirt level  config parameter 1-n
first level config parameter 1-n"""

import pyparsing as pp

indent_stack = [1]
func_body = pp.Forward()
# what you had as `start` looks like pretty much just any line of characters
stmt = pp.Word(pp.printables + " ")
func_body <<= pp.Group(stmt + pp.indentedBlock(func_body | stmt, indent_stack))

# parse your sample text and output results with pprint
pp.OneOrMore(func_body | pp.Group(stmt)).parseString(test).pprint()

Gives:

[['first level config parameter 1-n',
  [[['second level config parameter 1-n',
     [['thirt level config parameter 1-n'],
      ['thirt level config parameter n+1-m']]]],
   [['second level config parameter 1-n',
     [['thirt level  config parameter 1-n']]]]]],
 ['first level config parameter 1-n']]

Upvotes: 1

Related Questions