我为包含循环的脚本语言编写了一个解释器,使用javacc我已经定义了语法,但是我无法通过备份来重复执行块#34; for& #34 ;. 如何备份令牌管理器以便循环体可以重新解析,从而重新评估,一遍又一遍?
void For(): {ArrayList<String> lst;Token n,v;int i=0;} {
"for" "(" n=<ID> ":" v=<ID> ")" "{"
(actions()";" )+
"}"
}
答案 0 :(得分:0)
正如JavaCC FAQ(http://www.engr.mun.ca/~theo/JavaCC-FAQ/javacc-faq-moz.htm#tth_sEc7.3)中所解释的,最好的方法是输出某种形式的中间表示,然后解释它。一些常见的方法如下。
一种方法是从解析器输出树。然后解释树。解释器可以使用Interpreter设计模式。 https://en.wikipedia.org/wiki/Interpreter_pattern
第二种方法是转换为虚拟机的机器代码。可以在http://www.engr.mun.ca/~theo/Courses/sd/5895-downloads/turtle-talk.zip的Turtle Talk解释器中看到这种方法的一个示例。
第三种方法是转换为另一种高级编程语言,然后可以编译和执行。
答案 1 :(得分:0)
正如其他答案所说,这就是为什么人们通常只在内存中构建一个数据结构,其中一组命令被解析一次,然后可以重复执行。
但是如果你现在想要做一个纯粹的解释器,我需要的是记住结果是循环的令牌的起始位置(即&#34; for&#34;令牌)并回放到令牌流中的该位置。您可能还需要提前扫描开始和结束括号(&#34; {&#34;和&#34;}&#34;),以便您知道循环的结束。
一旦你拥有了这个,你的&#34; for&#34;命令从实际循环变为&#34;变量&#34;如果&#34;声明。如果条件为真,则执行命令,如果条件为假,则跳过所有内容,包括结束&#34;}&#34;。当你点击&#34;}&#34;时,你会跳回到&#34;对于&#34;的位置。再次检查状况。
答案 2 :(得分:0)
我们可以使用如下的JavaCode Production,
如果action()生产负责每一行。 请将分号移动到actions()Production。
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();
}
}
希望这会有所帮助。