我正在尝试使用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
;
我该如何实现该功能?
答案 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;
}
...
}