title: ANTLR character string seen as identifier
body: <p>i'm working on a sql parser to allow our programmers to create a mysql like query which is then automatically translated to mssql or mysql queries, depending on what you want. This to allow flexible transitions between mysql and mssql databases.</p>
  
  <p>I currently have what I set out to create except that there is one problem.</p>
  
  <p>If i run a query like this:</p>
  
  <pre><code>SELECT * FROM `x`.`y` WHERE `y`.`b` = 'hello'
  </code></pre>
  
  <p>the character string is seen as a identifier llo</p>
  
  <p>This is my grammer</p>
  
  <pre><code>grammar Query;
  
  query
      : (select_stmt|update_stmt|delete_stmt|insert_stmt|upsert_stmt) ';'? EOF
      ;
  
  select_stmt
      : select 'FROM' select_table_exp where? groupby? orderby? limit?
      ;
  
  update_stmt
      : 'UPDATE' table_exp set where?
      ;
  
  delete_stmt
      : 'DELETE FROM ' table_exp where    
      ;
  
  insert_stmt
      : 'INSERT INTO' table_exp fields values
      ;
  
  upsert_stmt
      : 'UPSERT' table_exp set ?  
      ;
  
  values
      : 'VALUES (' valuelist ')'
      ;
  
  valuelist
      : value (',' valuelist)?where
      ;
  
  fields
      : '(' groupbylist ')'
      ;
  
  set
      : 'SET' (setlist)
      ;
  
  setlist
      : setters (',' setlist)?
      ;
  
  select
      : 'SELECT' fieldlist
      ;
  
  where
      : 'WHERE' where_stmt 
      ;
  
  limit
      : 'LIMIT' (INT|param) (',' (INT|param))?
      ;
  
  groupby
      : 'GROUP BY' groupbylist    
      ;
  
  orderby
      : 'ORDER BY' orderbylist
      ;
  
  select_table_exp
      : table_exp (join_stmt)?    
      | '(' select_stmt ')' as
      ;
  
  table_exp
      : identifier as?
      ;
  
  fieldlist
      : 
        (
            function as
          | (identifier as?)
          | identifier_prefix? '*' // solve the problem of the `ID`.* problem
          | '(' select_stmt ')' as
        ) (',' fieldlist)?
      ;
  
  function
      : 'COUNT(' (identifier|'*') ')' 
      | 'MAX(' identifier ')'
      | 'MIN(' identifier ')'
      | 'AVERAGE(' identifier ')'
      | 'CONCAT(' groupbylist ')'
      | 'CONCAT_WS(' CHAR ',' groupbylist ')' 
      ;
  
  orderbylist
      : identifier ('ASC'|'DESC')? (',' orderbylist)? 
      ;
  
  groupbylist
      : identifier (',' groupbylist)? 
      ;
  
  as
      : 'AS' (ID | '`' ID '`')    
      ;
  
  join_stmt
      : leftjoin (join_stmt)?
      | rightjoin (join_stmt)?
      | join (join_stmt)?
      ;
  
  leftjoin
      : 'LEFT JOIN' (table_exp|('(' select_stmt ')' as)) on_stmt
      ;
  
  rightjoin
      : 'RIGHT JOIN' (table_exp|('(' select_stmt ')' as)) on_stmt
      ;
  
  join
      : 'JOIN' (table_exp|('(' select_stmt ')' as)) on_stmt
      ;
  
  on_stmt
      : 'ON' where_stmt
      ;
  
  where_stmt
      : where_exp ((BOOLEANAND|BOOLEANOR) where_stmt)?
      ;
  
  where_exp
      : where_exp_identifier
      | value (WHEREOPERATORS|EQUALITYOPERATOR) identifier
      | '(' select_stmt ')' (WHEREOPERATORS|EQUALITYOPERATOR) identifier
      ;
  
  where_exp_identifier
      : identifier (WHEREOPERATORS|EQUALITYOPERATOR) where_exp_identifier_operator_right
      | identifier 'BETWEEN' (numeric_value BOOLEANAND numeric_value)
      | identifier 'LIKE' string_value
      ;
  
  where_exp_identifier_operator_right
      : value
      | identifier
      | '(' select_stmt ')'
      ;
  
  setters
      : identifier EQUALITYOPERATOR value
      | value EQUALITYOPERATOR identifier
      | identifier EQUALITYOPERATOR '(' select_stmt ')'
      | '(' select_stmt ')' EQUALITYOPERATOR identifier
      ;
  
  identifier_value
      : value
      | identifier
      ;
  
  value
      : string_value
      | numeric_value
      | param
      ;
  
  string_value
      : STRING
      | CHAR
      ;
  
  numeric_value
      : INT
      | FLOAT
      ;
  
  identifier_prefix
      : ID '.'
      | '`' ID '`.'   
      ;
  
  identifier
      : identifier_prefix? ID 
      | identifier_prefix? '`' ID '`'
      ;
  
  param
      : '@' ID
      ;
  
  BOOLEANAND
      : 'AND'
      ;
  
  BOOLEANOR
      : 'OR'
      ;
  
  EQUALITYOPERATOR
      : '='
      ;
  
  WHEREOPERATORS
      : ('!='|'&lt;&gt;'|'&lt;'|'&gt;'|'&lt;='|'&gt;=')
      ;
  
  ID  :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
      ;
  
  INT :   '0'..'9'+
      ;
  
  FLOAT
      :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
      |   '.' ('0'..'9')+ EXPONENT?
      |   ('0'..'9')+ EXPONENT
      ;
  
  COMMENT
      :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
      |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
      ;
  
  WS  :   ( ' '
          | '\t'
          | '\r'
          | '\n'
          ) {$channel=HIDDEN;}
      ;
  
  STRING
      :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
      ;
  
  CHAR:  '\'' ( ESC_SEQ | ~('\''|'\\') ) '\''
      ;
  
  fragment
  EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
  
  fragment
  HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
  
  fragment
  ESC_SEQ
      :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
      |   UNICODE_ESC
      |   OCTAL_ESC
      ;
  
  fragment
  OCTAL_ESC
      :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
      |   '\\' ('0'..'7') ('0'..'7')
      |   '\\' ('0'..'7')
      ;
  
  fragment
  UNICODE_ESC
      :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
      ;
  </code></pre>
  
  <p>I'm far from an ANTLR expert so after 3 hours of fiddling with my grammar to try and get the grammar to accept a character string as correct at that position I decided to ask you guys for some help. Maybe some antlr guru here can help me sort this out.</p>
  
  <p>Many thanks</p>