⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sbasic.java

📁 一个很小的语言解释器,表述了一个微型的 smallbasic语言的解释过程,可以以该语言进行简单的过程语言编程
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 创建日期 2005-4-4
 *
 * TODO 要更改此生成的文件的模板,请转至
 * 窗口 - 首选项 - Java - 代码样式 - 代码模板
 */
import java.io.*;
import java.util.*;
/**
 * @author 姜周扬
 *
 * TODO Small Basic 语言解释器
 * 解释器包含了:表达式解析和解释器,两者合为一个类有助于优化解释器性能
 */
class SBasic {
	//程序最大长度限制
	final int PROG_SIZE = 10000;
	//表达式当前项类型
	final int NONE = 0;
	final int DELIMITER = 1;
	final int VARIABLE = 2;
	final int NUMBER = 3;
	final int COMMAND = 4;
	final int QUOTEDSTR = 5;
	//程序错误类型
	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;
	//Small Basic 内部定义关键字
	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; 
	//表达式结束符
	final String EOP = "\0";
	//二元操作符代码如<= >= !=
	final char LE = 1;
	final char GE = 2;
	final char NE = 3;
	//变量数组
	private double vars[];
	
	/*
	 * 
	 * @author Administrator
	 *
	 * TODO 这个类链接关键字到它的关键项
	 * 
	 */
	class Keyword{
		//关键字来源
		String keyword;
		//关键字内部表示方法索引
		int keywordTok;
		
