文法がわからん…

こんな感じ?SQL部分はかなりいい加減ですが

grammar Way2;

options {
  output = AST;
  ASTLabelType=CommonTree;
}

tokens {
  PROGRAM;
  UNSTRUCTURED;
  BIND_LITERAL;
  BIND_LIST;
  REPLACE;
  LIST;
  THEN;
  QUALIFIED;
}

@lexer::members {
private boolean inBlockComment = false;
private boolean inLineComment = false;
}

program
  : sql_fragment* EOF -> ^(PROGRAM sql_fragment*)
  ;

// fragments
sql_fragment
  : unstructured
  | list
  | bind
  | replace
  | if_block
  | begin_block
  ; 

unstructured
  : ~(
    COMMENT_START
    | LIST_START
    | LIST_END
    | COMMENT_END
    )
  ;

bind
  : bind_comment
    ( literal -> ^(BIND_LITERAL bind_comment literal)
    | list    -> ^(BIND_LIST bind_comment list)
    )
  ;

replace
  : replace_comment literal -> ^(REPLACE replace_comment literal)
  ;

list
  : LIST_START sql_fragment* LIST_END -> ^(LIST sql_fragment*)
  ;

if_block
  : if_comment sql_fragment* elseif_comment* else_comment? end_comment
    -> ^(IF if_comment ^(THEN sql_fragment*) elseif_comment* else_comment)
  ;

begin_block
  : begin_comment sql_fragment* end_comment -> ^(BEGIN sql_fragment*)
  ;
  
// expressions

expression
  : literal
  ;

literal
  : LITERAL
  ;

qualified
  : IDENT ( DOT IDENT )* -> ^(QUALIFIED IDENT*)
  ;

//// structured comments

replace_comment
  : COMMENT_START DOLLER qualified COMMENT_END -> qualified
  ;

bind_comment
  : COMMENT_START IDENT COMMENT_END -> IDENT
  ;

if_comment
  : COMMENT_START IF expression COMMENT_END -> ^(IF expression)
  ;

elseif_comment
  : COMMENT_START ELSEIF expression sql_fragment* COMMENT_END
    -> ^(ELSEIF expression ^(THEN sql_fragment*))
  ;

else_comment
  : COMMENT_START ELSE sql_fragment* COMMENT_END -> ^(ELSE sql_fragment*)
  ;

begin_comment
  : COMMENT_START BEGIN COMMENT_END -> ^(BEGIN)
  ;

end_comment
  : COMMENT_START END COMMENT_END -> ^(END)
  ;


// reserved..
IF
  : 'IF'
  ;

ELSEIF
  : 'ELSEIF'
  ;

ELSE
  : 'ELSE'
  ;

BEGIN
  : 'BEGIN'
  ;

END
  : 'END'
  ;


LIST_START
  : '('
  ;

LIST_END
  : ')'
  ;

DOLLER
  : '$'
  ;

DOT
  : '.'
  ;

COMMA
  : ','
  ;

LITERAL
  : ( '0'..'9' )+
  ;

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

COMMENT_START
  : {!inBlockComment}? '/*' { inBlockComment = true; }
  | {!inBlockComment && !inLineComment}? '--' { inLineComment = true; }
  ;

COMMENT_END
  : {inLineComment}? ( LINE_BREAK | EOF ) { inBlockComment = false; inLineComment = false; }
  | {inBlockComment}? '*/' { inBlockComment = false; }
  ;

WHITESPACE
  : ( ' ' | '\t' )+ { $channel = HIDDEN; }
  | { !inLineComment }? LINE_BREAK+ { $channel = HIDDEN; }
  ;

fragment
LINE_BREAK
  : '\r\n' | '\r' | '\n'
  ;
/* IF 1 */ /* a */1
-- ELSEIF 2 /* $a.b.c */2
-- ELSEIF 3 /* d */ 3
-- ELSEIF 4 IN /* hogehoge */(a, b, c)
-- ELSE 999
/* END */