缺少元素的 ANTLR 解析

ANTLR Parse with Missing Elements

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提供的base visitor:

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 'only' 提供了一种简单的方法来遍历语法。列表、逗号、数字的语义与解析器无关。因此,当您谈到缺失元素时,它超出了解析器的范畴。