2012-08-30 2 views
4

У меня есть следующая грамматика:ANTLR лексер не LOOKAHEAD на всех

rule: 'aaa' | 'a' 'a'; 

Он может успешно разбирать строку «ааа», но он не может разобрать «аа» со следующей ошибкой:

line 1:2 mismatched character '<EOF>' expecting 'a' 

FYI, это проблема лексера, а не парсер, потому что я даже не называю синтаксический анализатор. Основная функция выглядит следующим образом:

@members { 
    public static void main(String[] args) throws Exception { 
    RecipeLexer lexer = new RecipeLexer(new ANTLRInputStream(System.in)); 
    for (Token t = lexer.nextToken(); t.getType() != EOF; t = lexer.nextToken()) 
     System.out.println(t.getType()); 
    } 
} 

результат тот же с более очевидной версии:

rule: AAA | A A; 
AAA: 'aaa'; 
A: 'a'; 

Очевидно, что ANTLR лексер пытается соответствовать входному «аа» с правилом AAA, который терпит неудачу. Кроме того, ANTLR является парсером LL (*) или что-то еще, лексер должен работать отдельно от анализатора, и он должен иметь возможность разрешать двусмысленность. Грамматика отлично работает с хорошим старым lex (или flex), но это не похоже на ANTLR. Так в чем проблема?

Спасибо за помощь!

+0

Как определить маркеры в вашем лексере? Полагаю, что lexer предпочитает совпадение для 'a' вместо' aaa', учитывая один вход 'a'. – Dervall

+0

ANTLR жадный. –

+0

@Dervall Файл токена выглядит так: 'A = 4 AAA = 5' Он предпочитает' aaa' '' ''. И он может анализировать 'aaa' и' a', но не 'aa'. –

ответ

6

Созданные парсером ANTLR являются (или могут быть) LL (*), а не его лексеры.

Когда лексический видит вход "aa", он пытается соответствовать лексема AAA. Когда он этого не делает, он пытается сопоставить любой другой токен, который также соответствует "aa" (лексер не возвращается к A!). Поскольку это невозможно, возникает ошибка.

Это обычно не проблема, так как на практике часто бывает какое-то правило идентификатора "aa". Итак, какова реальная проблема, которую вы пытаетесь решить, или вы только любопытствовали о внутренней работе? Если это первый, отредактируйте свой вопрос и опишите свою актуальную проблему.

+0

Спасибо за разъяснение, Барт. Наверное, это ближе ко второму. Я использую lex/yacc, и я пытаюсь переключиться на ANTLR. У анализатора ANTLR уже есть ограничение как анализатор LL, но, как вы указали, речь идет о lexer, а не о парсере. Честно говоря, я буду немного разочарован, если ANTLR lexer не сможет справиться с такой сложностью, где могут работать другие лексеры, такие как 'lex'. Стоимость возврата не будет огромной, O (n^2) в худшем случае и может быть лучше, если ее можно будет отнести к делу. –

+0

@ KJ, есть способы решить это, конечно. Но вместо того, чтобы объяснять, как решить ваш пример соломы, я бы скорее попытался предложить решение «реальной» проблемы под рукой (в противном случае я в конечном итоге отвечу дважды ...). –

+0

Боюсь, я не ищу обходного пути для конкретной проблемы. Как я уже сказал, это ближе к любопытству, поскольку я рассматривал возможность использования ANTLR, потому что он поддерживает JAVA, в отличие от yacc, но я осторожничаю.Я знаю, что есть обходной путь к этой проблеме с ручным поиском (я видел ваш [предыдущий пост] (http://stackoverflow.com/a/8800722/456933)), но для решения подобных проблем, случай кажется ненадежным .. Спасибо за ответ, хотя! –

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