Search code examples
antlrantlrworks

antlr - Comment Line error


I'm using Antlr 3 under AntlrWorks 1.4.3 and I'm having trouble writing a grammar to ignore comment lines.

This is the grammar that exhibits the problem:

grammar Ex2;
@header {
    import java.util.HashMap;
}
@members {
    HashMap memory = new HashMap();
}
prog: stat+ ;

stat
    : expr NEWLINE {System.out.println($expr.value);}
    | ID '=' expr NEWLINE
        { memory.put($ID.text, new Integer($expr.value)); }
    | NEWLINE
    ;

expr returns [int value]
    : e=term {$value = $e.value;}
    ( '+' e=term {$value += $e.value;}
    | '-' e=term {$value -= $e.value;}
    )*
    ;

term returns [int value]
    : e=fact {$value = $e.value; }
    ( '*' e=fact {$value *= $e.value;}
    | '/' e=fact {$value /= $e.value;}
    | '^' e=fact {
                    for(int i = 0; i < $e.value; i++)
                        $value *= $value;   
                 }  
    )*;

fact returns [int value]
    : INT {$value = Integer.parseInt($INT.text);}
    | ID
    {
        Integer v = (Integer)memory.get($ID.text);
        if ( v!=null ) $value = v.intValue();
        else System.err.println("undefined variable "+$ID.text);
    }
    | '(' expr ')' {$value = $expr.value;}
    ;

COMMENT
    : '--' ~('/r' | '/n')* {skip();}
    ;   
ID 
    : ('a'..'z'|'A'..'Z')+ 
    ;
INT 
    : '0'..'9'+ 
    ;
NEWLINE
    :'\r'? '\n' 
    ;
WS 
    : (' '|'\t')+ {skip();} 
    ;

I get this error

error(204): /../Ex2.g:46:16: duplicate token type '/n' when collapsing subrule into set 

I would like to mention that almost every type of grammar that i try to debug using the COMMENT rule for the lexer crashes into the same error.

Please help and thank you in advance.


Solution

  • It's not:

    COMMENT
        : '--' ~('/r' | '/n')* {skip();}
        ; 
    

    but:

    COMMENT
        : '--' ~('\r' | '\n')* {skip();}
        ; 
    

    The problem is that /n are two characters, and the negation operator only works on sets of single characters. You can't negate the two substrings '/r' and '/n' but you can negate the set of two (single) chars '\r' and '\n'.