实现跳转功能

时间:2014-09-02 07:55:55

标签: antlr4 scripting-language

我正在尝试使用ANTLR4为我的脚本语言创建一个解释器。我还使用访问者实现了标准操作(mul,div,sub等),现在我要实现一个jump \ Salta函数调用。 Jump(n) FunctionCall在调用后忽略 n 行。例如:

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

output: 3

这是我目前的语法:

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
;

我该如何实现该功能?

1 个答案:

答案 0 :(得分:1)

更容易看一下我的Mu interpreter。您的jump电话看起来很像log电话:

jump
 : JUMP expr SCOL
 ;

JUMP : 'jump';

然后覆盖visitJump方法并跟踪jump(...)EvalVisitor来电内的值。

现在您需要做的就是覆盖visitBlock方法,如果jump(...)内的值内记录值大于0,请不要访问下一个表达式。一些伪代码:

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

    ...
}