空白のスキップとクォート出来る様にしてみた。

■[ANTLR] 空白文字のスキップCommentsAdd Starwarufuzaketaichi

引き続き、ASTは、タダじゃ作ってくれない。 - 設計と実装の狭間で。を添削。

予想以上に大変。

らしいのだけど、せっせとコピペしたので、それなりに楽勝。
しかし、それでは芸がないので、クォート処理をレキサーでやってみた。

grammar TwoWaySQL;

options {
	language = Java;
	output = AST;
	ASTLabelType = CommonTree;
}

tokens {
	BEGINNODE;
	IFNODE;
	EXPRESSIONNODE;
	ELSENODE;
}

@header {
package twowaysql.grammar;
}

@lexer::header {
package twowaysql.grammar;
}

@lexer::members {
boolean inComment = false;
boolean inLineComment = false;
}

twowaySQL : txt EOF;

txt 	:
	(comment | charactors)+
	;

charactors
	:	(IDENT| SYM_A| SYM_S | SYM_H | QUOTED)+
	;

// $<comment

comment :
	begincomment
	| ifcomment
	| blockcomment
	| linecomment
	;


blockcomment :
	C_ST (charactors)+ C_ED
	;

linecomment :
	C_LN_ST (charactors)+ C_LN_ED
	;

ifcomment :
	C_ST IF expression C_ED txt (elsecomment txt)* endcomment 
		-> ^(IFNODE ^(EXPRESSIONNODE expression) txt ^(ELSENODE elsecomment txt)*)
	;

elsecomment :
	(C_ST ELSE expression? C_ED -> ^(EXPRESSIONNODE expression?)
	|C_LN_ST ELSE lineexpression? C_LN_ED -> ^(EXPRESSIONNODE lineexpression?)
	) 
	;

expression :
	(charactors)+
	;
	
lineexpression :
	(charactors)+
;

begincomment :	
	((C_ST BEGIN C_ED | C_LN_ST BEGIN C_LN_ED) txt endcomment) -> ^(BEGINNODE txt)
	;

endcomment :
	C_ST END C_ED | C_LN_ST END C_LN_ED
	;

// $>
C_ST	:
	{!inComment}? '/*' { inComment = true; };

C_ED	:
	{inComment}? '*/' { inComment = false; };
	
C_LN_ST	:
	{!inComment}? '--' { inLineComment = true; inComment = true; };

C_LN_ED	:
	{inLineComment}? ( LN_R LN_N | LN_R | LN_N | EOF ) { inLineComment = false; inComment = false; };

QUOTED	:SYM_Q ~(SYM_Q)+ SYM_Q;

LT	: {!inLineComment}? (LN_R | LN_N)+ { $channel = HIDDEN; };
WS	: ('\t' | '\v' | '\f' | ' ' | '\u00A0')+ { $channel = HIDDEN; };

SYM_A	:	'*';
SYM_S	:	'/';
SYM_H	:	'-';
SYM_Q	:	'\u0027';

BEGIN :  ('b'|'B')('e'|'E')('g'|'G')('i'|'I')('n'|'N');
IF	:  ('i'|'I')('f'|'F');
ELSE	:  ('e'|'E')('l'|'L')('s'|'S')('e'|'E');
END	: ('e'|'E')('n'|'N')('d'|'D');

IDENT	: CHAR+;

fragment LN_R :	'\r';
fragment LN_N : '\n';
CHAR	: ~(SYM_A | SYM_S | SYM_H | SYM_Q | LN_R | LN_N | '\t' | '\v' | '\f' | ' ' | '\u00A0');

こんなテキストを食わせてるます。

ada.cec のしのし / 3 d/*aa hoge
 piro*/  ぎゃぼー
-- BeGiN
 /* If aa - bb
 dd*/moge piro /*eLsE ccc + 44 '*/' */cccd
	-- elSE fuga < '0'
		dfdze
	-- ElSe 
	 zzz '-- fugafuga'
 -- eNd
	-- moge うぼぁ zz
/* EnD*/

ポイントは、

/*eLsE ccc + 44 '*/' */

で、コメントが変な風に中断したり、

'-- fugafuga'

がコメントノードにならずテキストノードになる事ダス。

タダね、これだと、実は余りうまくない。
SQL内の空白は、最悪消えても良いのだけど、
コメント内の空白文字は、消えてしまっては困るのです。
何故なら、IFコメントとかのexpression部分は外部の式言語にそのまま食わせるから。