1
votes

This is a follow-up question from Antlr superfluous Predicate required? where I stated my problem in a simplified way, however it could not be solved there.
I have the following grammar and when I delete the {true}?=> predicates, the text is not recognized anymore. The input string is MODULE main LTLSPEC H {} {} {o} FALSE;. Note that the trailing ; is not tokenized as EOC, but as IGNORE. When I add {true}?=> to the EOC rule ; is tokenized as EOC.
I tried this from command-line with antlr-v3.3 and v3.4 without difference. Thanks in advance, I appreciate your help.

grammar NusmvInput;

options {
  language = Java;
}    
@parser::members{
public static void main(String[] args) throws Exception {
    NusmvInputLexer lexer = new NusmvInputLexer(new ANTLRStringStream("MODULE main LTLSPEC H {} {} {o} FALSE;"));
    NusmvInputParser parser = new NusmvInputParser(new CommonTokenStream(lexer));
    parser.specification();
  }
}    
@lexer::members{
    private boolean inLTL = false;
} 

specification : 
     module+ EOF
     ;
module : 
    MODULE module_decl    
    ;

module_decl : 
    NAME parameter_list ;
parameter_list 
    : ( LP (parameter ( COMMA parameter )*)? RP )?
    ;    
parameter
    : (NAME | INTEGER )
    ;    
/**************
*** LEXER
**************/
COMMA
    :{!inLTL}?=> ','
    ; 
OTHER 
    : {!inLTL}?=>( '&' | '|' | 'xor' | 'xnor' | '=' | '!' |
     '<' | '>' | '-' | '+' | '*' | '/' |
      'mod' | '[' | ']' | '?')
      ;     
RCP
      : {!inLTL}?=>'}'
      ;      
LCP
      : {!inLTL}?=>'{'
      ;
LP 
    : {!inLTL}?=>'('
    ;
RP 
    : {!inLTL}?=>')'
    ;   
MODULE
    : {true}?=> 'MODULE' {inLTL = false;}
    ;
LTLSPEC
    : {true}?=> 'LTLSPEC' 
    {inLTL = true; skip(); }
    ;  
EOC 
    : ';' 
    {
        if (inLTL){
            inLTL = false;
            skip();
        }
    }
    ;   
WS 
    : (' ' | '\t' | '\n' | '\r')+ {$channel = HIDDEN;} 
    ;
COMMENT 
    :  '--' .* ('\n' | '\r') {$channel = HIDDEN;} 
    ; 
INTEGER 
    : {!inLTL}?=> ('0'..'9')+
    ;
NAME 
    :{!inLTL}?=> ('A'..'Z' | 'a'..'z') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$' | '#' | '-')*
    ;
IGNORE
    : {inLTL}?=> . {skip();}
    ;
1
Just glancing over your grammar, I already see 2 errors: a ^ in the module rule while there's no output=AST present in the options, and the specification rule ends with a - (minus) sign.Bart Kiers
Sorry for that. I removed the tree-rewritting after copying the code into stackoverflow, and forgot those.Heinrich Ody

1 Answers

1
votes

It seems that without a predicate before MODULE and LTLSPEC, the NAME gets precedence over them even if these tokens are defined before the NAME token. Whether this is by design or a bug, I don't know.

However, the way you're trying to solve it seems rather complicated. As far as I can see, you seem to want to ignore (or skip) input starting with LTLSPEC and ending with a semi colon. Why not do something like this instead:

specification  : module+ EOF;
module         : MODULE module_decl;
module_decl    : NAME parameter_list;
parameter_list : (LP (parameter ( COMMA parameter )*)? RP)?;    
parameter      : (NAME | INTEGER);    

MODULE  : 'MODULE';
LTLSPEC : 'LTLSPEC' ~';'* ';' {skip();};
COMMA   : ','; 
OTHER   : ( '&' | '|' | 'xor' | 'xnor' | '=' | '!' |
            '<' | '>' | '-' | '+' | '*' | '/' |
           'mod' | '[' | ']' | '?')
        ;     
RCP     : '}';      
LCP     : '{';
LP      : '(';
RP      : ')';   
EOC     : ';';   
WS      : (' ' | '\t' | '\n' | '\r')+ {$channel = HIDDEN;};
COMMENT : '--' .* ('\n' | '\r') {$channel = HIDDEN;}; 
INTEGER : ('0'..'9')+;
NAME    : ('A'..'Z' | 'a'..'z') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$' | '#' | '-')*;