gpt4 book ai didi

java - 为什么我的 ANTLR4 语法中的这一添加会破坏不相关的规则替代方案?

转载 作者:行者123 更新时间:2023-12-01 12:28:23 29 4
gpt4 key购买 nike

我正在使用 ANTLR4 (org.antlr:antlr4-runtime:4.0) 解析 Magic 卡。这个最小化版本能够解析诸如附魔生物附魔黑色生物,...,以及保护生物免受传奇生物侵害,...

现在我正在尝试启用黑色保护,但这给我带来了问题。

我有以下词法分析器和解析器语法,以及一个测试类:

词法分析器:

lexer grammar OracleLexer;

Black: 'black';
Creature: 'creature';
Creatures: 'creatures';
Enchant: 'enchant';
From: 'from';
Legendary: 'legendary';
Protection: 'protection';

WS: [ \t\f\r\n]+ -> skip;

解析器:

parser grammar OracleParser;

options {
tokenVocab = OracleLexer;
}

line:
keywordAbility EOF;

keywordAbility:
Enchant singularObject #Enchant |
Protection From pluralObject #Protection; // (A)
// Protection From (pluralObject | objectQuality) #Protection; // (B)



singularObject:
objectQuality? Creature;

pluralObject:
objectQuality? Creatures;



objectQuality:
cardtypeQuality+? |
supertypeQuality+ cardtypeQuality*? |
colorQuality+ supertypeQuality* cardtypeQuality*?;

colorQuality:
Black;

supertypeQuality:
Legendary;

cardtypeQuality:
Creature;

测试类:

import static java.util.Arrays.*;
import static java.util.Collections.*;

import java.util.List;

import org.antlr.v4.runtime.*;


public class OracleParserTest {
private static final List<String> ruleNames = unmodifiableList(asList(OracleParser.ruleNames));

public static void main(String[] args) throws Exception {
parse("Enchant creature");
parse("Enchant black creature");
parse("Protection from black");
parse("Protection from black creatures");
}

private static void parse(String ability) throws RecognitionException {
OracleLexer lexer = new OracleLexer(new ANTLRInputStream(ability.toLowerCase()));
lexer.removeErrorListeners();
lexer.addErrorListener(new BailErrorListener());

OracleParser parser = new OracleParser(new CommonTokenStream(lexer));
parser.removeErrorListeners();
parser.setErrorHandler(new BailErrorStrategy());

RuleContext ctx = parser.line();

System.out.println(ctx.toStringTree(ruleNames));
ctx.inspect(ruleNames);
}
}

在解析器中,有一个 keywordAbility 规则,我在其中将替代 (A) 更改为 (B),突然间,我无法再匹配附魔黑色生物。以下是所有文本形式的解析树,如果有帮助的话:

 original strings
Enchant creature
Enchant black creature
Protection from black
Protection from black creatures

parse trees variant (A)
(line (keywordAbility enchant (singularObject creature)) <EOF>)
(line (keywordAbility enchant (singularObject (objectQuality (colorQuality black)) creature)) <EOF>)
does not parse - expected
(line (keywordAbility protection from (pluralObject (objectQuality (colorQuality black)) creatures)) <EOF>)

parse trees variant (B)
(line (keywordAbility enchant (singularObject creature)) <EOF>)
does not parse - problem!
(line (keywordAbility protection from (objectQuality (colorQuality black))) <EOF>)
(line (keywordAbility protection from (pluralObject (objectQuality (colorQuality black)) creatures)) <EOF>)

这是附魔黑色生物的堆栈跟踪:

Exception in thread "main" org.antlr.v4.runtime.misc.ParseCancellationException
at org.antlr.v4.runtime.BailErrorStrategy.recover(BailErrorStrategy.java:51)
at net.slightlymagic.laterna.oracle.grammar.OracleParser.objectQuality(OracleParser.java:462)
at net.slightlymagic.laterna.oracle.grammar.OracleParser.singularObject(OracleParser.java:235)
at net.slightlymagic.laterna.oracle.grammar.OracleParser.keywordAbility(OracleParser.java:161)
at net.slightlymagic.laterna.oracle.grammar.OracleParser.line(OracleParser.java:79)
at net.slightlymagic.laterna.oracle.grammar.OracleParserTest.parse(OracleParserTest.java:49)
at net.slightlymagic.laterna.oracle.grammar.OracleParserTest.main(OracleParserTest.java:35)
Caused by: org.antlr.v4.runtime.NoViableAltException
at org.antlr.v4.runtime.atn.ParserATNSimulator.noViableAlt(ParserATNSimulator.java:1532)
at org.antlr.v4.runtime.atn.ParserATNSimulator.execATNWithFullContext(ParserATNSimulator.java:816)
at org.antlr.v4.runtime.atn.ParserATNSimulator.execATN(ParserATNSimulator.java:701)
at org.antlr.v4.runtime.atn.ParserATNSimulator.predictATN(ParserATNSimulator.java:389)
at org.antlr.v4.runtime.atn.ParserATNSimulator.adaptivePredict(ParserATNSimulator.java:346)
at net.slightlymagic.laterna.oracle.grammar.OracleParser.objectQuality(OracleParser.java:440)
... 5 more

如何让语法(再次)解析此功能,以及为什么它不能按原样工作?

(我曾尝试删除 BailErrorStrategy,这使它可以工作,但也会导致 90% 的所有 Magic 能力被解析为误报,并且没有解释为什么该能力之前有效。BailErrorStrategy 是否/应该干扰回溯? )

最佳答案

ANTLR 4 不使用回溯(运行时库实际上不包含任何形式的此类功能的代码)。

我无法使用此消息末尾的测试来重现此问题。我的猜测是以下原因之一导致了问题:

  1. 您已将 BailErrorStrategy 添加到您的词法分析器中。它从来没有打算以这种方式使用。相反,请遵循 my other answer 中的建议。将语法错误专门推迟给解析器。
  2. 您可能使用的是旧版本的 ANTLR,该版本存在一个已修复的错误。
  3. 仅当使用单独的词法分析器和解析器语法时才会出现此问题(测试使用组合语法)。

测试用例:

@Test
public void testCardParsing() throws Exception {
String grammar =
"grammar Oracle;\n" +
"\n" +
"line @init{setErrorHandler(new BailErrorStrategy());} @after {System.out.println($ctx.toStringTree(this));} :\n" +
" keywordAbility EOF;\n" +
"\n" +
"keywordAbility:\n" +
" Enchant singularObject #Enchant |\n" +
"// Protection From pluralObject #Protection; // (A)\n" +
" Protection From (pluralObject | objectQuality) #Protection; // (B)\n" +
"\n" +
"singularObject:\n" +
" objectQuality? Creature;\n" +
"\n" +
"pluralObject:\n" +
" objectQuality? Creatures;\n" +
"\n" +
"objectQuality:\n" +
" cardtypeQuality+? |\n" +
" supertypeQuality+ cardtypeQuality*? |\n" +
" colorQuality+ supertypeQuality* cardtypeQuality*?;\n" +
"\n" +
"colorQuality:\n" +
" Black;\n" +
"\n" +
"supertypeQuality:\n" +
" Legendary;\n" +
"\n" +
"cardtypeQuality:\n" +
" Creature;\n" +
"\n" +
"Black: 'black';\n" +
"Creature: 'creature';\n" +
"Creatures: 'creatures';\n" +
"Enchant: 'enchant';\n" +
"From: 'from';\n" +
"Legendary: 'legendary';\n" +
"Protection: 'protection';\n" +
"\n" +
"WS: [ \\t\\f\\r\\n]+ -> skip;";

String input = "enchant creature";
String found = execParser("Oracle.g4", grammar, "OracleParser", "OracleLexer", "line", input, true);
assertEquals("(line (keywordAbility enchant (singularObject creature)) <EOF>)\n", found);
assertNull(stderrDuringParse);

input = "enchant black creature";
found = execParser("Oracle.g4", grammar, "OracleParser", "OracleLexer", "line", input, false);
assertEquals("(line (keywordAbility enchant (singularObject (objectQuality (colorQuality black)) creature)) <EOF>)\n", found);
assertNull(stderrDuringParse);

input = "protection from black";
found = execParser("Oracle.g4", grammar, "OracleParser", "OracleLexer", "line", input, false);
assertEquals("(line (keywordAbility protection from (objectQuality (colorQuality black))) <EOF>)\n", found);
assertNull(stderrDuringParse);

input = "protection from black creatures";
found = execParser("Oracle.g4", grammar, "OracleParser", "OracleLexer", "line", input, false);
assertEquals("(line (keywordAbility protection from (pluralObject (objectQuality (colorQuality black)) creatures)) <EOF>)\n", found);
assertNull(stderrDuringParse);
}

关于java - 为什么我的 ANTLR4 语法中的这一添加会破坏不相关的规则替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26142835/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com