我是ANTLR的新手,我正试着玩它。这是我能想到的最简单的语法,当我解析变量“id123”时它仍然无效(NoViableAltException),但它适用于“abc1”,“ab”,“c1d2f3”。
我正在使用ANTLR 3.1.3和ANTLRWorks 1.4。
options
{
language = 'CSharp2';
output = AST;
}
assign : variable '=' value;
value : (variable|constant);
variable: LETTER (LETTER|DIGIT)*;
constant: (STRING|INTEGER);
DIGIT : '0'..'9';
NATURAL : (DIGIT)+;
INTEGER : ('-')? NATURAL;
REAL : (INTEGER '.' NATURAL);
LETTER : ('a'..'z'|'A'..'Z');
CR : '\r' { $channel = HIDDEN; };
LF : '\n' { $channel = HIDDEN; };
CRLF : CR LF { $channel = HIDDEN; };
SPACE : (' '|'\t') { $channel = HIDDEN; };
STRING : '"' (~'"')* '"';
答案 0 :(得分:2)
ANTLR的词法分析器试图尽可能地匹配。每当两个(或更多)规则匹配相同数量的字符时,首先定义的规则将“赢”。因此,只要词法分析器偶然发现一个数字,就会创建一个DIGIT
标记,因为它是在NATURAL
之前定义的:
DIGIT : '0'..'9';
NATURAL : (DIGIT)+;
但是对于输入"id123"
,词法分析器产生了以下3个标记:
LETTER 'i'
LETTER 'd'
NATURAL '123'
因为词法分析器贪婪地匹配,因此创建了NATURAL
,并且不三个DIGIT
令牌。
你应该做的是制作词法{ER}规则{/ 1}}:
variable
另请注意,我制作了几个词法规则assign : VARIABLE '=' value;
value : (VARIABLE | constant);
constant : (STRING | INTEGER | REAL);
VARIABLE : LETTER (LETTER|DIGIT)*;
INTEGER : ('-')? NATURAL;
REAL : (INTEGER '.' NATURAL);
SPACE : (' ' | '\t' | '\r' | '\n') { $channel = HIDDEN; };
STRING : '"' (~'"')* '"';
fragment NATURAL : (DIGIT)+;
fragment DIGIT : '0'..'9';
fragment LETTER : ('a'..'z' | 'A'..'Z');
。这意味着词法分析器永远不会生成fragment
,NATURAL
或DIGIT
令牌。这些LETTER
规则只能由其他词法规则使用。换句话说,你的词法分析器只生成fragment
,VARIABLE
,INTEGER
和REAL
标记*(因此这些是你可以在解析器规则中使用的唯一标记) !)。
*和STRING
令牌,当然......