		Keyword(String str,int t){
			keyword = str;
			keywordTok = t;
		}
	}
	/*
	 * 关键字内部映射表:所有关键字输入均要求为小写字母
	 */
	Keyword kwTable[] = {
			new Keyword("print",PRINT),
			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;
	//程序执行当前下标
	private int progIdx;
	
	//存储当前表达式项
	private String token;
	//当前表达式项类型
	private int tokType;
	
	//内部关键字表示下标
	private int kwToken;
	
	/*
	 * 
	 * @author Administrator
	 *
	 * TODO 提供FOR循环支持
	 * 
	 */
	class ForInfo{
		//记录循环次数
		int var;
		//临时变量
		double target;
		//源程序代码中LOOP地址下标
		int loc;
	}
	//FOR循环支持栈
	private Stack fStack;
	
	/*
	 * 
	 * @author Administrator
	 *
	 * TODO 定义标签实体类
	 * 
	 */
	class Label{
		//标签名称
		String name;
		//源程序中标签地址
		int loc;
		public Label(String n,int i){
			name = n;
			loc = i;
		}
	}
	//标签表 Map
	private TreeMap labelTable;
	
	//GOSUB子程序调用栈
	private Stack gStack;
	
	//逻辑操作符
	char rops[] = {
			GE,NE,LE,'<','>','=',0
	};
	/* 创建一个逻辑操作符容器
	 * 以便于检查
	 */
	String relops = new String(rops);
	//**************** 类属性定义完毕  解释器部分开始  ********************************
	/*
	 * SBasic 构造函数
	 */
	public SBasic(String progName) throws InterpreterException {
		char tempbuf[] = new char[PROG_SIZE];
		int size;
		
		//载入源程序执行
		size = loadProgram(tempbuf,progName);
		if(size != -1){
			//创建一个程序大小的对象级数组保存源程序
			prog = new char[size];
			//将源程序字符拷贝到源程序数组
			System.arraycopy(tempbuf,0,prog,0,size);			
		}
	}
	/*
	 * 载入源程序
	 */
	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);
		}
		//如果文件以文件结束符EOF结束,回退一格去除结束符
		if(p[size-1]==(char)26) size--;
		//返回程序大小
		return size;
	}
	/*
	 * 执行解释器程序
	 */
	public void run() throws InterpreterException{
		//初始化解释所需存储空间
		//变量值保存数组
		vars = new double[26];
		//FOR循环支持栈
		fStack = new Stack();
		//标签树图
		labelTable = new TreeMap();
		//程序调用栈
		gStack = new Stack();
		progIdx = 0;
		//查找程序中所有的标签
		scanLabels();
		//执行解释程序
		sbInterp();		
	}
	/*
	 * Small Basic 程序解释执行入口点
	 */
	private void sbInterp() throws InterpreterException{
		//程序解释主循环
		do{
			getToken();
			//检查赋值语句
			if(tokType == VARIABLE){
				putBack();//将变量名返回输入流
				//执行赋值语句
				assignment();
			}
			else{//是关键字
				switch(kwToken){
				case PRINT:
					print();
					break;
				case GOTO:
					execGoto();
					break;
				case IF:
					execIf();
					break;
				case FOR:
					execFor();
					break;
				case NEXT:
					next();
					break;
				case INPUT:
					input();
					break;
				case GOSUB:
					gosub();
					break;
				case RETURN:
					greturn();
					break;
				case END:
					return;
				}
			}
		}while(!token.equals(EOP));
	}
    /*
     * 查找程序中所有的标签
     */
	private void scanLabels() throws InterpreterException{
		int i;
		Object result;
		//检查第一个项是否为标签
		getToken();
		if(tokType == NUMBER)
			labelTable.put(token,new Integer(progIdx));
		findEOL();
		do{
			getToken();
			if(tokType == NUMBER){//必须是一个行号
				result = labelTable.put(token,new Integer(progIdx));
				if(result != null) handleErr(DUPLABEL);
			}
			//如果不是空白行,查找下一行
			if(kwToken != EOL) findEOL();
		}while(!token.equals(EOP));
		progIdx = 0;
	}
	/*
	 * 查找下一行的起始点
	 */
	private void findEOL()
	{
		while(progIdx<prog.length && prog[progIdx]!='\n') ++progIdx;
		if(progIdx<prog.length) progIdx++;
	}
	/* X=3
	 * 赋值语句 标记一个变量的值
	 */
	private void assignment() throws InterpreterException{
		int var;
		double value;
		char vname;
		//获取变量的名称,第一个字母有效
		getToken();
		vname = token.charAt(0);
		//不是可识变量名
		if(!Character.isLetter(vname)){
			handleErr(NOTVAR);
			return;
		}
		//转换成变量表的下标
		var = (int) Character.toUpperCase(vname)-'A';
		//获得等号
		getToken();
		if(!token.equals("=")){
			handleErr(EQUALEXPECTED);
			return;
		}
		//获得变量的值
		value = evaluate();
		//标记变量值
		vars[var] = value;
	}
	/* PRINT X
	 * PRINT "...",X;X*X
	 * 打印语句处理
	 */
	private void print() throws InterpreterException{
		double result;
		int len = 0;
		int spaces;
		String lastDelim = "";
		
		do{
			//获得下一项
			getToken();
			if(kwToken == EOL || token.equals(EOP)) break;
			//是一个提示字符串
			if(tokType == QUOTEDSTR){
				System.out.print(token);
				len += token.length();
				getToken();
			}//是一个表达式
			else{
				putBack();
				result = evaluate();
				getToken();
				System.out.print(result);
				//添加值的长度,用来计算
				Double t=new Double(result);
				len += t.toString().length();
			}
			lastDelim = token;
			//如果为逗号分隔符,输出一个制表符
			if(lastDelim.equals(",")){
				//计算所需的输出空格
				spaces = 8 - (len % 8);
				len += spaces;
				while(spaces != 0){
					System.out.print(" ");
					spaces--;
				}
			}//如果为分号分隔符,输出一个空格
			else if(token.equals(";")){
				System.out.print(" ");
				len++;
			}
			else if(kwToken != EOL && !token.equals(EOP))
				handleErr(SYNTAX);
		}while(lastDelim.equals(";") || lastDelim.equals(","));
		//输出一行后,换行(PRINT 不能以; , 结束)
		if(kwToken==EOL || token.equals(EOP)){
			if(!lastDelim.equals(";") && !lastDelim.equals(","))
				System.out.println();
		}
		else handleErr(SYNTAX);
	}
	/* GOTO 行号
	 * GOTO 语句执行块
	 */
	private void execGoto() throws InterpreterException{
		Integer loc;
		//获得行号
		getToken();
		loc = (Integer)labelTable.get(token);
		//未定义行号
		if(loc == null)
			handleErr(UNDEFLABEL);
		else//程序跳转到指定的行号
			progIdx = loc.intValue();
	}
	/* IF 表达式 op 表达式 THEN 语句
	 * IF 语句执行模块
	 */
	private void execIf() throws InterpreterException{
		double result;
		//获得表达式的结果
		result = evaluate();
		/*如果表达式为真(即非0) 执行 IF语句块,否则
		 * 跳过THEN 到下一行,继续解释
		 */
		if(result != 0.0){
			getToken();
			if(kwToken != THEN){//没有THEN语句块
				handleErr(THENEXPECTED);
				return;
			}
		}//跳过此行
		else findEOL();
	}
	/* FOR 变量=初值 TO 结束值
	 * 执行语句
	 * NEXT
	 * FOR语句处理函数
	 */
	private void execFor() throws InterpreterException{
		ForInfo stckvar = new ForInfo();
		double value;
		char vname;
		//读取控制变量
		getToken();
		vname = token.charAt(0);
		//不可识别变量
		if(!Character.isLetter(vname)){
			handleErr(NOTVAR);
			return;
		}
		//保存控制变量下标
		stckvar.var = Character.toUpperCase(vname) - 'A';
		//读取等号
		getToken();
		if(token.charAt(0) != '='){
			handleErr(EQUALEXPECTED);
			return;
		}
		//获得初始变量值
		value = evaluate();
		vars[stckvar.var] = value;
		
		//读取TO关键字
		getToken();
		if(kwToken != TO) handleErr(TOEXPECTED);
		//计算循环结束值
		stckvar.target = evaluate();
		/* 如果循环可以至少执行一次的话
		 * 将变量压到FOR支持栈中
		 */
		if(value >= vars[stckvar.var]){
			stckvar.loc = progIdx;
			fStack.push(stckvar);
		}
		else//否则跳过FOR循环语句
			while(kwToken != NEXT) getToken();
	}
	/* FOR语句的NEXT处理
	 * NEXT 从栈中弹出变量
	 */
	private void next() throws InterpreterException{
		ForInfo stckvar;
		try{
			//完成本次FOR循环
			stckvar = (ForInfo)fStack.pop();
			//将变量值加1 控制变量只能递增
			vars[stckvar.var]++;
			//循环完毕
			if(vars[stckvar.var] > stckvar.target) return;
			//继续循环
			fStack.push(stckvar);
			progIdx = stckvar.loc;
		}//FOR 不配对 NEXT

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -