Small BASIC解释器
Small BASIC解释器的代码相当长—— 一般情况下不会将这么长的代码放在书的一章之中。但是不要被它的长度所吓倒。抛开其长度不谈,这个解释器的概念其实比较简单,只要掌握了解释器的一般模式,就能轻松理解它的每个部分。
接下来给出Small BASIC解释器的完整代码。本章剩下的篇幅将详细解释它的工作原理和使用方法。
// A Small BASIC Interpreter.
import java.io.*;
import java.util.*;
// Exception class for interpreter errors.
class InterpreterException extends Exception {
String errStr; // describes the error
public InterpreterException(String str) {
errStr = str;
}
public String toString() {
return errStr;
}
}
// The Small BASIC interpreter.
class SBasic {
final int PROG_SIZE = 10000; // maximum program size
// These are the token types.
final int NONE = 0;
final int DELIMITER = 1;
final int VARIABLE = 2;
final int NUMBER = 3;
final int COMMAND = 4;
final int QUOTEDSTR = 5;
// These are the types of errors.
final int SYNTAX = 0;
final int UNBALPARENS = 1;
final int NOEXP = 2;
final int DIVBYZERO = 3;
final int EQUALEXPECTED = 4;
final int NOTVAR = 5;
final int LABELTABLEFULL = 6;
final int DUPLABEL = 7;
final int UNDEFLABEL = 8;
final int THENEXPECTED = 9;
final int TOEXPECTED = 10;
final int NEXTWITHOUTFOR = 11;
final int RETURNWITHOUTGOSUB = 12;
final int MISSINGQUOTE = 13;
final int FILENOTFOUND = 14;
final int FILEIOERROR = 15;
final int INPUTIOERROR = 16;
// 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;
// This token indicates end-of-program.
final String EOP = "\0";
// Codes for double-operators, such as <=.
final char LE = 1;
final char GE = 2;
final char NE = 3;
// Array for variables.
private double vars[];
// 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)
};
private char[] prog; // refers to program array
private int progIdx; // current index into program
private String token; // holds current token
private int tokType; // holds token's type
private int kwToken; // internal representation of a keyword
// Support for FOR loops.
class ForInfo {
int var; // counter variable
double target; // target value
int loc; // index in source code to loop to
}
// Stack for FOR loops.
private Stack fStack;
// Defines label table entries.
class Label {
String name; // label
int loc; // index of label's location in source file
public Label(String n, int i) {
name = n;
loc = i;
}
}
// A map for labels.
private TreeMap labelTable;
// Stack for gosubs.
private Stack gStack;
// Relational operators.
char rops[] = {
GE, NE, LE, '<', '>', '=', 0
};
/* Create a string containing the relational
operators in order to make checking for
them more convenient. */
String relops = new String(rops);
// 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);
}
}
// 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);
}
|