Я разрабатываю грамматику для данного языка. Я считаю, что грамматика, которую я придумал, должна работать, но Antlr4 имеет другое мнение. Учитывая ошибки, он выглядит как пропавший backtracking. Но Antlr4 должен анализировать без этого ...Парсер Antlr4 терпит неудачу - требуется откат?
Каждый из примеров должен иметь ровно одно решение. Во время разбора есть двусмысленности, однако все, кроме одного, могут оказаться тупиками. Поэтому я ожидаю, что парсер вернется и попробует следующий подход. Но он просто сообщает о синтаксической ошибке.
Краткое описание грамматика: Есть элементы, разделенные символом '#'. После элемента может быть необязательный прыжок, который обозначается одним «=». Если сам элемент содержит '#' или '=', они экранируются путем их дублирования. Чтобы избежать двусмысленности, для элемента не допускается «#». Таким образом, '###' всегда является первым разделителем, а затем экранированным первым символом следующего элемента. A '####' не является разделителем, а всего лишь два escape-файла '#' внутри имени.
грамматик:
grammar ConfigPath;
configpath: toplevelement subprojectelement* EOF;
subprojectelement: '#' path jump?;
toplevelement: '#' path jump?;
jump: jumpcommand '=' jumpdestination;
jumpcommand: '#d' | '#devpath';
jumpdestination: NONHASHCHAR+;
path: pathelement ('/' pathelement)*;
pathelement: escapedCharacterHash* escapedCharacter ;
escapedCharacterHash: escapedCharacter | '##';
escapedCharacter: NONHASHCHAR | '==';
NONHASHCHAR: ~('#' | '/' | '=');
HASH: '#';
EQ: '=';
тесты, с ошибками синтаксического анализатора в комментариях
@Test
public void testTripleHash() throws Exception {
ConfigpathContext c = parse("#BU/ConfigPath###sub");
// line 1:16 extraneous input '#' expecting {'##', '==', NONHASHCHAR}
Assert.assertEquals("#BU/ConfigPath", c.toplevelement().getText());
Assert.assertEquals("###sub", c.subprojectelement().get(0).path().getText());
}
Поскольку pathelement не может заканчиваться хэш, первый тройного хэш должен закрыть toplevelelement и начать подпроект, который начинается с: ##
@Test
public void testDoubleHash() throws Exception {
ConfigpathContext c = parse("#BU/proj##bla#d==u##bla");
// line 1:15 mismatched input '==' expecting '='
Assert.assertEquals("#BU/proj##bla", c.toplevelement().getText());
Assert.assertEquals("#d==u##bla", c.subprojectelement().get(0).getText());
}
@Test
public void testJumps() throws Exception {
ConfigpathContext c = parse("#BU/pro##dla#du##d==la#d=dest");
// line 1:14 missing '=' at 'u'
Assert.assertEquals("#BU/pro##dla", c.toplevelement().getText());
Assert.assertEquals(1, c.subprojectelement().size());
Assert.assertEquals("#du##d==la", c.subprojectelement().get(0).path().getText());
Assert.assertEquals("dest", c.subprojectelement().get(0).jump().jumpdestination().getText());
}
private ConfigpathContext parse(String src) {
ConfigPathParser parser = new ConfigPathParser(new CommonTokenStream(new ConfigPathLexer(new ANTLRInputStream(src))));
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException("line " + line + ":" + charPositionInLine + " " + msg);
}
});
return parser.configpath();
}
Есть ли способ изменить грамматику принять тесты? Или Antlr4 просто не может разобрать такую грамматику? Будет ли Antlr3 с возвратом найти решения?
Ваша грамматика неправильно - если предположить, что синтаксический анализатор должен принять ваши примеры. Всего несколько советов - парсер и лексер определяют первое правило, поэтому вам нужно убедиться, что нет никакой двусмысленности. Если вы собираетесь использовать что-то вроде antlrworks, вы увидите, какое правило распознано и т. Д. – cantSleepNow