Совместное использование кода посетителя Antlr - PullRequest
0 голосов
/ 28 сентября 2018

У меня есть два файла грамматики / посетителей, Simple и Complex, которые разбивают объекты JSON на строки.Сложные объекты, которые я анализирую, могут содержать несколько простых объектов (вместе с дополнительными вещами).Для простоты, скажем, что когда я анализирую базовый простой объект (не простой объект, содержащийся в объекте Complex), я хочу начать строку с чего-то вроде «Simple start:», но когда я достигаю простой объект внутри объекта ComplexЯ хочу начать это с чего-то другого, скажем, «Простой внутри комплекса:».

Так что в настоящее время у меня есть два разных класса посетителей, метод visitSimpleObject простого посетителя будет возвращать строку, начинающуюся с «Простой запуск:»тогда как метод visitSimpleObject посетителя Complex вернет строку, начинающуюся с "Simple in Complex:".Помимо этой разницы, все остальное должно быть одинаковым, все остальное в Простом объекте может быть проанализировано одинаково, независимо от того, находится оно отдельно или внутри Сложного объекта.

Мой вопрос: как я могу поделиться кодом между этими двумя посетителями?Очевидно, что я мог бы скопировать и вставить весь соответствующий код SimpleVisitor в ComplexVisitor, но тогда мне придется синхронизировать их при любых изменениях.

Примечание: два класса посетителей уже расширяют BaseVisitor класс, поэтому я не могу использовать типичное наследование

1 Ответ

0 голосов
/ 28 сентября 2018

Вы можете использовать наследование, чтобы сделать это, см., Например: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

Короткий пример будет выглядеть примерно так:

abstract class Visitor{

    public void sharedMethod() {
        //Do something
    }

    public abstract void visitSimpleObject();
}

class SimpleVisitor extends Visitor{

    @Override
    public void visitSimpleObject() {
        System.out.println("Simple Start:");
    }
}

class ComplexVisitor extends Visitor{

    @Override
    public void visitSimpleObject() {
        System.out.println("Simple within Complex:");   
    }
}

В этом случае оба ваших посетителя будут расширяться оттот же суперкласс (посетитель), где находится общий код.Оба подкласса могут определять свое собственное поведение.Суперкласс сам может также расширить посетителя другого типа (или реализовать интерфейс).

РЕДАКТИРОВАТЬ

После комментариев может быть больше похоже на это:

Пример Ex.g4: грамматикаПример;

START_COMPLEX : 'complex';
START_SIMPLE : 'simple';
SEPERATOR : ':';
TEXT : [A-Za-z]+;

simple : START_SIMPLE ' ' SEPERATOR ' ' TEXT;
complex : START_COMPLEX ' ' SEPERATOR ' ' TEXT;

И пример кода:

public class Example{

    abstract class Visitor extends ExBaseVisitor<String>{
        @Override
        public String visitComplex(ExParser.ComplexContext ctx) {
            System.out.println("Visiting complex");
            return "";
        }

    }

    class SimpleVisitor extends Visitor{
        @Override
        public String visitSimple(ExParser.SimpleContext ctx) {
            System.out.println("Visiting Simple! " + ctx.TEXT());   
            return "";
            }
    }

    class ComplexVisitor extends Visitor{

        @Override
        public String visitSimple(ExParser.SimpleContext ctx) {
            System.out.println("Visiting Simple, from within complex! " + ctx.TEXT());  
            return "";
            }
    }



    public static void main(String[] args) {
        String text = "simple : hi";
        CharStream charStream = new ANTLRInputStream(text);
        ExLexer exLexer = new ExLexer(charStream);
        TokenStream tokenStream = new CommonTokenStream(exLexer);
        ExParser exParser = new ExParser(tokenStream);

        ComplexVisitor complexVisitor = new Example().new ComplexVisitor();
        complexVisitor.visit(exParser.simple());

        String text2 = "simple : hmmmmm";
        CharStream charStream2 = new ANTLRInputStream(text2);
        ExLexer exLexer2 = new ExLexer(charStream2);
        TokenStream tokenStream2 = new CommonTokenStream(exLexer2);
        ExParser exParser2 = new ExParser(tokenStream2);

        SimpleVisitor simpleVisitor = new Example().new SimpleVisitor();
        simpleVisitor.visit(exParser2.simple());


    }


}

Для меня это печатает:

Посещение Простое, изнутри сложное!привет

В гостях просто!хммммм

Общий код теперь называется visitComplex, что, возможно, немного глупо, но для примера, возможно, все в порядке.

...