Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6990759
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T19:23:58+00:00 2026-05-27T19:23:58+00:00

I’m trying to parse a language using ANTLR which can contain the following syntax:

  • 0

I’m trying to parse a language using ANTLR which can contain the following syntax:

someVariable, somVariable.someMember, functionCall(param).someMember,  foo.bar.baz(bjork).buffalo().xyzzy

This is the ANTLR grammar which i’ve come up with so far, and the access_operation throws the error

The following sets of rules are mutually left-recursive [access_operation, expression]:

grammar Test;

options { 
  output=AST;
  ASTLabelType=CommonTree; 
}

tokens {
  LHS;
  RHS;
  CALL;
  PARAMS;
}

start   
  :  body? EOF
  ;

body
  : expression (',' expression)*
  ;

expression
  : function -> ^(CALL)
  | access_operation
  | atom
  ;

access_operation
  : (expression -> ^(LHS)) '.'! (expression -> ^(RHS))
  ;

function
  : (IDENT '(' body? ')') -> ^(IDENT PARAMS?) 
  ;         

atom
  : IDENT
  | NUMBER
  ;

fragment LETTER : ('a'..'z' | 'A'..'Z');
fragment DIGIT  : '0'..'9';

IDENT    : (LETTER)+ ;
NUMBER   : (DIGIT)+ ;
SPACE    : (' ' | '\t' | '\r' | '\n') { $channel=HIDDEN; };

What i could manage so far was to refactor the access_operation rule to '.' expression which generates an AST where the access_operation node only contains the right side of the operation.

What i’m looking for instead is something like this:

enter image description here

How can the left-recursion problem solved in this case?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T19:23:58+00:00Added an answer on May 27, 2026 at 7:23 pm

    By “wrong AST” I’ll make a semi educated guess that, for input like "foo.bar.baz", you get an AST where foo is the root with bar as a child who in its turn has baz as a child, which is a leaf in the AST. You may want to have this reversed. But I’d not go for such an AST if I were you: I’d keep the AST as flat as possible:

        foo
       / | \
      /  |  \
    bar baz  ...
    

    That way, evaluating is far easier: you simply look up foo, and then walk from left to right through its children.

    A quick demo:

    grammar Test;
    
    options { 
      output=AST;
      ASTLabelType=CommonTree; 
    }
    
    tokens {
      BODY;
      ACCESS;
      CALL;
      PARAMS;
    }
    
    start   
     : body EOF -> body
     ;
    
    body
     : expression (',' expression)* -> ^(BODY expression+)
     ;
    
    expression
     : atom
     ;         
    
    atom
     : NUMBER
     | (IDENT -> IDENT) ( tail       -> ^(IDENT tail)
                        | call tail? -> ^(CALL IDENT call tail?)
                        )?
     ;
    
    tail
     : (access)+
     ;
    
    access
     : ('.' IDENT -> ^(ACCESS IDENT)) (call -> ^(CALL IDENT call))?
     ;
    
    call
     : '(' (expression (',' expression)*)? ')' -> ^(PARAMS expression*)
     ;
    
    IDENT  : LETTER+;
    NUMBER : DIGIT+;
    SPACE  : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
    
    fragment LETTER : ('a'..'z' | 'A'..'Z');
    fragment DIGIT  : '0'..'9';
    

    which can be tested with:

    import org.antlr.runtime.*;
    import org.antlr.runtime.tree.*;
    import org.antlr.stringtemplate.*;
    
    public class Main {
      public static void main(String[] args) throws Exception {
        String src = "someVariable, somVariable.someMember, functionCall(param).someMember, " + 
            "foo.bar.baz(bjork).buffalo().xyzzy";
        TestLexer lexer = new TestLexer(new ANTLRStringStream(src));
        TestParser parser = new TestParser(new CommonTokenStream(lexer));
        CommonTree tree = (CommonTree)parser.start().getTree();
        DOTTreeGenerator gen = new DOTTreeGenerator();
        StringTemplate st = gen.toDOT(tree);
        System.out.println(st);
      }
    }
    

    The output of Main corresponds to the following AST:

    enter image description here

    EDIT

    And since you indicated your ultimate goal is not evaluating the input, but that you rather need to conform the structure of the AST to some 3rd party API, here’s a grammar that will create an AST like you indicated in your edited question:

    grammar Test;
    
    options { 
      output=AST;
      ASTLabelType=CommonTree; 
    }
    
    tokens {
      BODY;
      ACCESS_OP;
      CALL;
      PARAMS;
      LHS;
      RHS;
    }
    
    start   
     : body EOF -> body
     ;
    
    body
     : expression (',' expression)* -> ^(BODY expression+)
     ;
    
    expression
     : atom
     ;         
    
    atom
     : NUMBER
     | (ID -> ID) ( ('(' params ')' -> ^(CALL ID params)) 
                    ('.' expression -> ^(ACCESS_OP ^(LHS ^(CALL ID params)) ^(RHS expression)))?
                  | '.' expression  -> ^(ACCESS_OP ^(LHS ID) ^(RHS expression))
                  )?
     ;
    
    params
     : (expression (',' expression)*)? -> ^(PARAMS expression*)
     ;
    
    ID     : LETTER+;
    NUMBER : DIGIT+;
    SPACE  : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
    
    fragment LETTER : ('a'..'z' | 'A'..'Z');
    fragment DIGIT  : '0'..'9';
    

    which creates the following AST if you run the Main class:

    enter image description here

    The atom rule may be a bit daunting, but you can’t shorten it much since the left ID needs to be available to most of the alternatives. ANTLRWorks helps in visualizing the alternative paths this rule may take:

    enter image description here

    which means atom can be any of the 5 following alternatives (with their corresponding AST’s):

    +----------------------+--------------------------------------------------------+
    | alternative          | generated AST                                          |
    +----------------------+--------------------------------------------------------+
    | NUMBER               | NUMBER                                                 |
    | ID                   | ID                                                     |
    | ID params            | ^(CALL ID params)                                      |
    | ID params expression | ^(ACCESS_OP ^(LHS ^(CALL ID params)) ^(RHS expression))|
    | ID expression        | ^(ACCESS_OP ^(LHS ID) ^(RHS expression)                |
    +----------------------+--------------------------------------------------------+
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am trying to understand how to use SyndicationItem to display feed which is
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
I'm using v2.0 of ClassTextile.php, with the following call: $testimonial_text = $textile->TextileRestricted($_POST['testimonial']); ... and
Basically, what I'm trying to create is a page of div tags, each has
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I used javascript for loading a picture on my website depending on which small
I have a jquery bug and I've been looking for hours now, I can't
I have a French site that I want to parse, but am running into
We are using XSLT to translate a RIXML file to XML. Our RIXML contains

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.