Question

I have the Grammar_A grammar and i want to split in two grammars, Grammar_A1 and Grammar_A2; Grammar_A2 imports Grammar_A1 (i have been included all on the end of the question).

When i try to compile my project, i obtain the error redefinition of 'init' action two times in Grammar_A2, despite that there are three '@init' actions.

If i comment two of the three @init actions, no matter wich, compiles fine.

I translate the grammar to Java and compile like the tutorial in Antlr4 website: i obtain the same errors making java -classpath .;../antlr-4.2-complete.jar org.antlr.v4.Tool Grammar_A2.g4, but indicates error 94, ACTION_REDEFINITION.

I have tryed to compile with antlr version 4.1 and version 4.2.

Any idea of what can i am doing wrong?

Grammar_A

grammar Grammar_A;

@parser::members
{
    protected const int EOF = Eof;
    int numPrints, numReads;
}

@lexer::members
{
    protected const int EOF = Eof;
    protected const int HIDDEN = Hidden;
}

program
@init { numPrints = numReads = 0; }
    :   (printExpression | readExpression)+
    ;

printExpression
@init {numPrints++;}
    :   PRINT_KEY 
        ( id
            | QUOT id QUOT
        )
        SEMICOLON
;

readExpression
@init {numReads++;}
    : ID READ_KEY SEMICOLON
;

id 
    :   ID | PRINT_KEY | READ_KEY
    ;

WS
    :   (' ' | '\r' | '\n') -> channel(HIDDEN)
    ;

PRINT_KEY : 'print';
READ_KEY : 'read';

ID : ('a'..'z')+ ;


SEMICOLON : ';';
QUOT : '"'; 

Grammar_A1

grammar Grammar_A1;

@parser::members
{
    protected const int EOF = Eof;
}

@lexer::members
{
    protected const int EOF = Eof;
    protected const int HIDDEN = Hidden;
}

id 
    :   ID | PRINT_KEY | READ_KEY
    ;    

WS
    :   (' ' | '\r' | '\n') -> channel(HIDDEN)
    ;

PRINT_KEY : 'print';
READ_KEY : 'read';

ID : ('a'..'z')+ ;

Grammar_A2

grammar Grammar_A2;

import Grammar_A1; 


@parser::members {
    int numPrints, numReads;
}

program
@init { numPrints = numReads = 0; }
    :   (printExpression | readExpression)+
    ;

printExpression
@init {numPrints++;}
    :   PRINT_KEY 
        ( id
            | QUOT id QUOT
        )
        SEMICOLON
;

readExpression
@init {numReads++;}
    : ID READ_KEY SEMICOLON
;


SEMICOLON : ';';
QUOT : '"';
Was it helpful?

Solution

  1. If you can reproduce this issue in the Java code (which it appears you can), you can report it as a bug on the reference implementation's issue tracker. Otherwise, if this is specific to the C# target, you can report it on the C# target's issue tracker.

  2. If you have one grammar, I highly recommend the only separation you ever consider is splitting it into a lexer grammar and parser grammar, and not use the import statement. The cases where an import statement actually helps are few and far between.

  3. The actions you've indicated in your question are not essential for correct parsing, and as such should be relocated to a listener or visitor which executes after the parse is complete. With these actions in the correct location, you will no longer be constrained by the issue you've described.

OTHER TIPS

I had the same problem, it could be a bug in ANTLR ?

To work around this I relocated all @init and @after blocks inline. Something like this (not tested):

grammar Grammar_A2;

import Grammar_A1; 


@parser::members {
    int numPrints, numReads;
}

program
    :   { numPrints = numReads = 0; } // previously @init
        (printExpression | readExpression)+
        { int numWhat = (numPrints + numReads);
          System.out.println(numWhat); } //  @after block
    ;

printExpression
    :   {numPrints++;} // previously @init
        PRINT_KEY 
        ( id
            | QUOT id QUOT
        )
        SEMICOLON
    ;

readExpression
    : {numReads++;} // previously @init
      ID READ_KEY SEMICOLON
    ;


SEMICOLON : ';';
QUOT : '"';

edit: I opened an issue here https://github.com/antlr/antlr4/issues/2041

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top