解释器
SBasic的解释器部分是实际执行程序的代码。一般而言,解释执行一个Small BASIC程序的工作相当容易,因为每个语句(赋值语句除外)都会以一个关键字开头。因此,解释器的工作就是从每行程序代码的开头获得关键字,然后执行关键字所指定的操作。解释器不断重复这个过程,直到解释完整个程序。在本节剩下的篇幅中,将详细分析解释器的每个组成部分。
3.5.1 InterpreterException类
解释器代码文件首先定义了InterpreterException类。当解释过程发生错误时就会抛出该类型的异常。使用SBasic的代码必须处理这个异常。语法错误、I/O错误和数值表达式中的错误都能引起该异常。
3.5.2 SBasic构造函数
下面列出SBasic的构造函数:
// Constructor for SBasic.
public SBasic(String progName)
throws InterpreterException {
char tempbuf[] = new char[PROG_SIZE];
int size;
// Load the program to execute.
size = loadProgram(tempbuf, progName);
if(size != -1) {
// Create a properly sized array to hold the program.
prog = new char[size];
// Copy the program into program array.
System.arraycopy(tempbuf, 0, prog, 0, size);
}
}
SBasic的构造函数接受一个文件名作为参数,指定需要解释的Small BASIC程序源文件。然后创建一个临时缓冲区,以保存读入的源文件。这个缓冲区的大小由PROG_SIZE指定,这个值已经被强制设置为10,000。这也是一个SBasic所能解释的程序的最大长度。在必要的时候,可以方便地改变这个数值。
接下来,构造函数调用loadProgram()方法,该方法读入源程序并返回其字符个数,如果读取失败则返回–1。然后构造函数创建一个长度与该程序长度相同的数组,并将它的一个引用赋给变量prog。最后整个程序被复制到这个新的队列。因此,prog指向的数组的长度与源程序的长度是完全相同的。
loadProgram()方法的代码如下:
// Load a program.
private int loadProgram(char[] p, String fname)
throws InterpreterException
{
int size = 0;
try {
FileReader fr = new FileReader(fname);
BufferedReader br = new BufferedReader(fr);
size = br.read(p, 0, PROG_SIZE);
fr.close();
} catch(FileNotFoundException exc) {
handleErr(FILENOTFOUND);
} catch(IOException exc) {
handleErr(FILEIOERROR);
}
// If file ends with an EOF mark, back up.
if(p[size-1] == (char) 26) size--;
return size; // return size of program
}
这个方法的大部分代码都简单易懂,但请特别注意这几行:
// If file ends with an EOF mark, back up.
if(p[size-1] == (char) 26) size--;
正如注释中说明的那样,这行代码丢弃了代表文件结束的EOF标志。众所周知,有些文本编辑器在文件结尾附加一个文件结束标记(通常是值为26的一个ASCII码),然而有些编辑器不附加任何标记。loadProgram()的做法是:判断文件是否有结束标志,如果有就将它删除,这样能同时处理两种情况。
|