Грамматика antlr4 для интерпретатора - определение точки входа во входном файле

Я пытаюсь понять, как заставить antlr4 выполняться в заданной точке входного файла, а не вверху. Я воспользовался советом пользователей SO и начал решение с помощью посетителей Antlr4.

Мой входной файл объявляет «BASIC», как подпрограммы, и имеет Main внизу. Пример входного файла:

   #Program hello;

   Sub mysub1()
      print "please dont call me but I know you will";
   End Sub

   Sub mysub2()
     #code
   End Sub

   Main() #execute code from here
     call mysub2;
   EndMain

Неудивительно, что он выполняет любой код в Sub, потому что он не знает ничего другого, кроме как начать сверху.

Мой файл грамматики включает

    prog
 :  stat* 'Main' stat* 'EndMain' EOF
 ;

stat
 : call_sub 
 | assignment
 | if_stat
 | while_stat 
     ...

Итак, первый stat* выполняется — и это моя точка зрения, как мне заставить выполнение начинаться с Main. например Как мне обнаружить/использовать токен/правило «Основной», а затем начать посещать его, а не верхнюю часть файла/дерева?

Спасибо заранее.

Кевин


person KevinY    schedule 24.12.2013    source источник


Ответы (1)


Мое решение состояло в том, чтобы объявить логическое значение maindone=false в расширенном классе BaseVisitor, а затем в моем

public Value visitBeginSublabel(@NotNull t5Parser.BeginSublabelContext ctx) { 
    if (maindone == false){
        subs.put(ctx.ID().toString(),ctx); // stash the function/sub name to HashMap
        //main not done. skipping activity
        return null;
    }
    ...
}

и при посещении visitMain

@Override public Value visitMain(@NotNull t5Parser.MainContext ctx) { 
    maindone=true;
    ...

Это, кажется, сделало свое дело. Я также привел в порядок грамматику, чтобы на глобальном уровне можно было объявлять только переменные и некоторые другие необходимые элементы.

Я не говорю, что это идеальный способ выполнения этого упражнения, но, безусловно, он сработал. Я также заявил

public Map< String,t5Parser.BeginactivitylabelContext>subs = new HashMap<String,t5Parser.BeginactivitylabelContext>();

Поскольку мне нужен быстрый поиск имен подпрограмм, когда я вызываю их из другой функции, поэтому в моей функции visitCall

  public Value visitCall(@NotNull t5Parser.CallContext ctx) { 
            this.visit(subs.get(ctx.ID().toString()));
         ...

Где мой исходный файл имеет

Main
   call myfunction()
EndMain

Занимаюсь этим всего неделю, поэтому ищу советы и лучшие ответы.

person KevinY    schedule 24.12.2013