2012-05-24 2 views
1

Я новичок в ANTLR, и я пытаюсь поиграть с ней. Это простейшая грамматика, о которой я мог думать, и все же она не работает (NoViableAltException), когда я разбираю переменную «id123», но она работает для «abc1», «ab», «c1d2f3».Грамматика не работает (NoViableAltException)

Я использую 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 : '"' (~'"')* '"'; 

ответ

2

ANTLR lexer пытается как можно больше сопоставить. Всякий раз, когда два (или более) правила соответствуют одинаковому количеству символов, правило, определяемое первым, будет «выигрывать». Таким образом, всякий раз, когда лексический натыкается на опалить цифры, с DIGIT маркер создается, поскольку он определен до NATURAL:

DIGIT : '0'..'9'; 
NATURAL : (DIGIT)+; 

но для ввода "id123" лексер получены следующие 3 лексемы:

LETTER   'i' 
LETTER   'd' 
NATURAL   '123' 

, потому что лексер встречается жадно, и поэтому создается NATURAL, а не три DIGIT токенов.

Что вы должны сделать, это правило лексического анализатора из 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 токены * (так что это единственные, которые вы можете использовать в правилах вашего парсера!).

* и '=' лексема, конечно ...

+0

Спасибо за объяснение, но теперь назначить работу это не распространяется. Я пытаюсь «id123 = 2222». Я просто скопировал и вставил ваш ответ. –

+0

Nevermind, неправильная отладка ... это работает! –

+0

Добро пожаловать @ JonathasCosta. –

Смежные вопросы