【已解决】antlr中支持EDDL的多国语言字符串其中用的是rule而非token

【背景】

如下antlr语法:

fragment
LETTER	:	'a'..'z' | 'A'..'Z';


STR_LAN	:	'"|' LETTER LETTER '|"';

//fragment
STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

multi_lan_str	:	STRING WS* STR_LAN STRING;

可以匹配:

"Deviation alarm"	"|sv|""Avviks larm"

但是用的是lexer的token。

现在去想要尝试用parser的rule去表示。

【折腾过程】

1.改为:

fragment
LETTER	:	'a'..'z' | 'A'..'Z';


STR_LAN	:	'"|' LETTER LETTER '|"';

//fragment
STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

string_value	:	(IMPORTED_VALUE | ID | multi_lan_str | STRING); // support multi language string

//multiple language string
//eg: "Current loop"       "|sv|""St?mslinga"
//multi_lan_str	:	STRING '"|' LETTER LETTER '|"' STRING;
//multi_lan_str	:	STRING WS+ STRING STRING;
//multi_lan_str	:	STRING WS* STR_LAN STRING;
multi_lan_str	:	STRING single_lan_str+;
single_lan_str	:	WS* '"|' lan_id '|"' lan_str; // single language string
lan_id	:	LETTER LETTER;
lan_str	:	STRING;

结果无法匹配:

multi lan str can not match

2.再去改为:

fragment
LETTER	:	'a'..'z' | 'A'..'Z';

STR_LAN	:	'"|' LETTER LETTER '|"';

string_value	:	(IMPORTED_VALUE | ID | multi_lan_str | STRING); // support multi language string

multi_lan_str	:	STRING single_lan_str+;
//single_lan_str	:	WS* '"|' lan_id '|"' lan_str; // single language string
single_lan_str	:	WS* lan_id lan_str; // single language string
lan_id	:	STR_LAN;
lan_str	:	STRING;

就可以了。

3.目前暂时缺点是:

对于lan_id,得到的是:

"|sv|"

而不是:

"sv"

但是凑合用了。

 

【总结】

antlr中的语法,尤其是lexer,还是需要额外小心,否则内容被之前的token匹配掉了,后面就无法匹配了。需要额外小心。



发表评论

电子邮件地址不会被公开。 必填项已用*标注

无觅相关文章插件,快速提升流量