[Python] How do I parse ambiguous indented blocks like this using pyparsing?

Discussão em 'Python' iniciado por Stack, Abril 14, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to parse data in the following format:

    data = """\
    map=1
    sub=1
    int=99
    foo=bar
    sub=2
    foo=bar
    int=99
    bar=qux
    """


    I based my grammar on the example from the pyparsing repository and this is what I got:

    from pyparsing import *


    stmt = Forward()
    suite = IndentedBlock(stmt)
    identifier = Word(alphas, alphanums)
    key = Combine(identifier + "=" + Word(nums))
    definition = key + suite

    rhs = Regex(r"[a-z0-9]+")
    lhs = identifier + Suppress("=") + rhs
    stmt << (definition | lhs)

    body = ZeroOrMore(stmt)

    # run it

    tree = body.parse_string(input_string)
    print(tree)


    The resulting parse-tree is almost correct:

    ['map=1', ['sub=1', ['int=99', ['foo', 'bar']], 'sub=2', ['foo', 'bar', 'int=99', ['bar', 'qux']]]]


    Since the map/submap keys contain an integer index postfix, e.g. =1, they are syntactically the same as integer assignments. This causes the parser to treat key-value pairs after an integer assignment as a new indented block.

    The desired outcome, however, is something like

    ['map=1', ['sub=1', ['int', '99', 'foo', 'bar'], ['sub=2', ['foo', 'bar', 'int', '99', 'bar', 'qux']]


    How can I eliminate this ambiguity? Some kind of negative lookahead, perhaps?

    Continue reading...

Compartilhe esta Página