Search code examples
xtext

Removing left recursion in xtext


I saw many posts on this, and also read Parsing Expressions with Xtext in https://eclipse.org/Xtext/documentation/307_special_languages.html, as well as https://typefox.io/parsing-expressions-with-xtext

However, I was not able to eliminate my LL recursion error:

My grammar is:

Was able to solve all but one issue

Trailer:
    '[' (index+=Expr)?']'|
    '(' (params+=Expr_list)? ')'|
    '.' name=id(trailer+=Trailer)* //TODO fix left recusion
;

Tried the following

Trailer:
    TerminalTrailer |
    '.' name=id (trailer+=TerminalTrailer )* //TODO fix left recusion


TerminalTrailer returns Trailer:
        '[' (index+=Expr)?']'|
        '(' (params+=Expr_list)? ')';

but this is not working , and I am a bit confused why , it is also don't account for a case that . name (Trailer) where trailer is another . name

any ideas?


Solution

  • these kind of expressions look like the following ones in Xtext

    Addition returns Expression:
      Multiplication ({Addition.left=current} '+' right=Multiplication)*;
    
    Multiplication returns Expression:
      Primary ({Multiplication.left=current} '*' right=Primary)*;
    
    Primary returns Expression:
      NumberLiteral |
      '(' Addition ')';
    
    NumberLiteral:
      value=INT;
    

    see http://typefox.io/parsing-expressions-with-xtext for a detailed explanation. and https://github.com/LorenzoBettini/xsemantics/blob/master/examples/it.xsemantics.example.expressions/src/it/xsemantics/example/expressions/Expressions.xtext for a bit more complex example

    Update:

    your stuff could be something like (untested)

    OrExpression:
        And_expr ({OrExpression.left=current} '||' right+=And_expr)*;
    
    And_expr returns Expression:
        Subtract_expr ({And_expr.left=current} '&&' right+=Subtract_expr)*;
    
        Subtract_expr returns Expression:
        "!" not=Subtract_expr
        | Compare_expr;
    
    Compare_expr returns Expression:
        Math_expr (operator+=('>=' | '<=' | '==' | '!=' | '>' | '<') comp+=Math_expr)+ |
        '(' Compare_expr ')' | // 
        Literal;
    
    Literal returns Expression:
        {Literal}(
        value?="true" | "false");
    
    Math_expr:
        valie=INT;
    

    Edit 2:

    Trailer:
        '[' (index+=Expr)?']'|
         '(' (params+=Expr_list)? ')'|
         '.' name=ID (=>trailer+=Trailer)*
     ;