1

I'm trying to create an interpreter for my scripting language using ANTLR4. I have yet implemented the standard operations (mul, div, sub, etc...) using visitors and now i've to implement a jump \ Salta function call. Jump(n) FunctionCall ignore n rows after his call. Example:

Fai var1 = 3,var2 = 4;
Fai Salta(1);    //my jump() function call
Fai var1=4;
println(var1);

output: 3

This is my current grammar:

grammar TL;
@members{
int salta=0;
}
parse
: block+ EOF
;

block
: DO statement (','statement )* END // Fai a=2,B=e;
; //manca l'if

DO:'Fai';
END:';';
Salta:'Salta';
statement
:assign
|functionCall
|saltaCall
;
functionCall
: Identifier '(' exprList? ')' #identifierFunctionCall
| Println '(' expr? ')' #printlnFunctionCall
| Print '(' expr ')' #printFunctionCall
;
saltaCall
:Salta '(' Number ')' rows[$Number.int]
;
rows[int n]
locals[int i=0;]
:({$i<$n}?END? block {$i++;})*
;

exprList
: expr (',' expr)*
;
assign
:Identifier '=' expr
;

Identifier
: [a-zA-Z_] [a-zA-Z_0-9]*
;

expr
: '-'expr   #unaryMinusExpr
| '!'expr   #notExpr
| expr '^' expr #powerExpr
| expr '*' expr #multiplyExpr
| expr '/' expr #divideExpr
| expr '%' expr #modulusExpr
| expr '+' expr #addExpr
| expr '-' expr #subtractExpr
| expr '>=' expr #gtEqExpr
| expr '<=' expr #ltEqExpr
| expr '>' expr #gtExpr
| expr '<' expr #ltExpr
| expr '==' expr #eqExpr
| expr 'O' expr #orExpr
| expr 'E' expr #andExpr
| expr '=' expr #eqExpr
| Number        #numberExpr
| Bool          #boolExpr
| Null          #nullExpr
| functionCall   #functionCallExpr
| Identifier    #identifierExpr
| String        #stringExpr
| '(' expr ')'  #exprExpr
;
Println:'println';
Print:'print';

Null:'null';

Or : 'O';
And : 'E';
Equals : '==';
NEquals : '!=';
GTEquals : '>=';
LTEquals : '<=';
Pow : '^';
Excl : '!';
GT : '>';
LT : '<';
Add : '+';
Subtract : '-';
Multiply : '*';
Divide : '/';
Modulus : '%';
OBrace : '{';
CBrace : '}';
OBracket : '[';
CBracket : ']';
OParen : '(';
CParen : ')';
Assign : '=';
QMark : '?';
Colon : ':';


Bool
: 'true'
| 'false'
;
Number
: Int ('.' Digit*)?
;


String
: ["] (~["\r\n] | '\\\\' | '\\"')* ["]
| ['] (~['\r\n] | '\\\\' | '\\\'')* [']
;



fragment Int
: [1-9] Digit*
| '0'
;
fragment Digit
: [0-9]
;
fragment NL
: '\n'
;

// ---------SKIP------------
Comment
: ('#' ~[\r\n]* ) -> skip
;
Space
: [ \t\r\n\u000C] -> skip
;

How can I implement that function?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
nik fer
  • 13
  • 3

1 Answers1

1

It's easier to have a look at my Mu interpreter. Your jump call would look a lot like a log call:

jump
 : JUMP expr SCOL
 ;

JUMP : 'jump';

Then override the visitJump method and keep track of the value inside the jump(...) call inside your EvalVisitor.

Now all you would need to do is override the visitBlock method and if the recorded value inside value inside the jump(...) is more then 0, don't visit the next expression. Some pseudo code:

public class EvalVisitor extends MuBaseVisitor<Value> {

    ...

    private Double jumpAmount = 0.0;

    @Override
    public Value visitBlock(@NotNull MuParser.BlockContext ctx) {

        for (MuParser.StatContext statContext : ctx.stat()) {

            if jumpAmount is more than 0, decrease by 1
            else visit (execute) statContext
        }

        return Value.VOID;
    }

    @Override
    public Value visitJump(@NotNull MuParser.JumpContext ctx) {

        Value amount = this.visit(ctx.expr());

        jumpAmount = amount.asDouble();

        return amount;
    }

    ...
}
Bart Kiers
  • 166,582
  • 36
  • 299
  • 288