Search code examples
antlrdslparser-generator

Antlr tells me NoViableAltException,i'm clueless


I'm currently working on a ANTLR grammar that accepts sql statements. I want to use this grammar to allow programmers to create mysql queries and the application will automatically change the query into the proper format for the needed database.

For example if you use LIMIT 0,5 in your query it will automatically transform this query to the proper format for mssql

This is my grammer up until now

grammar sql2;

query   
    : select ';'?  EOF
    ;

select
    : 'SELECT' top? select_exp 'FROM' table ('WHERE' compare_exp)? limit?
    ;

compare_exp
    : field CompareOperator param (BooleanOperator compare_exp)?
    ;

param
    : '@' ID
    ;

top
    : 'TOP' INT
    ;

limit
    : 'LIMIT' INT (',' INT)?
    ;

select_exp
    : field (',' select_exp)?
    ;

table
    : '`' ID '`' ('.`' ID '`')?
    | ID ('.' ID)?
    ;

field
    : table
    ;

ID  :   ('a'..'z'|'A'..'Z') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

CompareOperator
    : ( '=' | '<>' )
    ;

BooleanOperator
    : ('AND' | 'OR')
    ;

INT :   '0'..'9'+
    ;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

If I test this with the input

SELECT TOP 5 bla_asdf, bal, lab FROM `x`.`y` WHERE xdf = @tf AND bla = @b LIMIT 0, 5

it stops parsing my query at the AND bla = @b, at that point it gives me an NoViableAltException... If I put the input

SELECT TOP 5 bla_asdf, bal, lab FROM `x`.`y` WHERE xdf = @tf LIMIT 0, 5

It will give me no problems whatsoever.

I'm absolutely no expert at ANTLR but that also means that I don't see what I'm doing wrong here.

Can anybody help me on this?

Cheers


Solution

  • AND is tokenized as an ID, because the first lexer rule matching the longest input fragment wins.

    So you should define BooleanOperator before ID.