ANTLR рассматривает часть строки как ключевое слово - PullRequest
2 голосов
/ 29 ноября 2010

Я сейчас изучаю ANTLR для себя.Сначала я решил написать простейшую грамматику.Есть простой текстовый файл с директивами:

pid = something.pid
log = something.log

Я написал грамматику:

grammar TestGrammar;

options {
  language = Java;
}

@header {
  package test.antlr;
}

@lexer::header {
  package test.antlr;
}

program
  : directive+
  ;

directive
  : pid
  | log
  ;

pid
  : PID EQ (WORD|POINT)+
  ;

log
  : LOG EQ (WORD|POINT)+
  ;

WS: ( ' '
    | '\t'
    | '\r'
    | '\n'
    ) {$channel=HIDDEN;}
    ;

PID
  : 'pid'
  ;

LOG
  : 'log'
  ;

EQ
  : '='
  ;

POINT
  : '.'
  ;

WORD
  : ('a'..'z'|'A'..'Z'|'_')+
  ;

Я чувствую, что где-то допустил ошибку, и ANTLR доказывает, что выбрасывает MismatchedTokenException.Он обрабатывает что-то. pid как directive и выдает исключение.

Однако я не понимаю, что я делаю неправильно.Любая помощь будет оценена.

Спасибо.

1 Ответ

2 голосов
/ 29 ноября 2010

Лексер - очень простой объект: без вмешательства анализатора он маркирует входной источник. Итак, вход:

pid = something.pid

is not , маркированный как:

PID EQ WORD POINT WORD

а как:

PID EQ WORD POINT PID

Вот почему ваше правило:

pid
  : PID EQ (WORD|POINT)+
  ;

соответствует "pid = something." и оставляет второй "pid" в потоке токенов, ожидая, что EQ примет его (отсюда исключение).

Возможное исправление - сделать что-то вроде этого:

pid
  : PID EQ (word|POINT)+
  ;

log
  : LOG EQ (word|POINT)+
  ;

word
  : WORD
  | PID
  | LOG 
  ;

Или, сделав что-то вроде:

pid
  : PID EQ FULL_WORD
  ;

log
  : LOG EQ FULL_WORD
  ;

// ...

FULL_WORD
  : WORD (POINT WORD)*
  ;

// ...
...