解释器
3.5.3 关键字
Small BASIC解释器只能解释BASIC语言的一个子集,包括以下关键字:
在SBasic中,这些关键字和行结束符EOL的内部表示分别以final类型进行声明,如下所示:
// Internal representation of the Small BASIC keywords.
final int UNKNCOM = 0;
final int PRINT = 1;
final int INPUT = 2;
final int IF = 3;
final int THEN = 4;
final int FOR = 5;
final int NEXT = 6;
final int TO = 7;
final int GOTO = 8;
final int GOSUB = 9;
final int RETURN = 10;
final int END = 11;
final int EOL = 12;
注意UNKNCOM这个变量。lookUp()方法使用这个值来表示未知的关键字。
为了便于将关键字从外部表示转换为相应的内部表示,所有的外部表示和内部表示都保存在一个名为kwTable的表中。这个表由Keyword对象所组成。Keyword类和kwTable的定义如下所示:
// This class links keywords with their keyword tokens.
class Keyword {
String keyword; // string form
int keywordTok; // internal representation
Keyword(String str, int t) {
keyword = str;
keywordTok = t;
}
}
/* Table of keywords with their internal representation.
All keywords must be entered lowercase. */
Keyword kwTable[] = {
new Keyword("print", PRINT), // in this table.
new Keyword("input", INPUT),
new Keyword("if", IF),
new Keyword("then", THEN),
new Keyword("goto", GOTO),
new Keyword("for", FOR),
new Keyword("next", NEXT),
new Keyword("to", TO),
new Keyword("gosub", GOSUB),
new Keyword("return", RETURN),
new Keyword("end", END)
};
lookup()方法就是使用kwTable表,将关键字标识符转换为相应的内部表示。如果kwTable表中没有匹配标识符,lookup()将返回UNKNCOM。lookup()方法的代码如下:
/* Look up a token's internal representation in the
token table. */
private int lookUp(String s)
{
int i;
// Convert to lowercase.
s = s.toLowerCase();
// See if token is in table.
for(i=0; i < kwTable.length; i++)
if(kwTable[i].keyword.equals(s))
return kwTable[i].keywordTok;
return UNKNCOM; // unknown keyword
}
3.5.4 run()方法
SBasic对象创建之后,解析器调用run()方法执行它先前读入的程序。run()的代码如下所示:
// Execute the program.
public void run() throws InterpreterException {
// Initialize for new program run.
vars = new double[26];
fStack = new Stack();
labelTable = new TreeMap();
gStack = new Stack();
progIdx = 0;
scanLabels(); // find the labels in the program
sbInterp(); // execute
}
run()方法首先分配4个数据结构:一个保存变量值的数组,一个保存FOR循环的堆栈,一个保存标签的树图(TreeMap)和一个保存GOSUB子函数的堆栈。接下来progIdx变量被置为0,它保存着程序当前被解释的位置。每次调用run()方法时,这些域都会被重新设置,这样解释器就能够重复解释执行相同的程序。
然后调用的是scanLabels()方法,它扫描整个程序,找到所有的标签。每找到一个标签,解释器都把这个标签连同它的位置一起保存到labelTable图中。这些操作可以在程序执行之前加快程序的执行速度。
最后,解析器调用sbInterp()方法开始程序的执行过程。
|