Reputation: 615
I want to parse function calls that can call functions 'returned' by other functions:
thisReturnsFunction()()
I have done this:
id = Regex(r'[_a-zA-Z][_a-zA-Z0-9]*')
funcal = Forward()
value = funcal | id
funcal << value + Literal("(").suppress() + Literal(")").suppress()
Accidentally, Python stack overflows and the whole Python crashes.
I know that the value
is recursive and matches infinitely thisReturnsFunction("Hello!")
, because the funcal
is matching, because the value
is mathing, because the funcal
is matching...
How to avoid that and design valid pattern??
Upvotes: 1
Views: 143
Reputation: 1
I am not sure, that Pyparsing can parse high-order function in 'pure' way. But there are some 'hacky' way: create token for function, add handler for the token and make correct syntax structure inside the handler. Example (I also add tokens for function arguments)
from pyparsing import Forward, Literal, Regex, OneOrMore, Optional, Group, delimitedList
def function_parser(s, loc, toks):
if len(toks) <= 2:
return [toks[0], list(toks[1])]
else:
return [function_parser(s, loc, toks[:len(toks)-1]), toks[-1]]
id = Regex(r'[_a-zA-Z][_a-zA-Z0-9]*')
comma = Literal(',')
funcal = Forward()
expression = funcal | id
function_args = Optional(Group(delimitedList(expression,comma)),[])
funcal << id + OneOrMore(Literal("(").suppress() + function_args + Literal(")").suppress())
funcal.setParseAction(function_parser)
def test_print(string):
l = funcal.parseString(string).asList()
print(l)
test_print('justFunction(arg)')
test_print('justFunction(arg)',)
test_print('thisReturnsFunction()()',)
test_print('thisReturnsFunction(arg1, arg2)(arg3)')
It produces:
['justFunction', ['arg']]
['justFunction', ['arg']]
[['thisReturnsFunction', []], []]
[['thisReturnsFunction', ['arg1', 'arg2']], ['arg3']]
Upvotes: 0