2014-09-02 60 views
1

我正在尝试使用ANTLR4为我的脚本语言创建解释器。我还没有使用访问者实现标准操作(mul,div,sub等等),现在我已经实现了跳转\ Salta函数调用。 跳转(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

我会让'SaltaCall'成为解析器规则,即'saltaCall',因此您可以访问它的部分(即'Number')。 – Onur 2014-09-02 12:48:22

+0

感谢您的评论!现在,我怎么能忽略n块? – 2014-09-02 13:12:42

回答

0

看看我的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; 
    } 

    ... 
} 
+0

谢谢!!!有用!!! – 2014-09-03 11:25:40

+0

@nikfer,很高兴听到它。 – 2014-09-03 18:27:50