ASTと格闘している。いやlexerか。

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

添削してもらったので、少し直してみた。
そろそろ2byte文字も使ってみたいな…とか思って直している最中に、致命的な事が判明。


とりあえず、出来たトコまで晒しておくます。

grammar TwoWaySQL;

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

tokens {
	BEGINNODE;
	IFNODE;
	EXPRESSIONNODE;
	ELSENODE;
}

@header {
package twowaysql.grammar;
}

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

twowaySQL : txt EOF;

txt 	:
	(IDENT
	| comment
	| WS | LT)+
	;

// $<comment

comment :
	begincomment
	| ifcomment
	| blockcomment
	| linecomment
	;

blockcomment :
	C_ST (IDENT | LT)+ C_ED
	;

linecomment :
	C_LN (IDENT)+ (LT|EOF)
	;

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
	| C_LN ELSE expression? LT
	) -> ^(EXPRESSIONNODE expression?)
	;

expression :
	(IDENT | LT)+
	;

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

endcomment :
	C_ST END C_ED
	;

// $>
C_ST	:	'/*';
C_ED	:	'*/';
C_LN	:	'--';

BEGIN	: WS* ('b'|'B')('e'|'E')('g'|'G')('i'|'I')('n'|'N') WS*;
IF	: WS* ('i'|'I') ('f'|'F') WS*;
ELSE 	: WS* ('e'|'E')('l'|'L')('s'|'S')('e'|'E') WS*;
END	: WS* ('e'|'E')('n'|'N')('d'|'D') WS*;
	
// $<Charactors
LT	: '\n'		// Line feed.
	| '\r'		// Carriage return.
	| '\u2028'	// Line separator.
	| '\u2029'	// Paragraph separator.
	;
WS	: '\t' | '\v' | '\f' | ' ' | '\u00A0';

IDENT :	WS* CHAR+ WS*;

fragment CHAR	: 
		~(
		'\u002a' | '\u002f' |// ダメなのだけ省いてみた。
		LT | WS) ;
// $>

このgrammarに、こんなテキストを食わせる。

ada.cec のしのし / 3 d/*aa hoge
 piro*/  ぎゃぼー
/* BeGiN*/
 /* If aa bb
 dd*/moge piro /*eLsE ccc*/ccc
	/* ElSe */ zzz
 /*eNd*/
	-- moge うぼぁ zz
/* EnD*/

まず、一行目の「/ 3」の部分が宇宙の彼方に消える。
まぁ、/と*をCHARで使えないとしているので、そんなもんかな…と。
んで、

fragment CHAR	: ~(LT | WS) ;

と、してみる。すると、「 /* If」の所まで来てMismatchedTokenExceptionでしぬ。
「/* BeGiN*/」の部分は、通過しているけど、ASTが生成されていない。
ううむ…。