Antlr4 实现一个跳转函数

Antlr4 实现一个跳转函数,antlr4,scripting-language,Antlr4,Scripting Language,我正在尝试使用ANTLR4为我的脚本语言创建一个解释器。我已经使用访问者实现了标准操作(mul、div、sub等),现在我要实现一个jump\Salta函数调用。跳转(n)函数调用在调用后忽略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=

我正在尝试使用ANTLR4为我的脚本语言创建一个解释器。我已经使用访问者实现了标准操作(mul、div、sub等),现在我要实现一个jump\Salta函数调用。跳转(n)函数调用在调用后忽略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
;
语法TL;
@成员{
int-salta=0;
}
作语法分析
:块+EOF
;
块
:DO语句(“,”语句)*结束//Fai a=2,B=e;
; //曼卡·洛伊夫
DO:‘Fai’;
完:";";
萨尔塔:“萨尔塔”;
陈述
:分配
|函数调用
|盐沼
;
函数调用
:标识符“('exprList?)”#identifierFunctionCall
|Println'('expr?')#printlnFunctionCall
|打印“('expr')”#打印函数调用
;
盐沼
:Salta“('Number')”行[$Number.int]
;
行[int n]
局部变量[int i=0;]

:({$i更容易查看我的。你的
跳转
调用看起来很像
日志
调用:

jump
 : JUMP expr SCOL
 ;

JUMP : 'jump';
然后重写
visitJump
方法,并跟踪
jump(…)
调用中
EvalVisitor
内的值

现在,您需要做的就是重写
visitBlock
方法,如果
跳转(…)
内的记录值大于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;
    }

    ...
}
公共类EvalVisitor扩展了MuBaseVisitor{
...
私人双跳金额=0.0;
@凌驾
公共值visitBlock(@NotNull MuParser.BlockContext ctx){
for(MuParser.StatContext StatContext:ctx.stat()){
如果jumpAmount大于0,则减少1
否则请访问(执行)statContext
}
返回值.VOID;
}
@凌驾
公共值visitJump(@NotNull MuParser.JumpContext ctx){
Value amount=this.visit(ctx.expr());
jumpAmount=amount.asDouble();
退货金额;
}
...
}

我会将
SaltaCall
作为一个解析器规则,即
SaltaCall
,这样你就可以访问它的部分(即
编号
)。谢谢你的评论!!现在,我怎么能忽略n个块呢?