【发布时间】:2016-01-20 16:42:13
【问题描述】:
我正在为给定语言开发语法。 我相信我提出的语法应该有效 - 但 Antlr4 有不同的看法。鉴于这些错误,它看起来像是缺少回溯。但是 Antlr4 应该在没有那个的情况下解析......
每个示例都应该只有一个解决方案。解析过程中存在歧义,但是除了一个选项之外的所有选项都应该是死胡同。所以我希望解析器返回并尝试下一个可能的方法。但它只是报告语法错误。
语法小结: 有以“#”分隔的元素。在一个元素之后,可以有一个可选的跳转,由一个 '=' 表示。如果元素本身包含 '#' 或 '=' ,则会通过复制它们来进行转义。 为避免歧义,不允许元素以“#”结尾。所以'###'总是首先是分隔符,然后是下一个元素的转义第一个字符。 '####' 没有分隔符,只有两个转义的 '#' 在名称中。
语法:
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: '=';
测试,解析器错误为 cmets
@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() );
}
由于路径元素不能以散列结尾,三重散列的第一个应该关闭顶层元素并开始子项目元素,它以##开头
@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 之类的东西,您会看到识别出哪些规则等