Antlr 语法不起作用(NoViableAltException)

Antlr 语法不起作用(NoViableAltException),antlr,antlr3,Antlr,Antlr3,我是ANTLR的新手,我正试着和它一起玩。这是我所能想到的最简单的语法,当我解析变量“id123”时,它仍然不起作用(NoViableAltException),但它适用于“abc1”、“ab”、“c1d2f3” 我使用的是AntlR3.1.3和ANTLRWorks 1.4 options { language = 'CSharp2'; output = AST; } assign : variable '=' value; value : (variable|

我是ANTLR的新手,我正试着和它一起玩。这是我所能想到的最简单的语法,当我解析变量“id123”时,它仍然不起作用(NoViableAltException),但它适用于“abc1”、“ab”、“c1d2f3”

我使用的是AntlR3.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  :   '"' (~'"')* '"';

ANTLR的lexer尽量匹配。每当两个(或更多)规则匹配相同数量的字符时,首先定义的规则将“获胜”。因此,每当词法分析器偶然发现单个数字时,就会创建一个
数字
标记,因为它是在
自然
之前定义的:

DIGIT   :   '0'..'9';
NATURAL :   (DIGIT)+;   
但是对于输入
“id123”
,lexer生成了以下3个令牌:

LETTER          'i'
LETTER          'd'
NATURAL         '123'
因为lexer贪婪地匹配,因此创建了一个
NATURAL
,而不是三个
数字
标记

您应该做的是将lexer规则改为
变量

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');
还要注意,我制定了两条lexer规则
fragment
s。这意味着lexer永远不会产生
自然
数字
字母
标记。这些
fragment
规则只能由其他lexer规则使用。换句话说,你的lexer只会产生
变量
整数
实数
、和
字符串
标记*(所以你只能在解析器规则中使用这些标记!)


*当然,还有
'='
令牌…

谢谢您的解释,但是现在分配不起作用。我正在尝试“id123=2222”。我只是复制并粘贴了你的答案。