Разбор ANTLR с отсутствующими элементами - PullRequest
0 голосов
/ 28 июня 2018

Как ANTLR может анализировать отсутствующие элементы в списке как ноль (или какое-либо другое значение заполнителя)? Следующие выражения должны различаться через интерфейс посетителя.

[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] для всех трех выражений. Какие изменения я могу внести, чтобы различать эти входные данные?

1 Ответ

0 голосов
/ 29 июня 2018

Вот как бы я это сделал ...

Грамматика:

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, это выходит за рамки анализа.

...