package me.hammerle.scriptsystem; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import java.util.HashSet; import me.hammerle.exceptions.CodeTooLongException; import me.hammerle.exceptions.GoHigherAtRootTreeException; import me.hammerle.exceptions.GotoLabelNotFoundException; import me.hammerle.exceptions.NoChildTreeException; public class ScriptData { private final int id; private final Tree code; private String currentCode; private int position; private final HashMap variables; private final HashMap gotos; private final HashSet events; private final String scriptName; private boolean isWaiting; //private boolean isValid; private int overflowProtection; public ScriptData(int id, String filename) { this.id = id; code = new Tree<>(); position = 0; variables = new HashMap<>(); gotos = new HashMap<>(); events = new HashSet<>(); scriptName = filename; readCode(filename); isWaiting = false; //isValid = true; overflowProtection = 0; } public void goDeeper() throws NoChildTreeException { code.goDeeper(); } private void readCode(String filename) { File script = new File(filename + ".txt"); List lines; if(script.exists()) { try { lines = Files.readAllLines(script.toPath()); } catch (IOException ex) { ScriptUtils.printError("Datei '" + filename + "' kann nicht gelesen werden."); return; } } else { ScriptUtils.printError("Datei '" + filename + "' wurde nicht gefunden."); return; } int line = 0; int i = 0; int old = 0; int bracket = 0; boolean bracketEnd = false; int bracketEndPos = 0; boolean oneLineChild = false; boolean comment = false; int commentPos = 0; StringBuilder codeLine = new StringBuilder(); while(line < lines.size()) { if(old == codeLine.length() && !comment) { codeLine = new StringBuilder(lines.get(line).trim()); i = 0; old = 0; } else { codeLine.append(lines.get(line).trim()); } //System.out.println(codeLine); while(i < codeLine.length()) { switch(codeLine.charAt(i)) { case '@': if(comment) { break; } old = i; while(i < codeLine.length() && codeLine.charAt(i) != ' ') { i++; } try { code.selectLastChild(); // Nur für richtige Position } catch(NoChildTreeException ex) { } gotos.put(codeLine.substring(old + 1, i), code.getCurrentPosition()); codeLine.delete(old, i + 1); i = old - 1; break; case '/': if(!comment && i + 1 < codeLine.length() && codeLine.charAt(i + 1) == '*') { comment = true; commentPos = i; } if(!comment && i + 1 < codeLine.length() && codeLine.charAt(i + 1) == '/') { codeLine.delete(commentPos, codeLine.length()); } break; case '*': if(comment && i + 1 < codeLine.length() && codeLine.charAt(i + 1) == '/') { comment = false; codeLine.delete(commentPos, i + 2); i = commentPos; } break; case ';': if(comment) { break; } bracketEnd = false; code.addChild(codeLine.substring(old, i)); old = i + 1; if(oneLineChild) { oneLineChild = false; try { code.goHigher(); } catch(GoHigherAtRootTreeException ex) { System.out.println("Das sollte nicht passieren"); return; } } break; case '(': if(!comment && !oneLineChild) { bracket++; if(bracketEnd) { bracketEnd = false; oneLineChild = true; code.addChild(codeLine.substring(old, bracketEndPos)); old = bracketEndPos; try { code.selectLastChild(); code.goDeeper(); } catch(NoChildTreeException ex) { System.out.println("Das sollte nicht passieren"); } } } break; case ')': if(comment || oneLineChild) { break; } bracket--; if(bracket < 0) { ScriptUtils.printError(") ohne ( in Zeile " + (line + 1)); return; } if(bracket == 0) { bracketEnd = true; bracketEndPos = i + 1; } break; case '{': if(comment) { break; } bracketEnd = false; code.addChild(codeLine.substring(old, i)); old = i + 1; try { code.selectLastChild(); code.goDeeper(); } catch(NoChildTreeException ex) { System.out.println("Das sollte nicht passieren"); } break; case '}': if(comment) { break; } old = i + 1; try { code.goHigher(); } catch(GoHigherAtRootTreeException ex) { ScriptUtils.printError("} ohne { in Zeile " + (line + 1)); return; } break; } i++; } line++; } code.goToRoot(); } public void runCode() { try { while(!isWaiting) { try { code.selectNextChild(); } catch(NoChildTreeException ex) { //System.out.println("NACH OBEN!"); code.goHigher(); continue; } currentCode = code.getCurrentChildData(); findFunction(0, currentCode.length() - 1); } } catch(NoChildTreeException | GoHigherAtRootTreeException ex) { System.out.println("END PROGRAM"); } } private Object findFunction(int from, int to) { if(to <= from) // Springt in { } ohne Kopf { try { code.goDeeper(); } catch(NoChildTreeException ex) { System.out.println("SOLLTE NICHT SEIN"); } return null; } int old = from; int bracket; ArrayList list = new ArrayList<>(); while(currentCode.charAt(from) != '(') { from++; } bracket = from; from++; int last = from; int counter = 0; boolean string = false; while(from <= to) { if(string) { if(currentCode.charAt(from) == '"') { string = !string; } from++; continue; } switch(currentCode.charAt(from)) { case '"': string = !string; break; case ',': if(last != from) { list.add(currentCode.substring(last, from).trim()); } last = from + 1; break; case ')': if(counter > 0) { last = from + 1; counter--; break; } position = from; if(last != from) { list.add(currentCode.substring(last, from).trim()); } return doFunction(currentCode.substring(old, bracket).trim(), list); case '(': list.add(findFunction(last, to)); from = position - 1; last = from; counter++; break; } from++; } return null; } private Object doFunction(String function, List args) { for(int i = 0; i < args.size(); i++) { args.set(i, readParameter(args.get(i))); } Object o = CodeParser.parseFunction(this, function, args); if(o == null) { isWaiting = true; } return o; } private Object readParameter(Object o) { if(!(o instanceof String)) { return o; } String s = o.toString(); if(s.startsWith("\"") && s.endsWith("\"")) { return s.substring(1, s.length() - 1); } else if(s.startsWith("$")) { return getVar(s); } try { return ScriptUtils.getNumber(s); } catch(NumberFormatException ex) { return s; } } public int getId() { return id; } public String getName() { return scriptName; } /*public boolean isWaiting() { return isWaiting; } public void setWaiting(Boolean bool) { isWaiting = bool; } public boolean isValid() { return isValid; } public void setValid(Boolean bool) { isValid = bool; }*/ public Object getVar(String var) { if(var.startsWith("$")) { return variables.get(var); } return variables.get("$" + var); } public Object getVar(Object var) { return getVar(var.toString()); } public HashMap getVars() { return variables; } public void removeVar(String var) { if(var.startsWith("$")) { variables.remove(var); } variables.remove("$" + var); } public void removeVar(Object var) { removeVar(var.toString()); } public void setVar(String var, Object value) { if(!var.startsWith("$")) { var = "$" + var; } variables.put(var, value); } public void setVar(Object var, Object value) { setVar(var.toString(), value); } public void gotoLabel(String label) throws NoChildTreeException, CodeTooLongException { Integer[] i = gotos.get(label); if(i == null) { throw new GotoLabelNotFoundException(label); } overflowProtection++; if(overflowProtection > 50) { overflowProtection = 0; throw new CodeTooLongException(); } code.goToPosition(i); } public void resetOverflowProtection() { overflowProtection = 0; } public void loadEvent(Object event) { events.add(event.toString()); } public void unloadEvent(Object event) { events.remove(event.toString()); } public boolean isEventLoaded(Object event) { return events.contains(event.toString()); } }