For loop 如何在javacc中实现循环(For)

For loop 如何在javacc中实现循环(For),for-loop,interpreter,javacc,For Loop,Interpreter,Javacc,我为包含for循环的脚本语言制作了一个解释器,使用javacc我已经定义了语法,但我无法备份到行以重复执行块“for”。 如何备份令牌管理器,以便可以一次又一次地重新解析循环体,从而重新评估循环体 void For(): {ArrayList<String> lst;Token n,v;int i=0;} { "for" "(" n=<ID> ":" v=<ID> ")" "{" (actions()";" )+ "}"

我为包含for循环的脚本语言制作了一个解释器,使用javacc我已经定义了语法,但我无法备份到行以重复执行块“for”。 如何备份令牌管理器,以便可以一次又一次地重新解析循环体,从而重新评估循环体

void For(): {ArrayList<String> lst;Token n,v;int i=0;} {

      "for" "(" n=<ID> ":"  v=<ID> ")" "{"
    (actions()";"  )+
    "}"


    }
void For():{ArrayList lst;标记n,v;int i=0;}{
对于“”((“n=”:“v=”)“{”
(actions()“;”)+
"}"
}

正如javaccfaq()中所解释的,最好的方法是输出某种形式的中间表示,然后对其进行解释。以下是一些常见的方法

  • 一种方法是从解析器输出树。然后解释这棵树。解释器可以使用解释器设计模式

  • 第二种方法是转换为虚拟机的机器代码。这种方法的一个例子可以在位于的Turtle Talk解释器中看到

  • 第三种方法是翻译成另一种高级编程语言,然后可以编译和执行


正如其他答案所说,这就是为什么人们通常在内存中构建一个数据结构,其中一组命令被解析一次,然后可以重复执行

但是,如果您现在想做一个纯解释器,那么需要记住原来是循环的令牌的起始位置(即“for”令牌),并在令牌流中倒回该位置。您可能还需要向前扫描开始括号和结束括号(“{”和“}”),以便知道循环的结束


一旦有了它,“for”命令就会从实际循环变为“if”语句的变体。如果条件为true,则执行命令;如果条件为false,则跳过所有内容,包括结束“}”。当你点击“}”时,你跳回“for”的位置,再次检查条件。

我们可以使用如下的JavaCode产品

前提是action()生产负责每一条生产线。 请将分号移动到actions()产品

令牌:{
}
void For():{ArrayList lst;标记n,v;int i=0;}{
对于“”(“n=”:“v=”)
环体();
}
Java代码
无效循环体(){
令牌t=getNextToken();
while(t.kind!=RCURLY){
动作();
t=getNextToken();
}
}

希望这会有所帮助。

可以通过在每个bnf产品中添加一个参数来告诉它是否执行,从而完成前面的扫描。无论如何,你都需要这个来处理if语句。使用JavaCC,其中最棘手的部分是倒带。生成的令牌管理器中没有接口。可以通过对生成的令牌管理器进行子类化来添加所需的接口。
TOKEN : {
   <LCURLY : "{" >
   <RCURLY : "}" >
}


void For(): {ArrayList<String> lst;Token n,v;int i=0;} {
    "for" "(" n=<ID> ":"  v=<ID> ")" <LCURLY>
         loopBody ();
    <RCURLY>
}

JAVACODE
void loopBody () {
    Token t = getNextToken();
    while (t.kind != RCURLY) {
       actions();
       t = getNextToken();
    }
}