|
@@ -37,6 +37,7 @@ public class Code
|
|
|
|
|
|
public void executeFunction(SnuviParser parser, Script sc, Stack<Object> stack)
|
|
|
{
|
|
|
+ //System.out.println("EXE: " + this.toString());
|
|
|
if(function == null)
|
|
|
{
|
|
|
if(value != null)
|
|
@@ -316,261 +317,269 @@ public class Code
|
|
|
|
|
|
public static Code[] generate(SnuviParser parser, String scriptName, String code, HashMap<String, Integer> gotos)
|
|
|
{
|
|
|
- System.out.print("Starting '" + scriptName + "' ... ");
|
|
|
- long startTime = System.currentTimeMillis();
|
|
|
-
|
|
|
- Code.scriptName = scriptName;
|
|
|
-
|
|
|
- StringBuilder sb = new StringBuilder(code);
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // comments
|
|
|
- // ---------------------------------------------------------------------
|
|
|
-
|
|
|
- removeComments(sb);
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // replacing Strings with #... to get rid of "
|
|
|
- // ---------------------------------------------------------------------
|
|
|
-
|
|
|
- HashMap<String, String> strings = replaceStrings(sb);
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // allowing labels without ;
|
|
|
- // ---------------------------------------------------------------------
|
|
|
-
|
|
|
- formatLabels(sb);
|
|
|
-
|
|
|
- code = sb.toString();
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // split code into lines
|
|
|
- // ---------------------------------------------------------------------
|
|
|
-
|
|
|
- ArrayList<String> lines = new ArrayList<>();
|
|
|
int lineCounter = 1;
|
|
|
- ArrayList<Integer> realCodeLine = new ArrayList<>();
|
|
|
- int old = 0;
|
|
|
- int pos = 0;
|
|
|
- int length = code.length();
|
|
|
- int counter = 0;
|
|
|
- int bracketCounter = 0;
|
|
|
- boolean closed = true;
|
|
|
- Stack<Integer> brackets = new Stack<>();
|
|
|
- while(pos < length)
|
|
|
- {
|
|
|
- switch(code.charAt(pos))
|
|
|
- {
|
|
|
- case '(':
|
|
|
- closed = false;
|
|
|
- bracketCounter++;
|
|
|
- break;
|
|
|
- case ')':
|
|
|
- bracketCounter--;
|
|
|
- break;
|
|
|
- case ';':
|
|
|
- if(bracketCounter != 0)
|
|
|
- {
|
|
|
- throw new PreScriptException(scriptName, lineCounter, "unbalanced ()");
|
|
|
- }
|
|
|
- lines.add(removeNonSyntax(code.substring(old, pos)));
|
|
|
- realCodeLine.add(lineCounter);
|
|
|
- old = pos + 1;
|
|
|
- closed = true;
|
|
|
- break;
|
|
|
- case '{':
|
|
|
- if(bracketCounter != 0)
|
|
|
- {
|
|
|
- throw new PreScriptException(scriptName, lineCounter, "unbalanced ()");
|
|
|
- }
|
|
|
- brackets.push(lineCounter);
|
|
|
- counter++;
|
|
|
- lines.add(removeNonSyntax(code.substring(old, pos)));
|
|
|
- realCodeLine.add(lineCounter);
|
|
|
- old = pos + 1;
|
|
|
- lines.add("{");
|
|
|
- realCodeLine.add(lineCounter);
|
|
|
- break;
|
|
|
- case '}':
|
|
|
- if(!closed)
|
|
|
- {
|
|
|
- throw new PreScriptException(scriptName, lineCounter, "missing ;");
|
|
|
- }
|
|
|
- else if(bracketCounter != 0)
|
|
|
- {
|
|
|
- throw new PreScriptException(scriptName, lineCounter, "unbalanced ()");
|
|
|
- }
|
|
|
- counter--;
|
|
|
- if(counter < 0)
|
|
|
- {
|
|
|
- throw new PreScriptException(scriptName, lineCounter, "unexpected }");
|
|
|
- }
|
|
|
- old = pos + 1;
|
|
|
- lines.add("}");
|
|
|
- realCodeLine.add(lineCounter);
|
|
|
- brackets.pop();
|
|
|
- break;
|
|
|
- case '\n':
|
|
|
- lineCounter++;
|
|
|
- break;
|
|
|
- }
|
|
|
- pos++;
|
|
|
- }
|
|
|
- // well the second check should be useless
|
|
|
- if(counter != 0 && !brackets.isEmpty())
|
|
|
+ try
|
|
|
{
|
|
|
- throw new PreScriptException(scriptName, brackets.pop(), "unbalanced {}");
|
|
|
- }
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // generating byte code
|
|
|
- // ---------------------------------------------------------------------
|
|
|
+ //System.out.print("Starting '" + scriptName + "' ... ");
|
|
|
+ //long startTime = System.currentTimeMillis();
|
|
|
|
|
|
- LineCompiler compiler = new LineCompiler(parser, scriptName);
|
|
|
- ArrayList<Code> co = new ArrayList<>();
|
|
|
- int line;
|
|
|
- byte layer = 0;
|
|
|
- String s;
|
|
|
- for(int i = 0; i < lines.size(); i++)
|
|
|
- {
|
|
|
- s = lines.get(i);
|
|
|
- //System.out.println(s);
|
|
|
- if(s.isEmpty() || s.equals("{"))
|
|
|
- {
|
|
|
- continue;
|
|
|
+ Code.scriptName = scriptName;
|
|
|
+
|
|
|
+ StringBuilder sb = new StringBuilder(code);
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // comments
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+
|
|
|
+ removeComments(sb);
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // replacing Strings with #... to get rid of "
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+
|
|
|
+ HashMap<String, String> strings = replaceStrings(sb);
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // allowing labels without ;
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+
|
|
|
+ formatLabels(sb);
|
|
|
+
|
|
|
+ code = sb.toString();
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // split code into lines
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+
|
|
|
+ ArrayList<String> lines = new ArrayList<>();
|
|
|
+ lineCounter = 1;
|
|
|
+ ArrayList<Integer> realCodeLine = new ArrayList<>();
|
|
|
+ int old = 0;
|
|
|
+ int pos = 0;
|
|
|
+ int length = code.length();
|
|
|
+ int counter = 0;
|
|
|
+ int bracketCounter = 0;
|
|
|
+ boolean closed = true;
|
|
|
+ Stack<Integer> brackets = new Stack<>();
|
|
|
+ while(pos < length)
|
|
|
+ {
|
|
|
+ switch(code.charAt(pos))
|
|
|
+ {
|
|
|
+ case '(':
|
|
|
+ closed = false;
|
|
|
+ bracketCounter++;
|
|
|
+ break;
|
|
|
+ case ')':
|
|
|
+ bracketCounter--;
|
|
|
+ break;
|
|
|
+ case ';':
|
|
|
+ if(bracketCounter != 0)
|
|
|
+ {
|
|
|
+ throw new PreScriptException(scriptName, lineCounter, "unbalanced ()");
|
|
|
+ }
|
|
|
+ lines.add(removeNonSyntax(code.substring(old, pos)));
|
|
|
+ realCodeLine.add(lineCounter);
|
|
|
+ old = pos + 1;
|
|
|
+ closed = true;
|
|
|
+ break;
|
|
|
+ case '{':
|
|
|
+ if(bracketCounter != 0)
|
|
|
+ {
|
|
|
+ throw new PreScriptException(scriptName, lineCounter, "unbalanced ()");
|
|
|
+ }
|
|
|
+ brackets.push(lineCounter);
|
|
|
+ counter++;
|
|
|
+ lines.add(removeNonSyntax(code.substring(old, pos)));
|
|
|
+ realCodeLine.add(lineCounter);
|
|
|
+ old = pos + 1;
|
|
|
+ lines.add("{");
|
|
|
+ realCodeLine.add(lineCounter);
|
|
|
+ break;
|
|
|
+ case '}':
|
|
|
+ if(!closed)
|
|
|
+ {
|
|
|
+ throw new PreScriptException(scriptName, lineCounter, "missing ;");
|
|
|
+ }
|
|
|
+ else if(bracketCounter != 0)
|
|
|
+ {
|
|
|
+ throw new PreScriptException(scriptName, lineCounter, "unbalanced ()");
|
|
|
+ }
|
|
|
+ counter--;
|
|
|
+ if(counter < 0)
|
|
|
+ {
|
|
|
+ throw new PreScriptException(scriptName, lineCounter, "unexpected }");
|
|
|
+ }
|
|
|
+ old = pos + 1;
|
|
|
+ lines.add("}");
|
|
|
+ realCodeLine.add(lineCounter);
|
|
|
+ brackets.pop();
|
|
|
+ break;
|
|
|
+ case '\n':
|
|
|
+ lineCounter++;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ pos++;
|
|
|
}
|
|
|
- else if(s.equals("break") || s.equals("continue"))
|
|
|
+ // well the second check should be useless
|
|
|
+ if(counter != 0 && !brackets.isEmpty())
|
|
|
{
|
|
|
- co.add(new Code(s, 0, realCodeLine.get(i), layer));
|
|
|
- continue;
|
|
|
+ throw new PreScriptException(scriptName, brackets.pop(), "unbalanced {}");
|
|
|
}
|
|
|
- else if(lines.get(Math.min(i + 1, lines.size() - 1)).equals("{"))
|
|
|
- {
|
|
|
- layer++;
|
|
|
- if(s.equals("try") || s.equals("catch") || s.equals("else"))
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // generating byte code
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+
|
|
|
+ LineCompiler compiler = new LineCompiler(parser, scriptName);
|
|
|
+ ArrayList<Code> co = new ArrayList<>();
|
|
|
+ int line;
|
|
|
+ byte layer = 0;
|
|
|
+ String s;
|
|
|
+ for(int i = 0; i < lines.size(); i++)
|
|
|
+ {
|
|
|
+ s = lines.get(i);
|
|
|
+ //System.out.println(s);
|
|
|
+ if(s.isEmpty() || s.equals("{"))
|
|
|
{
|
|
|
- co.add(new Code(s, 0, realCodeLine.get(i), layer));
|
|
|
continue;
|
|
|
}
|
|
|
- }
|
|
|
- else if(s.equals("}"))
|
|
|
- {
|
|
|
- layer--;
|
|
|
- co.add(new Code("gotoline", 0, realCodeLine.get(i), layer));
|
|
|
- continue;
|
|
|
- }
|
|
|
- else if(s.charAt(0) == '@')
|
|
|
- {
|
|
|
- gotos.put(s.substring(1), co.size());
|
|
|
- continue;
|
|
|
- }
|
|
|
- line = realCodeLine.get(i);
|
|
|
- compiler.reset(line, layer, s);
|
|
|
- compiler.compile(co, strings);
|
|
|
- co.get(co.size() - 1).stackPush = false;
|
|
|
- }
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // generating gotos of key words
|
|
|
- // ---------------------------------------------------------------------
|
|
|
-
|
|
|
- Code[] c = co.toArray(new Code[co.size()]);
|
|
|
- //java.util.Arrays.stream(c).forEach(cod -> System.out.println(cod.toString()));
|
|
|
-
|
|
|
- //System.exit(0);
|
|
|
- int oldLayer = 0;
|
|
|
- int newLayer;
|
|
|
- for(int i = 0; i < c.length; i++)
|
|
|
- {
|
|
|
- newLayer = c[i].layer;
|
|
|
- if(oldLayer < newLayer)
|
|
|
- {
|
|
|
- int j = findKeyWord(i, c);
|
|
|
- if(j == 0)
|
|
|
+ else if(s.equals("break") || s.equals("continue") || s.equals("return"))
|
|
|
{
|
|
|
- //java.util.Arrays.stream(c).forEach(cod -> System.out.println(cod.toString()));
|
|
|
- throw new PreScriptException(scriptName, c[i].realLine, "well, fuck this, this should never happen");
|
|
|
+ co.add(new Code(s, 0, realCodeLine.get(i), layer));
|
|
|
+ continue;
|
|
|
}
|
|
|
- boolean jumpBack = j < 0;
|
|
|
- j = Math.abs(j);
|
|
|
- int k;
|
|
|
- for(k = j; k < c.length; k++)
|
|
|
+ else if(lines.get(Math.min(i + 1, lines.size() - 1)).equals("{"))
|
|
|
{
|
|
|
- if(c[k].layer < newLayer)
|
|
|
+ layer++;
|
|
|
+ if(s.equals("try") || s.equals("catch") || s.equals("else"))
|
|
|
{
|
|
|
- break;
|
|
|
+ co.add(new Code(s, 0, realCodeLine.get(i), layer));
|
|
|
+ continue;
|
|
|
}
|
|
|
}
|
|
|
- c[j].value = k - j;
|
|
|
- if(jumpBack)
|
|
|
+ else if(s.equals("}"))
|
|
|
{
|
|
|
- c[k].value = i - k - 1;
|
|
|
+ layer--;
|
|
|
+ co.add(new Code("gotoline", 0, realCodeLine.get(i), layer));
|
|
|
+ continue;
|
|
|
}
|
|
|
- else
|
|
|
+ else if(s.charAt(0) == '@')
|
|
|
{
|
|
|
- c[k].value = 0;
|
|
|
+ gotos.put(s.substring(1), co.size());
|
|
|
+ continue;
|
|
|
}
|
|
|
+ line = realCodeLine.get(i);
|
|
|
+ compiler.reset(line, layer, s);
|
|
|
+ compiler.compile(co, strings);
|
|
|
+ co.get(co.size() - 1).stackPush = false;
|
|
|
}
|
|
|
- oldLayer = newLayer;
|
|
|
- }
|
|
|
-
|
|
|
- // ---------------------------------------------------------------------
|
|
|
- // generating break and continue
|
|
|
- // ---------------------------------------------------------------------
|
|
|
|
|
|
- String f;
|
|
|
- Code data;
|
|
|
- for(int i = 0; i < c.length; i++)
|
|
|
- {
|
|
|
- f = c[i].function;
|
|
|
- if(f != null)
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // generating gotos of key words
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+
|
|
|
+ Code[] c = co.toArray(new Code[co.size()]);
|
|
|
+ //java.util.Arrays.stream(c).forEach(cod -> System.out.println(cod.toString()));
|
|
|
+
|
|
|
+ //System.exit(0);
|
|
|
+ int oldLayer = 0;
|
|
|
+ int newLayer;
|
|
|
+ for(int i = 0; i < c.length; i++)
|
|
|
{
|
|
|
- if(f.equals("break"))
|
|
|
+ newLayer = c[i].layer;
|
|
|
+ if(oldLayer < newLayer)
|
|
|
{
|
|
|
- for(int j = i; j < c.length; j++)
|
|
|
+ int j = findKeyWord(i, c);
|
|
|
+ if(j == 0)
|
|
|
+ {
|
|
|
+ //java.util.Arrays.stream(c).forEach(cod -> System.out.println(cod.toString()));
|
|
|
+ throw new PreScriptException(scriptName, c[i].realLine, "well, fuck this, this should never happen");
|
|
|
+ }
|
|
|
+ boolean jumpBack = j < 0;
|
|
|
+ j = Math.abs(j);
|
|
|
+ int k;
|
|
|
+ for(k = j; k < c.length; k++)
|
|
|
{
|
|
|
- data = c[j];
|
|
|
- if("gotoline".equals(data.function) && data.value != null && (int) data.value != 0)
|
|
|
+ if(c[k].layer < newLayer)
|
|
|
{
|
|
|
- c[i].value = j - i;
|
|
|
- j += (int) data.value + 1;
|
|
|
- for(; j < c.length; j++)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ c[j].value = k - j;
|
|
|
+ if(jumpBack)
|
|
|
+ {
|
|
|
+ c[k].value = i - k - 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ c[k].value = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ oldLayer = newLayer;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+ // generating break and continue
|
|
|
+ // ---------------------------------------------------------------------
|
|
|
+
|
|
|
+ String f;
|
|
|
+ Code data;
|
|
|
+ for(int i = 0; i < c.length; i++)
|
|
|
+ {
|
|
|
+ f = c[i].function;
|
|
|
+ if(f != null)
|
|
|
+ {
|
|
|
+ if(f.equals("break"))
|
|
|
+ {
|
|
|
+ for(int j = i; j < c.length; j++)
|
|
|
+ {
|
|
|
+ data = c[j];
|
|
|
+ if("gotoline".equals(data.function) && data.value != null && (int) data.value != 0)
|
|
|
{
|
|
|
- if("while".equals(c[j].function))
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
- else if("for".equals(c[j].function))
|
|
|
+ c[i].value = j - i;
|
|
|
+ j += (int) data.value + 1;
|
|
|
+ for(; j < c.length; j++)
|
|
|
{
|
|
|
- c[i] = new Code("breakreset", 0, c[i].value, c[i].realLine, c[i].layer);
|
|
|
+ if("while".equals(c[j].function))
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ else if("for".equals(c[j].function))
|
|
|
+ {
|
|
|
+ c[i] = new Code("breakreset", 0, c[i].value, c[i].realLine, c[i].layer);
|
|
|
+ }
|
|
|
}
|
|
|
+ break;
|
|
|
}
|
|
|
- break;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- else if(f.equals("continue"))
|
|
|
- {
|
|
|
- for(int j = i; j < c.length; j++)
|
|
|
+ else if(f.equals("continue"))
|
|
|
{
|
|
|
- data = c[j];
|
|
|
- if("gotoline".equals(data.function) && data.value != null && (int) data.value != 0)
|
|
|
+ for(int j = i; j < c.length; j++)
|
|
|
{
|
|
|
- c[i].value = j - i + (int) data.value;
|
|
|
- break;
|
|
|
+ data = c[j];
|
|
|
+ if("gotoline".equals(data.function) && data.value != null && (int) data.value != 0)
|
|
|
+ {
|
|
|
+ c[i].value = j - i + (int) data.value;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- // end
|
|
|
- System.out.println((System.currentTimeMillis() - startTime) + " ms");
|
|
|
- //java.util.Arrays.stream(c).forEach(cod -> System.out.println(cod.toString()));
|
|
|
- //gotos.forEach((k, v) -> System.out.println("Lable " + k + " " + v));
|
|
|
- //System.exit(0);
|
|
|
- return c;
|
|
|
+ // end
|
|
|
+ //System.out.println((System.currentTimeMillis() - startTime) + " ms");
|
|
|
+ //java.util.Arrays.stream(c).forEach(cod -> System.out.println(cod.toString()));
|
|
|
+ //gotos.forEach((k, v) -> System.out.println("Lable " + k + " " + v));
|
|
|
+ //System.exit(0);
|
|
|
+ return c;
|
|
|
+ }
|
|
|
+ catch(IndexOutOfBoundsException ex)
|
|
|
+ {
|
|
|
+ throw new PreScriptException(scriptName, lineCounter, "unbalanced {}");
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private static int findKeyWord(int start, Code[] c)
|