SoftDev30_15
SoftDev30_15

Reputation: 503

antlr4 switch statement grammar to visitor

As a lot of people around the programming community, I am also trying to build my own programming language for a school project in Java. I am using antlr4 with intellij, as it helps a lot generating the tree at the same time I am writing test code. I created a visitor class to add functionality to my code and so far I was able to make an if/else statement and a while statement. So I would also like to create a switch statement and implement it to the visitor class. My grammar for the switch statement is the following:

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;

So I assume that I start the method like this:

@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;
}

I want to write the case statement inside the switch method but I do not know how to go from here, and I didn't find any simple example... Can anyone point to the right direction, or provide with some simple code? Thanks in advance.

EDIT: A simple example of the syntax that I want is the following:

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

Upvotes: 0

Views: 981

Answers (1)

sepp2k
sepp2k

Reputation: 370465

From your comment it sounds like you're writing an interpreter that executes the code directly in the visitor without going through any IR or anything like that (please correct me if I misunderstood).

So your problem is that you can't just write a switch statement inside your code if you don't even know how many case statements there are going to be - you can't put a case inside a loop after all. And even if that weren't a problem, the other problem would be that case statements need compile-time constants, but you'd need to use them with values you extracted from your parse tree.

If you were generating code, none of that would be a problem because you could just generate the proper amount of cases with the given values and everything would be fine. But you're not, so everything is dynamic and you can't use switch.

But that's not a problem because no one says that you have to implement switch using switch. As you probably know, a switch is just a more convenient (and often more performant) way of writing a series of if statements. In your example (assuming your language has implicit breaks), that'd be:

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

What this means for your interpreter is that you can evaluate the expression you're switching on, then loop over all the cases and for each case compare the evaluated number to the value of the case with an if. As soon as one of the condition matches, you execute the associated code and break out of the loop.

If you don't have implicit breaks, you should instead only break out of the loop when you encounter a break and otherwise use a flag to remember if you've already encountered a true condition and then execute every subsequent code block until you encounter a break or reach the end of the switch.

Upvotes: 0

Related Questions