📄 interpreter.java
字号:
package gscript;
import java.io.*;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
/**
* 解释器 Interpreter , can execute script that like basic language phrase.
*
* the next version would be comment with english all , sorry
*
* KNOWN ISSUE:
*
* MODIFY LOG :
* 20070117 修改了load()方法,使支持本地文件载入,使可以支持GB2312文件
* 修改了start()方法,使外部传进来的环境变量都变为小写,否则可能无法找到此变量
* 修改了calcExprLogImpl()方法,修正计算 (true) 表达式的错误
* 修改了calcExprNumImpl()方法,修正计算 (true) 表达式的错误
* 修正了Stdlib中一些标准方法的错误,因上0.8.0中修改了容器,所以弹出的先后顺序有误
* 修正了load中,对行尾注释的错误处理
*
*
* <p>Title: </p>
* <p>Description: </p>
* <p>Copyright: Copyright (c) 2007</p>
* <p>Company: </p>
* @author Gust
* @version 0.9.0 sourceforge opened first version.
* @ lastModify 20071109
*/
public class Interpreter {
static private final String[] STRS_RESERVED = {
"if", "else", "endif", "while", "loop", "sub", "ret"};
static private final String STR_SYMBOL = "+-*/><()=, []:&|!\'";
static private final String STR_NUMERIC = "0123456789";
//关键字代码
static private final int
KEYWORD_IF = 0
, KEYWORD_ELSE = 1
, KEYWORD_ENDIF = 2
, KEYWORD_WHILE = 3
, KEYWORD_LOOP = 4
, KEYWORD_SUB = 5
, KEYWORD_RET = 6
;
public static final int
ERR_ILLEGAL = 0
, ERR_VAR = 1
, ERR_TYPE_INVALID = 2
, ERR_NOSUB = 3
, ERR_NO_VAR = 4
, ERR_PARA_CALC = 5
, ERR_PAESEPARA = 6
, ERR_NO_SRC = 7
, ERR_OPSYMB = 8
, ERR_ARR_OUT = 9
;
public static final String[] STRS_ERR = {
" Illegal statment ,"
, " Invalid variable name "
, " Data type error "
, " No such method "
, " No such variable "
, " Method parameter error "
, " Parameter count error "
, " Code not load yet "
, " Operation symbol error "
, " Array out of bounds "
};
//源码字符串数组
private String[] srcCode;
//变量范围控制
private boolean isTopCall; //是否是顶级调用
private Hashtable golbleVar; //全局变量,在init()中初始化
//脚本中过程首地址 ,sub address in script
private Hashtable subAddr;
//系统过程及扩充过程列表 ,extend method lib
private Vector extSubList;
/**
* 构造方法
*/
public Interpreter() {
}
/**
*初始化类
*/
private void init() {
srcCode = null;
//脚本中过程首地址
subAddr = new Hashtable();
//系统过程及扩充过程列表
extSubList = new Vector();
//加入标准库
Stdlib stdlib = new Stdlib();
register(stdlib);
}
/**
* 装载脚本
* @param path String
*/
public void load(String path) {
//初始化
init();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
//File ipFile = new File(path); //j2se使用此方法
//FileInputStream is = new FileInputStream(ipFile);
InputStream is = new Object().getClass().getResourceAsStream(path); //j2me使用
int ch = 0;
while ( (ch = is.read()) != -1) {
baos.write(ch);
}
}
catch (Exception ex) {
}
byte[] srcBytes = baos.toByteArray();
//求出总行数,去掉0x0d标识,win和xnix下的换行不统一
int lineCount = 1; //增加一行,留下余地
for (int i = 0; i < srcBytes.length; i++) {
int ch = srcBytes[i];
if (ch == 0x0a) {
lineCount++;
}
if (ch == 0x0d || ch == 0x09) { //预处理0x0d0a=0x20,0x09=0x20
srcBytes[i] = 0x20;
}
}
//转换为String数组
ByteArrayOutputStream line = new ByteArrayOutputStream();
//StringBuffer sb = new StringBuffer();
srcCode = new String[lineCount];
lineCount = 0;
for (int i = 0; i < srcBytes.length; i++) {
if (srcBytes[i] == 0x0a || i + 1 == srcBytes.length) { //行结束,或者文件结束
try {
String s = new String(line.toByteArray()); //j2me使用
//String s = new String(line.toByteArray(), "GB2312"); //j2se使用
s = s.trim();
srcCode[lineCount++] = s;
}
catch (Exception ex1) {
}
line.reset();
}
else {
line.write(srcBytes[i]);
}
}
//预处理
for (int i = 0; i < srcCode.length; i++) {
//校验是否有空串
if (srcCode[i] == null) {
srcCode[i] = "";
}
//去掉注释
if (srcCode[i].indexOf('\'') >= 0) {
int dqCount = 0; //双引号计数
for (int m = 0; m < srcCode[i].length(); m++) {
char ch = srcCode[i].charAt(m);
if (ch == '\"') {
dqCount++;
}
if (ch == '\'' && (dqCount % 2) == 0) { //如果 ' 不在双引号内,则说明是注释
srcCode[i] = srcCode[i].substring(0, m);
break;
}
}
srcCode[i] = srcCode[i].trim();
}
//找过程起始行号
String ins = srcCode[i];
if (ins.startsWith(STRS_RESERVED[KEYWORD_SUB] + " ")) {
String subName = getFirstWord(ins.substring(ins.indexOf(STRS_RESERVED[KEYWORD_SUB]) + STRS_RESERVED[KEYWORD_SUB].length()));
subAddr.put(subName, new Int(i)); //放入过程表中
}
}
}
/**
* 启动执行
*
* @return Object
*/
public Object start() {
return start(null);
}
/**
*
* @param env Hashtable
* @return Object
*/
public Object start(Hashtable env) {
//变量范围控制
isTopCall = true; //是否是顶级调用
golbleVar = new Hashtable();
//开始执行代码
try {
if (srcCode == null) {
errout(0, STRS_ERR[ERR_NO_SRC]);
}
else {
//如果环境变量存在
if (env != null) {
for (Enumeration e = env.keys(); e.hasMoreElements(); ) {
Object key = e.nextElement();
Object val = env.get(key);
key = ( (String) key).toLowerCase();
golbleVar.put(key, val);
}
}
//执行脚本
return callSub(null, null);
}
}
catch (Exception ex) {
}
return null;
}
/**
* 过程解析,脚本执行体
*
* @param paraStack Hashtable
* @param instrucPointer int
* @return Object
*/
private Object _sub(Vector paraStack, int instrucPointer) {
int ip = instrucPointer; //运行行号
//构建变量表
Hashtable localVar; //本方法的变量表,键是变量名,值是变量值
//把当前方法的变量表压入stack
if (isTopCall) {
localVar = golbleVar; //顶级方法的局部变量为全局变量
isTopCall = false;
}
else {
localVar = new Hashtable(); //非顶级调用,则是局部方法
}
//把参数放进列表
try {
String inst = srcCode[ip];
if (getFirstWord(inst).equals(STRS_RESERVED[KEYWORD_SUB])) { //是子过程
String paraName = inst.substring(inst.indexOf('(') + 1, inst.lastIndexOf(')'));
Vector sName = parseInstruct(paraName); //先弹左边参数
while (sName.size() > 0) {
String pName = (String) vPopFront(sName);
if (pName.charAt(0) != ',') {
localVar.put(pName, vPopBack(paraStack));
}
}
ip++; //跳到下一行
}
else { //是主过程,和子过程的区别是,没有sub开头的语句
}
}
catch (Exception ex1) {
errout(ip, STRS_ERR[ERR_PAESEPARA]);
}
while (ip < srcCode.length) {
try {
String instruct = srcCode[ip];
//print(ip + " " + instruct);
if (instruct.length() != 0) { //非空行
int keywordCode = getKeywordCode(getFirstWord(instruct));
if (keywordCode >= 0) { //是关键字语句
switch (keywordCode) {
case KEYWORD_WHILE:
Bool wb = (Bool) calcExpr(instruct.substring(STRS_RESERVED[KEYWORD_WHILE].length()), localVar);
if (wb.getVal() == false) { //如果为假,则查else或endif
int countWhile = 1;
for (int i = ip + 1; i < srcCode.length; i++) {
String tmpHead = getFirstWord(srcCode[i]);
if (tmpHead.equals(STRS_RESERVED[KEYWORD_WHILE])) {
countWhile++;
}
else
if (tmpHead.equals(STRS_RESERVED[KEYWORD_LOOP])) {
countWhile--;
}
//跳转
if (tmpHead.equals(STRS_RESERVED[KEYWORD_LOOP]) && countWhile == 0) {
ip = i;
break;
}
}
}
break;
case KEYWORD_LOOP:
int countWhile = 1;
for (int i = ip - 1; i > 0; --i) {
String tmpHead = getFirstWord(srcCode[i]);
if (tmpHead.equals(STRS_RESERVED[KEYWORD_WHILE])) {
countWhile--;
}
else
if (tmpHead.equals(STRS_RESERVED[KEYWORD_LOOP])) {
countWhile++;
}
//跳转
if (tmpHead.equals(STRS_RESERVED[KEYWORD_WHILE]) && countWhile == 0) {
ip = i - 1;
break;
}
}
break;
case KEYWORD_IF: //if分支
Bool ib = (Bool) calcExpr(instruct.substring(STRS_RESERVED[KEYWORD_IF].length()), localVar);
if (ib.getVal() == false) { //如果为假,则查else或endif
int countIf = 1;
for (int i = ip + 1; i < srcCode.length; i++) {
String tmpHead = getFirstWord(srcCode[i]);
if (tmpHead.equals(STRS_RESERVED[KEYWORD_IF])) {
countIf++;
}
else
if (tmpHead.equals(STRS_RESERVED[KEYWORD_ENDIF])) {
countIf--;
}
//跳转
if (tmpHead.equals(STRS_RESERVED[KEYWORD_ELSE]) && countIf == 1) {
ip = i;
break;
}
else
if (tmpHead.equals(STRS_RESERVED[KEYWORD_ENDIF]) && countIf == 0) {
ip = i;
break;
}
}
}
break;
case KEYWORD_ELSE:
int countIf = 1;
for (int i = ip + 1; i < srcCode.length; i++) {
String tmpHead = getFirstWord(srcCode[i]);
if (tmpHead.equals(STRS_RESERVED[KEYWORD_IF])) {
countIf++;
}
else
if (tmpHead.equals(STRS_RESERVED[KEYWORD_ENDIF])) {
countIf--;
}
//跳转
if (tmpHead.equals(STRS_RESERVED[KEYWORD_ENDIF]) && countIf == 0) {
ip = i;
break;
}
}
break;
case KEYWORD_SUB:
return null;
case KEYWORD_RET: //过程结束
if (instruct.length() > STRS_RESERVED[KEYWORD_RET].length()) {
return calcExpr(instruct.substring(instruct.indexOf(" ")), localVar);
}
else {
return null;
}
}
}
else
if (isArr(instruct)) { //数组
_setArr(instruct, localVar);
}
else
if (isSubCall(instruct)) { //过程
callSub(instruct, localVar);
}
else
if (isVar(instruct)) { //是赋值语句
_setVar(instruct, localVar);
}
else {
errout(ip, STRS_ERR[ERR_ILLEGAL]);
}
}
}
catch (Exception ex) {
errout(ip, STRS_ERR[ERR_ILLEGAL] + ex.getMessage());
ex.printStackTrace();
break;
}
//指针自动加一
ip++;
} //end while
return null;
}
/**
* 注册扩充方法库
* @param lib Lib
*/
public void register(Lib lib) {
extSubList.addElement(lib);
}
//;----------------------------------------------------------------------------
//; 工具方法
//;----------------------------------------------------------------------------
/**
* 得到第一个单词
* @param instruct String
* @return String
*/
private String getFirstWord(String instruct) {
instruct = instruct.trim();
StringBuffer tsb = new StringBuffer();
for (int i = 0; i < instruct.length(); i++) {
if (isSymbol(instruct.charAt(i))) {
break;
}
tsb.append(instruct.charAt(i));
}
return tsb.toString().trim().toLowerCase();
}
/**
* 是否是关键字
* @param s String
* @return boolean
*/
private int getKeywordCode(String s) {
if (s == null || s.length() == 0) {
return -1;
}
for (int i = 0; i < STRS_RESERVED.length; i++) {
if (s.equals(STRS_RESERVED[i])) {
return i;
}
}
return -1;
}
/**
* 是否是过程调用
* @param s String
* @return boolean
*/
private boolean isSubCall(String s) {
if (getInstructType(s) == '(') {
return true;
}
return false;
}
/**
* 是变量
* @param s String
* @return boolean
*/
private boolean isVar(String s) {
if (getInstructType(s) == '=') {
return true;
}
return false;
}
/**
* 是数组
* @param s String
* @return boolean
*/
private boolean isArr(String s) {
if (getInstructType(s) == '[') {
return true;
}
return false;
}
/**
* 得到第一个符号,由此可判别出是一条什么语句
* @param instruct String
* @return String
*/
private char getInstructType(String instruct) {
for (int i = 0; i < instruct.length(); i++) {
if ("(=[".indexOf(instruct.charAt(i)) >= 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -