4

I'm trying to parse a simple language. The trouble comes with parsing function calls. I'm trying to tell it that a function call is an expression followed by left parenthesis, argument list, and right parenthesis. I have something like this:

expr = Forward()
iden = Word(alphas+'_', alphanums+'_')
integer = Word(nums)
binop = operatorPrecedence(expr, ...) # irrevelant
call = expr + Literal('(') + delimitedList(expr) + Literal(')')
expr << call | integer | iden

The problem is obvious: expr is left-recursive. However, I can't figure what to do to solve this. I'm experienced with right-recursive-style grammars(a.k.a. PLY, Yacc, etc.) but am still trying to figure out left-recursive grammars.

kirbyfan64sos
  • 10,377
  • 6
  • 54
  • 75
  • To parse an immediately-left-recursive production in an LL parser, you need to either (a) convert it to a weakly-equivalent right-recursive production, or (b) write an explicit disambiguation or curtailment algorithm. (Or, of course, you can weaken the production so that a call can't start with any `expr`, only with a sub-production of `expr`.) I don't know `pyparsing` well enough to know if (b) is an option. – abarnert Jul 23 '14 at 00:30
  • I think there are PyParsing examples for various versions of Python, which basically uses option (c). IIRC, in early 2.x (which is probably the simplest) a `call` was an `atom` (not an `expr`) followed by a parenthesized `arglist`, and produced a `power` (not an `expr`). Just figure out where in the precedence you want call expressions to go, split the `operatorPrecedence` group into the half about that and the half below that, and explicitly put the call in between. (But, you know, actually look at the pyparsing examples or Python grammar rather than trusting my memory.:)) – abarnert Jul 23 '14 at 00:35
  • So in this language, "36(21)" is a valid function call? – PaulMcG Jul 23 '14 at 06:26
  • 1
    @PaulMcGuire: Technically not, but that would be found out *after* parsing, when the code is checked. It *is* syntactically valid, however. – kirbyfan64sos Jul 23 '14 at 19:48

1 Answers1

3
Functionname = Word(alphanums + '_')
functionbody = Forward()
functionbody <<=  Functionname + (Literal("(") +
Optional( delimitedList ( functionbody | Word(alphanums + '_') | "''"),'')
+ Literal(")"))
rajender kumar
  • 412
  • 3
  • 12