Мне нужно разобрать язык небольших выражений (и, или нет, парены меняют приоритет), поэтому выбрал 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=>
Если я смогу понять, почему это происходит в грамматике, которая должна быть хорошей, я должен быть в состоянии выяснить, почему то же самое происходит в моей грамматике (очень похожая концепция).
Может кто-нибудь предложить какое-нибудь понимание?