antlr4 переключает грамматику оператора на посетителя - PullRequest
0 голосов
/ 23 мая 2018

Как и многие люди из сообщества программистов, я также пытаюсь создать свой собственный язык программирования для школьного проекта на Java.Я использую antlr4 с intellij, так как это очень помогает при создании дерева, в то время как я пишу тестовый код.Я создал класс посетителя, чтобы добавить функциональность в мой код, и до сих пор я мог сделать оператор if / else и оператор while.Поэтому я также хотел бы создать оператор switch и реализовать его для класса посетителя.Моя грамматика для оператора switch следующая:

switch_rule: SWITCH LPAREN any_var RPAREN LBRACKET case_rule* RBRACKET;

case_rule:  CASE any_var PRES statement;

statement:
    expression
    | rule_ifset
    | rule_for
    | method_call
    | rule_whiledo
    | rule_dowhile
    | switch_rule
    | assign
    |var_declaration;

any_var :INT              # NumericConst
        | DOUBLE           # NumericConst
        | IDENTIFIER       # NumericVariable
        |boolean_var      # BooleanConst;

Итак, я предполагаю, что я запускаю метод следующим образом:

@Override
public InputValue visitSwitch_rule(AdamantParser.Switch_ruleContext ctx) {
    InputValue value = this.visit(ctx.any_var().getChild(0));
    if(!value.isInteger()){throw new RuntimeException("switch value is not an integer");}
    else{
           //code to write here
    }

    return InputValue.VOIDval;
}

Я хочу написать оператор case внутри метода switchно я не знаю, как идти отсюда, и я не нашел ни одного простого примера ... Кто-нибудь может указать верное направление или предоставить какой-нибудь простой код?Заранее спасибо.

РЕДАКТИРОВАТЬ: простой пример синтаксиса, который я хочу, следующий:

switch(aNumber){
   case 1: print("return 1");
   case 2: print("return 2");
}

1 Ответ

0 голосов
/ 24 мая 2018

Из вашего комментария звучит так, как будто вы пишете интерпретатор, который выполняет код непосредственно в посетителе, не проходя через IR или что-то подобное (пожалуйста, исправьте меня, если я не понял).

Итак, ваша проблемав том, что вы не можете просто написать оператор switch внутри своего кода, если вы даже не знаете, сколько будет case операторов - вы все равно не можете поместить case в цикл.И даже если бы это не было проблемой, другой проблемой было бы то, что case операторам нужны константы времени компиляции, но вам нужно было бы использовать их со значениями, извлеченными из дерева разбора.

Есливы генерировали код, ничего из этого не было бы проблемой, потому что вы могли просто сгенерировать правильное количество случаев с заданными значениями, и все было бы хорошо.Но это не так, поэтому все динамично и вы не можете использовать switch.

Но это не проблема, потому что никто не говорит, что вам нужно реализовать switch, используя switch.Как вы, вероятно, знаете, переключатель - это просто более удобный (и часто более производительный) способ написания серии операторов if.В вашем примере (при условии, что ваш язык имеет неявные значения break s), это будет:

if (aNumber == 1) {
    print("return 1");
} else if (aNumber == 2) {
    print("return 2");
}

Что это означает для вашего интерпретатора, что вы можете оценить выражение, которое вы включаете, затем выполнить циклдля всех случаев и для каждого случая сравните оцененное число со значением case с if.Как только одно из условий совпадает, вы выполняете соответствующий код и выходите из цикла.

Если у вас нет неявных break s, вы должны вместо этого выходить из цикла только тогда, когдавстретить break и в противном случае использовать флаг, чтобы запомнить, если вы уже столкнулись с истинным условием, а затем выполнять каждый последующий блок кода, пока не встретите break или не достигнете конца switch.

...