[antlr-interest] Method Invocation Rule (expr.methodname()) causing mutually left-recursive grammar

Michael Cooper tillerman35 at yahoo.com
Mon Oct 29 08:45:43 PDT 2012


I'm getting the dreaded "mutually left-recursive" error.  It started when I tried to add method invocations to the mix.


What I would like is method invocations like "variable.method(arg1, arg2, arg3)" and to be able to "chain" them together like in java ("whateverwhatever".length().tostring().length().tostring().length()" returning 2

Here is the grammar snippet.  Any help is appreciated.


atom[boolean eval_now] returns [InterpValue value]
  : varname=IDENTIFIER //Return an ival with the type & value of a scalar variable
    { if($eval_now && interp.getContinueStatus()==0) $value=interp.getScalarValueByName($varname.text); }
  | varname=IDENTIFIER '[' key_or_index=expr[eval_now] ']' //Return an ival containing the scalar type & value at the given index of an array variable, key of a map variable, or name or index of a record column
    { if($eval_now && interp.getContinueStatus()==0) $value=interp.getScalarValueByKeyOrIndex($varname.text,$key_or_index.value); }
  | varname=IDENTIFIER '.' membername=IDENTIFIER //Return an ival containing the scalar type & value at the given index of an array variable or key of a map variable
    { if($eval_now && interp.getContinueStatus()==0) $value=interp.getScalarValueByMemberName($varname.text,$membername.text); }
  | BOOLEAN_LITERAL //Convert literal to an ival of type boolean with given "true" or "false" value
    { if($eval_now && interp.getContinueStatus()==0) $value = new InterpValue("boolean",$BOOLEAN_LITERAL.text); } 
  | INTEGER_LITERAL //Convert literal to an ival of type integer with given numeric value
    { if($eval_now && interp.getContinueStatus()==0) $value = new InterpValue("integer",$INTEGER_LITERAL.text); }
  | DECIMAL_LITERAL //Convert literal to an ival of type decimal with given numeric value
    { if($eval_now && interp.getContinueStatus()==0) $value = new InterpValue("numeric",$DECIMAL_LITERAL.text); }
  | STRING_LITERAL //Convert literal to an ival of type 
    { if($eval_now && interp.getContinueStatus()==0) $value = new InterpValue("string",$STRING_LITERAL.text); }
  | '(' e=expr[eval_now] ')' 
    { if($eval_now && interp.getContinueStatus()==0) $value = $e.value; }
  | hasrows=consume_record[eval_now]
    { if($eval_now && interp.getContinueStatus()==0) $value = $hasrows.value; }
  | f=function_call[eval_now]
    { if($eval_now && interp.getContinueStatus()==0) $value = $f.value; }
  | m=method_invocation[eval_now]
    { if($eval_now && interp.getContinueStatus()==0) $value = $m.value; }
;

method_invocation[boolean eval_now]  returns [InterpValue value]
@init { ArrayList<Token> method_args = new ArrayList<Token>(); ArrayList<String> method_params = new ArrayList<String>(); }
  : lhs=expr[false] '.' 
    funcname=IDENTIFIER '('
    ( e1=expr[false] { method_args.add($e1.start); method_params.add($e1.text); }
      ( ',' e2=expr[false] { method_args.add($e2.start); method_params.add($e2.text); } )*
    )?
   ')' { if($eval_now && interp.getContinueStatus()==0) $value=interp.methodInvocation($lhs.text,$funcname.text,method_args,method_params); }
;


More information about the antlr-interest mailing list