John David
John David

Reputation: 111

ANTLR NoViableAltException with JAVA

In my grammar with antlrworks, I can get noviablealtexception for rules like if, while which need corresponding right and left brackets. However, in java, i cannot get noviablealtexception.

loop_statement: (WHILE LPAREN expr RPAREN statement)
        | (DO statement WHILE LPAREN expr RPAREN);

condition_statement 
      : IF LPAREN expr RPAREN statement (options {greedy=true;}: ELSE statement)?

In statement rule I have a block rule which is,

statement_blocks
  :   (LBRACE statement* RBRACE) 
  ;

And statement rule is below,

statement
  :  var_dec
    | statement_blocks 
    | condition_statement  
    | loop_statement
    | expr_statement 
;

Before posting this I've checked some examples. I think i need to add EOF at the end of each rule. When I add EOF for those rules, I get different errors. For example,

loop_statement: ((WHILE LPAREN expr RPAREN statement)
    | (DO statement WHILE LPAREN expr RPAREN)) EOF;

condition_statement 
  : (
     (IF LPAREN expr RPAREN statement (options {greedy=true;}: ELSE statement)?
    )EOF

These are what I get for the following inputs;

if(s==d){
d=s;
if(a=n){
s=h;
}
a=g;
}

line 6:0 missing EOF at 'a'
When I remove the first left bracket from the first "if"

if(s==d)
    d=s;
    if(a=n){
    s=h;
    }
    a=g;
    } 

testcases/new file line 3:0 missing EOF at 'if',
testcases/new file line 6:0 missing EOF at 'a'

 while(s==d){
    d=s;
    while(a=n){
    s=h;
    }
    a=g;
    }

line 6:0 missing EOF at 'a'
When I remove the first left bracket from the first "while"

 while(s==d)
    d=s;
    while(a=n){
    s=h;
    }
    a=g;
    }

testcases/new file line 3:0 missing EOF at 'while'
testcases/new file line 6:0 missing EOF at 'a'

Upvotes: 4

Views: 5737

Answers (1)

Bart Kiers
Bart Kiers

Reputation: 170148

No, you need to place EOF at the end of your "main" parser rule, not after more than one statement. By doing so, the parser expects the end of the file after such statements (which is not correct, of course).

My guess is that your entry point does not contain EOF causing the parser to stop prematurely instead of throwing an error/exception when it stumbles upon invalid input.

Here's a demo (note the EOF after the parse rule):

T.g

grammar T;

parse
  :  statement+ EOF
  ;

statement
  :  var_dec
  |  statement_blocks
  |  c=condition_statement {System.out.println("parsed :: " + $c.text);}
  ;

var_dec
  :  ID '=' ID ';'
  ;

statement_blocks
  :  LBRACE statement* RBRACE
  ;

condition_statement 
  :  IF LPAREN expr RPAREN statement (options {greedy=true;}: ELSE statement)?
  ;

expr
  :  ID '==' ID
  ;

IF     : 'if';
ELSE   : 'else';
ID     : 'a'..'z'+;
LBRACE : '{';
RBRACE : '}';
LPAREN : '(';
RPAREN : ')';
SPACE  : (' ' | '\t' | '\r' | '\n')+ {skip();};

which can be tested with the class:

Main.java

import org.antlr.runtime.*;

public class Main {
  public static void main(String[] args) throws Exception {
    TLexer lexer = new TLexer(new ANTLRFileStream("in.txt"));
    TParser parser = new TParser(new CommonTokenStream(lexer));
    parser.parse();
  }
}

Testing it all

If you now parse the input file (in.txt):

if(s==d) {
  d=s;
  if(a==n){
    s=h;
  }
  a=g;
}

there's no problem, as you can see:

java -cp antlr-3.3.jar org.antlr.Tool T.g
javac -cp antlr-3.3.jar *.java
java -cp .:antlr-3.3.jar Main

parsed :: if(a==n){s=h;}
parsed :: if(s==d){d=s;if(a==n){s=h;}a=g;}

And if you remove a ( or ) from the file in.txt, you will get the following (similar) error:

in.txt line 1:8 missing RPAREN at '{'

Upvotes: 2

Related Questions