package com.lfk.justweengine.utils.script; import com.lfk.justweengine.utils.tools.ValidatorsUtils; import java.io.IOException; import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * ScriptManager * * @author liufengkai * Created by liufengkai on 16/2/8. */ public class ScriptManager implements KeyCode { private HashMap<String, Function> functionIndex; private Stack<Long> indexStack; private Stack<Boolean> ifStack; private RandomAccessFile file; private long fileLength; private long fileLines = 0; private final Object lock = new Object(); private Exp exp = new Exp(); private static HashMap<String, Object> flagDefaultMap = new HashMap<>(); public ScriptManager() { functionIndex = new HashMap<>(); indexStack = new Stack<>(); ifStack = new Stack<>(); } public void open(String name) { try { file = new RandomAccessFile(name, "rw"); fileLength = file.length(); } catch (IOException e) { e.printStackTrace(); } CodeThread thread = new CodeThread(); thread.start(); thread.setPreTreatment(new OnAfterPreTreatment() { @Override public void AfterPreTreatment() { for (int i = 0; i < 50; i++) { doExecute(); } } }); } /** * 预处理线程: * 接到脚本后进行预处理,把方法的开始和末尾的位置保存 * 并且定位主函数入栈 * * @example : * <p> * 位置入栈: * BEGIN FUNCTION: * ... * END FUNCTION * <p> * 主函数标记: * <p> * MAIN: */ private class CodeThread extends Thread { private long startIndex; private long endIndex; private String functionName; private OnAfterPreTreatment preTreatment; public void setPreTreatment(OnAfterPreTreatment preTreatment) { this.preTreatment = preTreatment; } public CodeThread() { clearData(); fileLines = 0; } private void clearData() { startIndex = 0; endIndex = 0; functionName = null; } @Override public void run() { super.run(); synchronized (lock) { try { // 处理整个脚本 while (file.getFilePointer() < fileLength) { // 读入每一行 String line = new String((file.readLine()). getBytes("iso-8859-1"), "UTF-8").trim(); fileLines++; // 检测开始标记 if (line.startsWith(KeyCode.FLAG_BEGIN_TAG)) { startIndex = file.getFilePointer(); functionName = line.substring(6, line.length() - 1); // 检测结束标记 } else if (line.startsWith(KeyCode.FLAG_END_TAG) && !line.startsWith(KeyCode.FLAG_END_IF_TAG)) { // 方法名字相同 然后保存 if (functionName.equals(line.substring(4, line.length()))) { endIndex = file.getFilePointer(); functionIndex.put(functionName, new Function(startIndex, endIndex)); } else { // 清理数据 clearData(); } // 寻找主函数 } else if (line.startsWith("MAIN")) { indexStack.add(file.getFilePointer()); } } } catch (IOException e) { e.printStackTrace(); } // 指针放到主函数位置 setIndex(indexStack.peek()); if (preTreatment != null) preTreatment.AfterPreTreatment(); } } } public interface OnAfterPreTreatment { void AfterPreTreatment(); } public synchronized void doExecute() { try { if (file.getFilePointer() == fileLength) { return; } String line = new String((file.readLine()). getBytes("iso-8859-1"), "UTF-8").trim(); updateIndex(); // 判断空行 if (line.equals("")) { line = file.readLine(); updateIndex(); } if (!ifStack.empty()) { // false if (!ifStack.peek()) { while (true) { line = file.readLine(); if (hasRax(KeyCode.FLAG_ELSE_TAG, line)) { ifStack.pop(); break; } else if (hasRax(KeyCode.FLAG_ELSE_IF_TAG, line)) { break; } else if (hasRax(KeyCode.FLAG_END_IF_TAG, line)) { ifStack.pop(); return; } } } } if (line.startsWith(KeyCode.FLAG_RUN_TAG)) { runParse(line); } else if (line.startsWith(KeyCode.FLAG_END_TAG) && !line.startsWith(KeyCode.FLAG_END_IF_TAG)) { endParse(); } else if (hasRax("=", line)) { evalParse(line); } else if (hasRax(KeyCode.FLAG_IF_TAG, line)) { ifStack.push(ifParse(line)); } else if (hasRax(KeyCode.FLAG_ELSE_IF_TAG, line)) { if (!ifStack.peek()) { ifStack.pop(); ifStack.push(elseIfParse(line)); } else { ifEndParse(); } } else if (hasRax(KeyCode.FLAG_ELSE_TAG, line)) { doExecute(); } } catch (IOException e) { e.printStackTrace(); } } private void updateIndex() { try { indexStack.pop(); indexStack.push(file.getFilePointer()); } catch (IOException e) { e.printStackTrace(); } } public boolean setIndex(long index) { if (index <= fileLength) { try { file.seek(index); } catch (IOException e) { e.printStackTrace(); return false; } } return false; } private void ifEndParse() { while (true) { String line = null; try { line = file.readLine(); } catch (IOException e) { e.printStackTrace(); } if (hasRax(KeyCode.FLAG_END_IF_TAG, line)) { ifStack.pop(); break; } } } private void runParse(String command) { String name = command.substring(4, command.length()); if (functionIndex.containsKey(name)) { long index = functionIndex.get(name).getStartIndex(); setIndex(index); indexStack.push(index); } } private void endParse() { indexStack.pop(); setIndex(indexStack.peek()); } private boolean elseIfParse(String command) { return coverParse(command.substring(7, command.length() - 1)); } private boolean ifParse(String command) { return coverParse(command.substring(3, command.length() - 1)); } private boolean coverParse(String command) { List list = commandToCondition(command); Object valueA = list.get(1); Object valueB = list.get(2); valueA = !flagDefaultMap.containsKey(valueA.toString()) ? valueA : flagDefaultMap.get(valueA.toString()); valueB = !flagDefaultMap.containsValue(valueB.toString()) ? valueB : flagDefaultMap.get(valueB.toString()); String condition = list.get(0).toString(); if ("==".equals(condition)) { return valueA.toString().equals(valueB.toString()); // 非等 } else if ("!=".equals(condition)) { return !valueA.toString().equals(valueB.toString()); // 大于 } else if (">".equals(condition)) { float numberA = Float.parseFloat(valueA.toString()); float numberB = Float.parseFloat(valueB.toString()); return numberA > numberB; // 小于 } else if ("<".equals(condition)) { float numberA = Float.parseFloat(valueA.toString()); float numberB = Float.parseFloat(valueB.toString()); return numberA < numberB; // 大于等于 } else if (">=".equals(condition)) { float numberA = Float.parseFloat(valueA.toString()); float numberB = Float.parseFloat(valueB.toString()); return numberA >= numberB; // 小于等于 } else if ("<=".equals(condition)) { float numberA = Float.parseFloat(valueA.toString()); float numberB = Float.parseFloat(valueB.toString()); return numberA <= numberB; } return false; } private void evalParse(String command) { String com = command.replace(" ", ""); int index = com.indexOf("="); String left = com.substring(0, index); String right = com.substring(index + 1); float rightNum; // 不是字符串 // 是表达式 if (exp.exp(right)) { // 替换 for (Object o : flagDefaultMap.entrySet()) { Map.Entry entry = (Map.Entry) o; right = rax(entry.getKey().toString(), right); } // 计算 rightNum = exp.parse(right); flagDefaultMap.put(left, rightNum); } else if (ValidatorsUtils.isNumeric(right)) { rightNum = exp.parse(right); flagDefaultMap.put(left, rightNum); } } private String rax(String rax, String command) { String X = "([^a-zA-Z0-9]|^)" + rax + "([^a-zA-Z0-9]|$)"; Pattern pattern = Pattern.compile(X); Matcher matcher = pattern.matcher(command); // printIt(command + "\n"); while (matcher.find()) { System.out.println("start:" + matcher.start()); System.out.println("end:" + matcher.end()); command = command.substring(0, matcher.start() + 1) + flagDefaultMap.get(rax).toString() + command.substring(matcher.end() - 1); } return command; } public List commandToCondition(String command) { List<String> list = new ArrayList<>(); int index; if (command.contains(KeyCode.FLAG_EQUAL_TAG)) { list.add(KeyCode.FLAG_EQUAL_TAG); } else if (command.contains(KeyCode.FLAG_UN_EQUAL_TAG)) { list.add(KeyCode.FLAG_UN_EQUAL_TAG); } else if (command.contains(KeyCode.FLAG_SMALLER_TAG) && !command.contains(KeyCode.FLAG_SMALLER_EQUAL_TAG)) { list.add(KeyCode.FLAG_SMALLER_TAG); } else if (command.contains(KeyCode.FLAG_BIGGER_TAG) && !command.contains(KeyCode.FLAG_BIGGER_EQUAL_TAG)) { list.add(KeyCode.FLAG_BIGGER_TAG); } else if (command.contains(KeyCode.FLAG_SMALLER_EQUAL_TAG)) { list.add(KeyCode.FLAG_SMALLER_EQUAL_TAG); } else if (command.contains(KeyCode.FLAG_BIGGER_EQUAL_TAG)) { list.add(KeyCode.FLAG_BIGGER_EQUAL_TAG); } index = command.indexOf(list.get(0)); list.add(command.substring(0, index).trim()); list.add(command.substring(index + list.get(0).length())); return list; } private boolean hasRax(String rax, String command) { String X = "([^a-zA-Z0-9]|^)" + rax + "([^a-zA-Z0-9]|$)"; Pattern pattern = Pattern.compile(X); Matcher matcher = pattern.matcher(command); return matcher.find(); } public void printIt() { // printIt(functionIndex.size() + ""); for (Object o : functionIndex.entrySet()) { Map.Entry entry = (Map.Entry) o; Object key = entry.getKey(); Function val = (Function) entry.getValue(); System.out.print("key:" + key + "val:" + val.getStartIndex() + "\n" ); } // printIt(flagDefaultMap.size() + ""); for (Object o : flagDefaultMap.entrySet()) { Map.Entry entry = (Map.Entry) o; Object key = entry.getKey(); System.out.print("key:" + key + "val:" + entry.getValue().toString() + "\n" ); } } private static void printIt(String name) { System.out.print(name + "\n"); } }