Все грамматики ANTLR выдают ошибку «нет жизнеспособной альтернативы на входе« <EOF>»» - PullRequest
2 голосов
/ 07 сентября 2011

Мне нужно разобрать язык небольших выражений (и, или нет, парены меняют приоритет), поэтому выбрал ANTLR для этой задачи, я добился хорошего прогресса (ANTLRWorks очень хорош для новичка). Я использовал несколько ссылок «Начало работы» с веб-сайта antlr, а затем нашел две публикации в блоге, которые идеально подходят для того, что я пытаюсь достичь:

http://www.codeproject.com/KB/recipes/sota_expression_evaluator.aspx http://www.alittlemadness.com/2006/06/05/antlr-by-example-part-1-the-language

Проблема, с которой я сталкиваюсь, не имеет значения, какой ввод я добавлю, я всегда получаю ошибку:

Строка 1:29. На входе 'EOF' нет реальной альтернативы

Так что, как часть моего устранения неполадок, я решил попробовать грамматику, которая, как я знал, была хорошей, и сгенерировал лексер / парсер из грамматики ECalc.g, найденной по первой ссылке. К моему удивлению, я получил ту же ошибку при использовании этой грамматики! Я сбит с толку. Единственные изменения, которые я внес в грамматику, заключались в том, чтобы заставить ее генерировать код Java и удалить код CSharp в разделе @members.

Вот мой класс тестера:

public class ECalcTester {
private final static Logger logger = Logger.getLogger(ECalcTester.class);

public static void main(String[] args) {
    BasicConfigurator.configure();
    ECalcLexer lex = new ECalcLexer(new ANTLRStringStream("false || not (false and true)"));

    Token token;
    while (true) {
        token = lex.nextToken();
        if (token.getType() == Token.EOF) {
            break;
        }

        System.out.println("Token: ‘" + token.getText() + "’");
    }

    CommonTokenStream tokens = new CommonTokenStream(lex);
    lex.nextToken();

    ECalcParser parser = new ECalcParser(tokens);
    try {
        logger.debug(parser.expression().getTree());
    } catch (org.antlr.runtime.RecognitionException e) {
        logger.error("Exception ", e);
    }

}

Вот вывод:

Token: ‘false’
Token: ‘ ’
Token: ‘||’
Token: ‘ ’
Token: ‘not’
Token: ‘ ’
Token: ‘(’
Token: ‘false’
Token: ‘ ’
Token: ‘and’
Token: ‘ ’
Token: ‘true’
Token: ‘)’
line 1:29 no viable alternative at input '<EOF>'
0 [main] DEBUG ECalcTester  - <unexpected: [@0,29:29='<EOF>',<-1>,1:29], resync=>

Если я смогу понять, почему это происходит в грамматике, которая должна быть хорошей, я должен быть в состоянии выяснить, почему то же самое происходит в моей грамматике (очень похожая концепция).

Может кто-нибудь предложить какое-нибудь понимание?

1 Ответ

5 голосов
/ 07 сентября 2011

После распечатки ваших токенов вы окажетесь в конце потока токенов. Вам нужно будет сбросить поток токенов, вызвав

lex.reset();

Это заставит лексера вернуться к началу потока токенов, чтобы вы могли вызвать свой анализатор.

...