【背景】
如下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;
结果无法匹配:
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匹配掉了,后面就无法匹配了。需要额外小心。