这是我简短的 ANTLR4 语言:
grammar test;
prog: (decl | expr)+
;
decl: doc | quiz
;
doc: '%doc' paramlist
;
quiz: '%quiz' paramlist STR? '%quiz' ENDL
;
paramlist: '(' VAR '=' PARAMVAL {, VAR '=' PARAMVAL}')'
;
expr:expr '\*' expr
|expr '+' expr
|expr '-' expr
|DOC
;
// tokens
DOC: 'doc';
PERCENT: '%';
VAR: \[a-zA-Z\_\]\[a-zA-Z0-9\_\]\* ;
PARAMVAL: \[^,\]+|'"'\[^"\]\*'"' ;
STR: (\~\["\\\\r\\n\] | EscapeSequence)+ ;
fragment EscapeSequence:
'\\' 'u005c'? \[btnfr"'\\\]
| '\\' 'u005c'? (\[0-3\]? \[0-7\])? \[0-7\]
| '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit;
fragment HexDigit: \[0-9a-fA-F\];
ENDL: '\n' ;
WS: [ \t\n]+ -> skip;
为了使用 doc 解析器规则,我编写了“%doc”,ANTLR 根据此屏幕截图识别它。
但是,当我尝试填写缺失的 PARAMVAL 时,解析树会将所有内容识别为 STR。
当您在 STR 规则周围添加分隔符时,它会起作用。不过,我想使用不带分隔符的 STR 规则。
为什么当任何解析器规则都没有使用 STR 时,STR 规则却被识别? (除了测验,但这恰恰是规则的中间部分。
正如评论中的500 - 内部服务器错误所提到的:词法分析器独立于解析器工作。词法分析器遵循 2 条规则:
由于第一条规则,很明显输入
"%doc(v=^)"
变成了 STR
标记。
其他一些不正确的事情,或者工作方式与您想象的不同:在解析器规则中定义文字标记时,ANTLR 会自动创建词法分析器规则。这意味着如果您这样做:
doc
: '%doc' paramlist
;
DOC : 'doc';
PERCENT : '%';
ANTLR 将在幕后创建此内容:
doc
: T__0 paramlist
;
T__0 : '%doc';
DOC : 'doc';
PERCENT : '%';
并且由于规则 1,输入“%doc”将始终成为
T__0
标记,而永远不会成为 PERCENT
和 DOC
标记。
此外,
[^,]
不匹配逗号以外的任何字符:它匹配 ^
或 ,
。您的意思可能是~[,]
。但要小心:执行 ~[,]+
会再次(如 STR
)匹配太多字符。