Skip to content

Backtracking #75

@Kodiologist

Description

@Kodiologist

It looks like funcparserlib has no way to allow backtracking, in the manner of Parsec's try. #43 provides one example of where you might want this. I found myself wanting it in changing Hy to parse dfor forms like this (hylang/hy#2324):

(dfor  x (range 10)  y (range 3)  #(x y) (* x y))

It would be the equivalent of this Python:

{(x, y): x*y  for x in range(10)  for y in range(3)}

dfor and friends in Hy have a relatively complicated parser, so here's a simplified example:

from collections import namedtuple
from funcparserlib.parser import tok, many, finished
from funcparserlib.lexer import Token

FORM = tok('FORM')

loopers = many(FORM + FORM)

lfor = loopers + FORM + finished
dfor = loopers + FORM + FORM + finished

def f(parser, ts):
    return parser.parse([Token(t, 1) for t in ts.split()])

print(f(lfor, 'FORM FORM  FORM FORM  FORM'))
print(f(dfor, 'FORM FORM  FORM FORM  FORM FORM'))

Here the example with lfor returns ([(1, 1), (1, 1)], 1, None), as desired, but for dfor, I get funcparserlib.parser.NoParseError: got unexpected end of input, expected: FORM. The problem is that loopers consumes all the FORM FORM pairs and doesn't try moving back one iteration of many to give the final FORM + FORM + finished in dfor a chance to match.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions