ANTLR如何将列表中缺少的元素解析为null(或其他占位符值(?以下表达式应可通过访客界面进行区分。
[1,,2]
[1,2,]
[,1,2]
下面是一个示例语法:
grammar Test;
list : '[' elems+=number? (',' elems+=number?)* ']';
number : DIGIT+;
DIGIT: [0-9];
下面是一个用 Kotlin 编写的测试程序:
fun main(args: Array<String>) {
println(doTest("[1,2,]")) // Actual: [1, 2] Expected: [1, 2, null]
println(doTest("[1,,2]")) // Actual: [1, 2] Expected: [1, null, 2]
println(doTest("[,1,2]")) // Actual: [1, 2] Expected: [null, 1, 2]
}
fun doTest(input: String): List<Int?> {
val lexer = TestLexer(CharStreams.fromString(input))
val tokens = CommonTokenStream(lexer)
val parser = TestParser(tokens)
return Visitor.visit(parser.list())
}
object Visitor : TestBaseVisitor<List<Int?>>() {
override fun visitList(ctx: TestParser.ListContext): List<Int?> =
ctx.elems.map { s -> s.text.toIntOrNull() }
}
这将生成一个类似于所有三个表达式的列表[1,2]
。我可以进行哪些更改才能区分这些输入?
这是我会怎么做的...
语法:
grammar Test;
list : '[' leading_item? item* ']';
leading_item:
NUMBER
;
item:
COMMA | COMMA NUMBER
;
NUMBER:
'0' | ('1'..'9')('0'..'9')*
;
COMMA:
','
;
扩展 antlr 提供的基本访问者:
public class TestVisitor extends TestBaseVisitor<ArrayList<String>> {
@Override
public ArrayList<String> visitList(ListContext ctx) {
ArrayList<String> ret = new ArrayList<String>();
if(ctx.leading_item() != null) {
ret.add(ctx.leading_item().NUMBER().getText());
}
if(ctx.item() != null) {
for(ItemContext itemCtx : ctx.item()) {
if(itemCtx.NUMBER() != null) {
ret.add(itemCtx.NUMBER().getText());
}
else {
ret.add("");
}
}
}
return ret;
}
}
称之为
TestLexer lexer = new TestLexer(charStream);
TokenStream tokens = new CommonTokenStream(lexer);
TestParser parser = new TestParser(tokens);
ParseTree tree = parser.list();
TestVisitor visitor = new TestVisitor();
ArrayList<String> list = visitor.visit(tree);
注意:
您必须记住,ANTLR"仅"提供了一种简单的方法来浏览语法。列表、逗号、数字的语义与解析器无关。因此,当您谈到Missing Elements时,它超出了解析器的联盟。