Create function calls to returned functions parser in PyParsing

153 views Asked by At

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??

1

There are 1 answers

0
mmmm1998 On

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']]