Browse Source

rewrote line compiler again, now with intelligent syntax priority

Kajetan Johannes Hammerle 7 years ago
parent
commit
a2f033dbe1

+ 7 - 1
nbproject/private/private.xml

@@ -2,6 +2,12 @@
 <project-private xmlns="http://www.netbeans.org/ns/project-private/1">
     <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
     <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
-        <group/>
+        <group>
+            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/LineCompiler.java</file>
+            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/Code.java</file>
+            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/Syntax.java</file>
+            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/SnuviParser.java</file>
+            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/snuviscript/SnuviScript.java</file>
+        </group>
     </open-files>
 </project-private>

+ 1 - 1
src/me/hammerle/code/Code.java

@@ -9,7 +9,7 @@ import me.hammerle.math.Fraction;
 public class Code
 {
     protected final int realLine;
-    protected final String function;
+    protected String function;
     protected final int pars;
     protected final byte layer;
     protected Object value;

+ 213 - 359
src/me/hammerle/code/LineCompiler.java

@@ -4,433 +4,287 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Stack;
 import me.hammerle.exceptions.PreScriptException;
-import me.hammerle.math.Fraction;
 
 public class LineCompiler 
 {
     private int realLine;
-    // counts brackets to know if we are in a function
-    private int bracketCounter;
-    // last special character to stop push
-    private final Stack<Integer> lastSpecial;
     // comma counter, for functions
     private final Stack<Integer> commaCounter;
-    // store for adding function on next successfull push
-    private final HashMap<Integer, String> nextFunction;
-    // stores if a function was just called
-    private boolean function;
     
     private String line;
     private byte layer;
     
-    private SnuviParser parser;
     private String scriptName;
     
     public LineCompiler(SnuviParser parser, String scriptName)
     {
         realLine = 0;
-        bracketCounter = 0;
-        lastSpecial = new Stack<>();
         commaCounter = new Stack<>();
-        nextFunction = new HashMap<>();
-        function = false;
         line = "";
         layer = 0;
-        this.parser = parser;
         this.scriptName = scriptName;
     }
 
     public void reset(int realLine, byte layer, String line) 
     {
         this.realLine = realLine;
-        bracketCounter = 0;
-        lastSpecial.clear();
-        lastSpecial.push(line.length());
         commaCounter.clear();
-        nextFunction.clear();
-        function = false;
         this.line = line;
         this.layer = layer;
     }
     
-    private boolean push(HashMap<String, String> strings, ArrayList<Code> co, int index)
-    {
-        if(function)
-        {
-            if(index + 1 != lastSpecial.peek())
-            {
-                co.add(new Code(Code.convertInput(strings, line.substring(index + 1, lastSpecial.pop()), true), realLine, layer));
-            }
-        }
-        else
-        {
-            co.add(new Code(Code.convertInput(strings, line.substring(index + 1, lastSpecial.pop()), true), realLine, layer));
-        }
-        String sNextFunction = nextFunction.remove(bracketCounter);
-        if(sNextFunction != null)
-        {
-            if(sNextFunction.equals("sub") && !co.isEmpty())
-            {
-                Code c = co.get(co.size() - 1);
-                if("".equals(c.value))
-                {
-                    c.value = new Fraction(0);
-                }
-            }
-            co.add(new Code(sNextFunction, 2, realLine, layer));
-            return true;
-        }
-        return false;
-    }
-    
     private boolean isAllowedChar(char c)
     {
-        return Character.isLetterOrDigit(c) || c == '.' || c == '_';
+        return Character.isLetterOrDigit(c) || c == '.' || c == '_' || c == '#';
     }
     
     public void compile(ArrayList<Code> co, HashMap<String, String> strings)
     {
-        try
+        Stack<Stack<Syntax>> syntaxStack = new Stack<>();
+        syntaxStack.push(new Stack<>());
+        
+        char[] chars = line.toCharArray();
+        char c;
+        int old = chars.length;
+        Syntax syntax;
+        String s;
+        for(int i = old - 1; i >= 0; i--)
         {
-            int old;
-            int j = line.length() - 1;    
-            boolean arrayState = true;
-            String arrayFunction = null;
-            int commas;
-            String syntax;
-            while(j >= 0)
+            c = chars[i];
+            if(!isAllowedChar(c))
             {
-                syntax = null;
-                switch(line.charAt(j))
+                syntax = getSyntax(line, i);
+                if(syntax == Syntax.UNKNOWN)
                 {
-                    case '+': 
-                        if(line.charAt(j - 1) == '+')
-                        {
-                            int last = lastSpecial.pop();
-                            if(last - j >= 2)
-                            {
-                                // ++i
-                                if(j + 1 - last == 0)
-                                {                                  
-                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
-                                }
-                                co.add(new Code(line.substring(j + 1, last), realLine, layer));
-                                co.add(new Code("inc", 1, realLine, layer));
-                                j--;
-                            }
-                            else
-                            {
-                                Code c = co.get(co.size() - 1);
-                                if("array.get".equals(c.function))
-                                {
-                                    co.set(co.size() - 1, new Code("array.inc", 2, c.realLine, c.layer));
-                                    j--;
-                                    lastSpecial.push(j);
-                                    function = true;
-                                    break;
-                                }
-                                // i++
-                                j--;
-                                old = j;
-                                j--;
-                                if(line.charAt(j) == ']')
-                                {
-                                    arrayFunction = "postinc";
-                                    lastSpecial.push(j);
-                                    j--;
-                                    continue;
-                                }
-                                while(j >= 0 && isAllowedChar(line.charAt(j)))
-                                {
-                                    j--;
-                                }
-                                j++;
-                                if(j - old == 0)
-                                {
-                                    co.forEach(s -> System.out.println(s));
-                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
-                                }
-                                co.add(new Code(line.substring(j, old), realLine, layer));
-                                co.add(new Code("postinc", 1, realLine, layer));
-                            }
-                            lastSpecial.push(j);
-                            function = true;
-                            break;
-                        }
-                        syntax = "add"; 
-                        break;
-                    case '-': 
-                        if(line.charAt(j - 1) == '-')
-                        {
-                            int last = lastSpecial.pop();
-                            if(last - j >= 2)
-                            {
-                                // ++i
-                                if(j + 1 - last == 0)
-                                {                                  
-                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
-                                }
-                                co.add(new Code(line.substring(j + 1, last), realLine, layer));
-                                co.add(new Code("dec", 1, realLine, layer));
-                                j--;
-                            }
-                            else
-                            {
-                                Code c = co.get(co.size() - 1);
-                                if("array.get".equals(c.function))
-                                {
-                                    co.set(co.size() - 1, new Code("array.dec", 2, c.realLine, c.layer));
-                                    j--;
-                                    lastSpecial.push(j);
-                                    function = true;
-                                    break;
-                                }
-                                // i++
-                                j--;
-                                old = j;
-                                j--;
-                                if(line.charAt(j) == ']')
-                                {
-                                    arrayFunction = "postdec";
-                                    lastSpecial.push(j);
-                                    j--;
-                                    continue;
-                                }
-                                while(j >= 0 && isAllowedChar(line.charAt(j)))
-                                {
-                                    j--;
-                                }
-                                j++;
-                                if(j - old == 0)
-                                {
-                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
-                                }
-                                co.add(new Code(line.substring(j, old), realLine, layer));
-                                co.add(new Code("postdec", 1, realLine, layer));
-                            }
-                            lastSpecial.push(j);
-                            function = true;
-                            break;
-                        }
-                        syntax = "sub"; 
-                        break;
-                    case '*': syntax = "mul"; break;
-                    case '/': syntax = "div"; break;
-                    case '%': syntax = "math.mod"; break;
-                    case '^': syntax = "math.pow"; break;
-                    case '<': syntax = "less"; break;
-                    case '>': syntax = "greater"; break;
-                    case '|': 
+                    throw new PreScriptException(scriptName, realLine, "unexpected character");
+                }
+                else if(syntax.isIncOrDec())
+                {
+                    Code change = co.get(co.size() - 1);
+                    if(change.function.equals("array.get"))
                     {
-                        if(line.charAt(j - 1) == '|')
-                        {
-                            function = push(strings, co, j);
-                            nextFunction.put(bracketCounter, "or");
-                            j--;
-                            lastSpecial.push(j);
-                            j--;
-                            continue;
-                        }
-                        break;
+                        change.function = "array." + syntax.getFunction();
                     }
-                    case '&': 
+                }
+                s = line.substring(i + 1, old);
+                if(!s.isEmpty())
+                {
+                    Stack<Syntax> stack = syntaxStack.peek();
+                    if(!stack.isEmpty())
                     {
-                        if(line.charAt(j - 1) == '&')
+                        Syntax sy = stack.peek();
+                        if(sy == Syntax.INC)
                         {
-                            function = push(strings, co, j);
-                            nextFunction.put(bracketCounter, "and");
-                            j--;
-                            lastSpecial.push(j);
-                            j--;
-                            continue;
+                            stack.pop();
+                            stack.push(Syntax.POST_INC);
+                        }
+                        else if(sy == Syntax.DEC)
+                        {
+                            stack.pop();
+                            stack.push(Syntax.POST_DEC);
                         }
-                        break;
                     }
-                    case ']':
+                    co.add(new Code(Code.convertInput(strings, s, true), realLine, layer));
+                }
+                i += 1 - syntax.getFunction().length();
+                old = i;
+                if(syntax.shouldStartLayer())
+                {
+                    syntaxStack.push(new Stack<>());
+                    commaCounter.push(0);
+                    continue;
+                }
+                else if(syntax.shouldEndLayer())
+                {
+                    Stack<Syntax> currentStack = syntaxStack.pop();
+                    while(!currentStack.isEmpty())
                     {
-                        bracketCounter++;
-                        lastSpecial.push(j);
-                        break;
+                        doStackEmptying(co, currentStack.pop());
                     }
-                    case '[':
+                    old--;
+                    int pos = old;
+                    while(old >= 0 && isAllowedChar(chars[old]))
                     {
-                        old = lastSpecial.pop();
-                        if(old - j >= 2)
-                        {
-                            co.add(new Code(Code.convertInput(strings, line.substring(j + 1, old), true), realLine, layer));
-                        }
-                        String sNextFunction = nextFunction.remove(bracketCounter);
-                        if(sNextFunction != null)
-                        {
-                            co.add(new Code(sNextFunction, 2, realLine, layer));
-                        }
-                        old = j;
-                        j--;
-                        while(j >= 0 && isAllowedChar(line.charAt(j)))
-                        {
-                            j--;
-                        }
-                        j++;
-                        co.add(new Code(line.substring(j, old), realLine, layer));
-                        if(arrayFunction != null)
-                        {
-                            if(arrayFunction.equals("postinc") || arrayFunction.equals("postdec"))
-                            {
-                                co.add(new Code("array." + arrayFunction, 2, realLine, layer));
-                                arrayFunction = null;
-                                lastSpecial.push(j);
-                                break;
-                            }
-                            co.add(new Code("array." + arrayFunction, 3, realLine, layer));
-                            arrayFunction = null;
-                            j = -1;
-                            continue;
-                        }
-                        else if(arrayState)
-                        {
-                            co.add(new Code("array.get", 2, realLine, layer));
-                        }
-                        else
-                        {
-                            co.add(new Code("array.set", 3, realLine, layer));
-                        }
-                        lastSpecial.push(j);
-                        function = true;
-                        bracketCounter--;
-                        break;
+                        old--;
                     }
-                    case '=':
+                    old++;
+                    s = line.substring(old, pos + 1);
+                    if(syntax.isArray())
                     {
-                        char before = line.charAt(j - 1);
-                        switch(before)
-                        {
-                            case '=': syntax = "equal"; break;
-                            case '!': syntax = "notequal"; break;
-                            case '>': syntax = "greaterequal"; break;
-                            case '<': syntax = "lessequal"; break;
-                            case ']': syntax = "bracket"; break;
-                        }
-                        if(syntax != null)
-                        {
-                            if(syntax.equals("bracket"))
-                            {
-                                arrayState = false;
-                                function = push(strings, co, j);
-                                j--;
-                                lastSpecial.push(j);
-                                j--;
-                                continue;
-                            }
-                            function = push(strings, co, j);
-                            nextFunction.put(bracketCounter, syntax);
-                            j--;
-                            lastSpecial.push(j);
-                            j--;
-                            continue;
-                        }
-                        function = push(strings, co, j);
-                        int checker = j - 2;
-                        char c;
-                        while(checker >= 0)
+                        co.add(new Code(s, realLine, layer));
+                        if(!syntaxStack.isEmpty())
                         {
-                            c = line.charAt(checker);
-                            if(c == ']')
-                            {
-                                break;
-                            }
-                            else if(!isAllowedChar(c))
+                            Stack<Syntax> arrayFunction = syntaxStack.pop();
+                            if(!arrayFunction.isEmpty())
                             {
-                                throw new PreScriptException(scriptName, realLine, "unexpected character");
-                            }
-                            checker--;
-                        }
-                        String var;
-                        switch(before)
-                        {
-                            case '+': syntax = "add"; break;
-                            case '-': syntax = "sub"; break;
-                            case '*': syntax = "mul"; break;
-                            case '/': syntax = "div"; break;
-                            default:
-                                var = line.substring(0, j);
-                                co.add(new Code(var, realLine, layer));
-                        }
-                        if(syntax != null)
-                        {
-                            if(line.charAt(j - 2) == ']')
-                            {
-                                arrayFunction = syntax;
-                                j -= 2;
+                                Syntax sy = arrayFunction.pop();
+                                if(sy.isIncOrDec())
+                                {
+                                    if(sy == Syntax.INC)
+                                    {
+                                        sy = Syntax.POST_INC;
+                                    }
+                                    else if(sy == Syntax.DEC)
+                                    {
+                                        sy = Syntax.POST_DEC;
+                                    }
+                                }
+                                co.add(new Code("array." + sy.getFunction(), sy.isIncOrDec() ? 2 : 3, realLine, layer));
                                 continue;
                             }
-                            co.add(new Code(line.substring(0, j - 1), realLine, layer));
-                            co.add(new Code(syntax + "var", 2, realLine, layer));
-                        }
-                        else
-                        {
-                            co.add(new Code("setvar", 2, realLine, layer));
                         }
-                        j = -1;
-                        continue;
+                        co.add(new Code("array.get", 2, realLine, layer));
                     }
-                    case ')':
+                    else
                     {
-                        bracketCounter++;
-                        lastSpecial.push(j);
-                        commaCounter.push(0);
-                        break;
-                    }
-                    case ',':
-                    {
-                        commaCounter.push(commaCounter.pop() + 1);
-                        function = push(strings, co, j);
-                        lastSpecial.push(j);
-                        break;
-                    }
-                    case '(':
-                    {
-                        commas = commaCounter.pop() + 1;
-                        if(line.charAt(j + 1) != ')')
+                        if(line.startsWith("()", pos + 1))
                         {
-                            if(j + 1 != lastSpecial.peek())
-                            {
-                                co.add(new Code(Code.convertInput(strings, line.substring(j + 1, lastSpecial.pop()), true), realLine, layer));
-                            }
+                            co.add(new Code(s, 0, realLine, layer));
                         }
                         else
                         {
-                            commas = 0;
-                        }
-                        String sNextFunction = nextFunction.remove(bracketCounter);
-                        if(sNextFunction != null)
-                        {
-                            co.add(new Code(sNextFunction, 2, realLine, layer));
-                        }
-                        bracketCounter--;
-                        function = true;
-                        old = j;
-                        j--;
-                        while(j >= 0 && isAllowedChar(line.charAt(j)))
-                        {
-                            j--;
+                            co.add(new Code(s, commaCounter.pop() + 1, realLine, layer));
                         }
-                        j++;
-                        co.add(new Code(line.substring(j, old).toLowerCase(), commas, realLine, layer));
-                        lastSpecial.push(j);
                     }
+                    continue;
+                }
+                else if(!syntaxStack.isEmpty())
+                {
+                    Stack<Syntax> currentStack = syntaxStack.peek();
+                    while(!currentStack.isEmpty() && currentStack.peek().getWeight() <= syntax.getWeight())
+                    {
+                        doStackEmptying(co, currentStack.pop());
+                    }
+                    currentStack.push(syntax);
                 }
-                if(syntax != null)
+                
+                if(syntax == Syntax.COMMA)
                 {
-                    function = push(strings, co, j);
-                    nextFunction.put(bracketCounter, syntax);
-                    lastSpecial.push(j);
+                    commaCounter.push(commaCounter.pop() + 1);
                 }
-                j--;
             }
         }
-        catch(StringIndexOutOfBoundsException ex)
+        
+        s = line.substring(0, old);
+        if(!s.isEmpty())
         {
-            throw new PreScriptException(scriptName, realLine, "unexpected character");
+            co.add(new Code(s, realLine, layer));
+        }
+        
+        if(!syntaxStack.isEmpty())
+        {
+            Stack<Syntax> currentStack = syntaxStack.peek();
+            while(!currentStack.isEmpty())
+            {
+                doStackEmptying(co, currentStack.pop());
+            }
+        }
+    }
+    
+    private void doStackEmptying(ArrayList<Code> co, Syntax sy)
+    {
+        if(sy.isFunction())
+        {
+            if(sy.isIncOrDec())
+            {
+                Code change = co.get(co.size() - 1);
+                if(change.value instanceof Variable)
+                {
+                    change.value = ((Variable) change.value).getName();
+                }
+                co.add(new Code(sy.getFunction(), sy.getParameters(), realLine, layer));
+            }
+            else
+            {
+                co.add(new Code(sy.getFunction(), sy.getParameters(), realLine, layer));
+            }
+        }
+    }
+    
+    private static Syntax getSyntax(String code, int pos)
+    {
+        // priorities from C specification
+        // http://en.cppreference.com/w/c/language/operator_precedence
+        switch(code.charAt(pos))
+        {
+            case '(': return Syntax.OPEN_BRACKET;
+            case ')': return Syntax.CLOSE_BRACKET;
+            case '[': return Syntax.OPEN_SBRACKET;
+            case ']': return Syntax.CLOSE_SBRACKET;
+            case '!': return Syntax.NOT;
+            case '~': return Syntax.BIT_NOT;
+            case '*': return Syntax.MUL;
+            case '/': return Syntax.DIV;
+            case '%': return Syntax.MOD;
+            case '^': return Syntax.BIT_XOR;
+            case ',': return Syntax.COMMA;
+            case '+': 
+                if(pos >= 1 && code.charAt(pos - 1) == '+')
+                {
+                    return Syntax.INC;
+                }
+                return Syntax.ADD;
+            case '-': 
+                if(pos >= 1 && code.charAt(pos - 1) == '-')
+                {
+                    return Syntax.DEC;
+                }
+                return Syntax.SUB;
+            case '<': 
+                if(pos >= 1 && code.charAt(pos - 1) == '<')
+                {
+                    return Syntax.LEFT_SHIFT;
+                }
+                return Syntax.SMALLER;
+            case '>': 
+                if(pos >= 1 && code.charAt(pos - 1) == '>')
+                {
+                    return Syntax.RIGHT_SHIFT;
+                }
+                return Syntax.GREATER;
+            case '&': 
+                if(pos >= 1 && code.charAt(pos - 1) == '&')
+                {
+                    return Syntax.AND;
+                }
+                return Syntax.BIT_AND;
+            case '|': 
+                if(pos >= 1 && code.charAt(pos - 1) == '|')
+                {
+                    return Syntax.OR;
+                }
+                return Syntax.BIT_OR;
+            case '=':
+                if(pos >= 1)
+                {
+                    switch(code.charAt(pos - 1))
+                    {
+                        case '<': 
+                            if(pos >= 2 && code.charAt(pos - 2) == '<')
+                            {
+                                return Syntax.SET_SHIFT_LEFT;
+                            }
+                            return Syntax.SMALLER_EQUAL;
+                        case '>': 
+                            if(pos >= 2 && code.charAt(pos - 2) == '>')
+                            {
+                                return Syntax.SET_SHIFT_RIGHT;
+                            }
+                            return Syntax.GREATER_EQUAL;
+                        case '=': return Syntax.EQUAL;
+                        case '!': return Syntax.NOT_EQUAL;
+                        case '+': return Syntax.SET_ADD;
+                        case '-': return Syntax.SET_SUB;
+                        case '*': return Syntax.SET_MUL;
+                        case '/': return Syntax.SET_DIV;
+                        case '%': return Syntax.SET_MOD;
+                        case '&': return Syntax.SET_BIT_AND;
+                        case '^': return Syntax.SET_BIT_XOR;
+                        case '|': return Syntax.SET_BIT_OR;
+                    }
+                }
+                return Syntax.SET;
         }
+        return Syntax.UNKNOWN;
     }
 }

+ 6 - 3
src/me/hammerle/code/Script.java

@@ -298,14 +298,17 @@ public class Script
         }
     }
     
-    public void gotoLabel(String label, boolean scheduled)
+    public void gotoLabel(String label, boolean scheduled, boolean resetFor)
     {
         Integer i = gotos.get(label);
         if(i == null)
         {
             throw new GotoLabelNotFoundException(label);
         }
-        forMap.clear();
+        if(resetFor)
+        {
+            forMap.clear();
+        }
         incLoopCounter();
         position = i - (scheduled ? 0 : 1);
     }  
@@ -318,7 +321,7 @@ public class Script
     public void gotoLabelWithReturn(String label)
     {
         returnStack.push(position);
-        gotoLabel(label, false);
+        gotoLabel(label, false, false);
     }
     
     public void doReturn()

+ 26 - 22
src/me/hammerle/code/SnuviParser.java

@@ -224,25 +224,25 @@ public class SnuviParser
         // -------------------------------------------------------------------------------    
         registerConsumer("array.new", (args, sc) ->                                                
                 sc.setVar(args[0].toString(), new Object[ScriptUtils.getInt(args[1])]));
-        registerConsumer("array.set", (args, sc) ->                            
+        registerConsumer("array.=", (args, sc) ->                            
                 ((Object[]) sc.getVar(args[0].toString()))[ScriptUtils.getInt(args[1])] = args[2]);
         registerFunction("array.get", (args, sc) ->                            
                 ((Object[]) sc.getVar(args[0].toString()))[ScriptUtils.getInt(args[1])]);
-        registerFunction("array.inc", (args, sc) -> 
+        registerFunction("array.++", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
                     o[i] = ((Fraction) o[i]).add(new Fraction(1));
                     return o[i];
                 });
-        registerFunction("array.dec", (args, sc) -> 
+        registerFunction("array.--", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
                     o[i] = ((Fraction) o[i]).sub(new Fraction(1));
                     return o[i];
                 });
-        registerFunction("array.postinc", (args, sc) -> 
+        registerFunction("array.p+", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
@@ -250,7 +250,7 @@ public class SnuviParser
                     o[i] = f.add(new Fraction(1));
                     return f;
                 });
-        registerFunction("array.postdec", (args, sc) -> 
+        registerFunction("array.p-", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
@@ -258,25 +258,25 @@ public class SnuviParser
                     o[i] = f.sub(new Fraction(1));
                     return f;
                 });
-        registerConsumer("array.add", (args, sc) -> 
+        registerConsumer("array.+=", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
                     o[i] = ((Fraction) o[i]).add((Fraction) args[2]);
                 });
-        registerConsumer("array.sub", (args, sc) -> 
+        registerConsumer("array.-=", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
                     o[i] = ((Fraction) o[i]).sub((Fraction) args[2]);
                 });
-        registerConsumer("array.mul", (args, sc) -> 
+        registerConsumer("array.*=", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
                     o[i] = ((Fraction) o[i]).mul((Fraction) args[2]);
                 });
-        registerConsumer("array.div", (args, sc) -> 
+        registerConsumer("array./=", (args, sc) -> 
                 {
                     Object[] o =  (Object[]) sc.getVar(args[0].toString());
                     int i = ScriptUtils.getInt(args[1]);
@@ -470,26 +470,26 @@ public class SnuviParser
         // -------------------------------------------------------------------------------    
         // commands without library
         // -------------------------------------------------------------------------------    
-        registerFunction("add", (args, sc) -> 
+        registerFunction("+", (args, sc) -> 
                 ((Fraction) args[0]).add((Fraction) args[1]));
-        registerFunction("sub", (args, sc) -> 
+        registerFunction("-", (args, sc) -> 
                 ((Fraction) args[0]).sub((Fraction) args[1]));
-        registerConsumer("addvar", (args, sc) -> 
+        registerConsumer("+=", (args, sc) -> 
                 {
                     String s = args[0].toString();
                     sc.setVar(s, ((Fraction) sc.getVar(s)).add((Fraction) args[1]));
                 });
-        registerConsumer("subvar", (args, sc) -> 
+        registerConsumer("-=", (args, sc) -> 
                 {
                     String s = args[0].toString();
                     sc.setVar(s, ((Fraction) sc.getVar(s)).sub((Fraction) args[1]));
                 });
-        registerConsumer("mulvar", (args, sc) -> 
+        registerConsumer("*=", (args, sc) -> 
                 {
                     String s = args[0].toString();
                     sc.setVar(s, ((Fraction) sc.getVar(s)).mul((Fraction) args[1]));
                 });
-        registerConsumer("divvar", (args, sc) -> 
+        registerConsumer("/=", (args, sc) -> 
                 {
                     String s = args[0].toString();
                     sc.setVar(s, ((Fraction) sc.getVar(s)).div((Fraction) args[1]));
@@ -501,6 +501,7 @@ public class SnuviParser
                     sc.setVar(s, n);
                     return n;
                 });
+        registerAlias("++", "inc");
         registerFunction("dec", (args, sc) -> 
                 {
                     String s = args[0].toString();
@@ -508,6 +509,7 @@ public class SnuviParser
                     sc.setVar(s, n);
                     return n;
                 });
+        registerAlias("--", "dec");
         registerFunction("postinc", (args, sc) -> 
                 {
                     String s = args[0].toString();
@@ -515,6 +517,7 @@ public class SnuviParser
                     sc.setVar(s, n.add(new Fraction(1)));
                     return n;
                 });
+        registerAlias("p+", "postinc");
         registerFunction("postdec", (args, sc) -> 
                 {
                     String s = args[0].toString();
@@ -522,14 +525,16 @@ public class SnuviParser
                     sc.setVar(s, n.add(new Fraction(-1)));
                     return n;
                 });
-        registerFunction("mul", (args, sc) -> 
+        registerAlias("p-", "postdec");
+        registerFunction("*", (args, sc) -> 
                 ((Fraction) args[0]).mul((Fraction) args[1]));
-        registerFunction("div", (args, sc) -> 
+        registerFunction("/", (args, sc) -> 
                 ((Fraction) args[0]).div((Fraction) args[1]));
         registerFunction("getvar", (args, sc) -> 
                 sc.getVar(args[0].toString()));
         registerConsumer("setvar", (args, sc) -> 
                 sc.setVar(args[0].toString(), args[1]));
+        registerAlias("=", "setvar");
         registerConsumer("removevar", (args, sc) -> 
                 sc.removeVar(args[0].toString()));
         registerConsumer("reset", (args, sc) -> 
@@ -539,7 +544,7 @@ public class SnuviParser
         
         // branching
         registerConsumer("goto", (args, sc) -> 
-                sc.gotoLabel(args[0].toString(), false));
+                sc.gotoLabel(args[0].toString(), false, true));
         registerConsumer("sgoto", (args, sc) -> 
                 scheduleGoto(args, sc));
         registerConsumer("gosub", (args, sc) -> 
@@ -589,9 +594,8 @@ public class SnuviParser
                 }); 
         registerConsumer("continue", (args, sc) -> 
                 sc.jump()); 
-        registerFunction("equal", (args, sc) -> 
+        registerFunction("==", (args, sc) -> 
                 isEqual(args));
-        registerAlias("equals", "equal");
         registerFunction("less", (args, sc) -> 
                 ((Fraction) args[0]).compareTo((Fraction) args[1]) < 0);
         registerFunction("greater", (args, sc) -> 
@@ -606,7 +610,7 @@ public class SnuviParser
                 !((boolean) args[0]));
         registerFunction("and", (args, sc) -> 
                 Arrays.stream(args).allMatch(s -> s.equals(true)));
-        registerFunction("or", (args, sc) -> 
+        registerFunction("||", (args, sc) -> 
                 Arrays.stream(args).anyMatch(s -> s.equals(true)));
         registerConsumer("waitfor", (args, sc) ->     
                 waitFor(args, sc));
@@ -898,7 +902,7 @@ public class SnuviParser
             }
             try
             {
-                sc.gotoLabel(args[1].toString(), true);
+                sc.gotoLabel(args[1].toString(), true, true);
                 sc.runCode();
             }
             catch(Exception ex)

+ 109 - 0
src/me/hammerle/code/Syntax.java

@@ -0,0 +1,109 @@
+package me.hammerle.code;
+
+public enum Syntax
+{
+    UNKNOWN(" ", 0),
+    OPEN_BRACKET("(", 1, (byte) 2),
+    CLOSE_BRACKET(")", 1, (byte) 1),
+    OPEN_SBRACKET("[", 1, (byte) 4),
+    CLOSE_SBRACKET("]", 1, (byte) 3),
+    INC("++", 2, (byte) 5, (byte) 1),
+    POST_INC("p+", 2, (byte) 5, (byte) 1),
+    DEC("--", 2, (byte) 5, (byte) 1),
+    POST_DEC("p-", 2, (byte) 5, (byte) 1),
+    NOT("!", 2, (byte) 0, (byte) 1),
+    BIT_NOT("~", 2, (byte) 0, (byte) 1),
+    MUL("*", 3),
+    DIV("/", 3),
+    MOD("%", 3),
+    ADD("+", 4),
+    SUB("-", 4),
+    LEFT_SHIFT("<<", 5),
+    RIGHT_SHIFT(">>", 5),
+    SMALLER("<", 6),
+    SMALLER_EQUAL("<=", 6),
+    GREATER(">", 6),
+    GREATER_EQUAL(">=", 6),
+    EQUAL("==", 7),
+    NOT_EQUAL("!=", 7),
+    BIT_AND("&", 8),
+    BIT_XOR("^", 9),
+    BIT_OR("|", 10),
+    AND("&&", 11),
+    OR("||", 12),
+    SET("=", 14),
+    SET_ADD("+=", 14),
+    SET_SUB("-=", 14),
+    SET_MUL("*=", 14),
+    SET_DIV("/=", 14),
+    SET_MOD("%=", 14),
+    SET_SHIFT_LEFT("<<=", 14),
+    SET_SHIFT_RIGHT(">>=", 14),
+    SET_BIT_AND("&=", 14),
+    SET_BIT_XOR("^=", 14),
+    SET_BIT_OR("|=", 14),
+    COMMA(",", 15, (byte) -1);       
+
+    private int weight;
+    private String function;
+    private byte status;
+    private byte pars;
+
+    Syntax(String function, int weight, byte status, byte pars)
+    {
+        this.weight = weight;
+        this.function = function;
+        this.status = status;
+        this.pars = pars;
+    }   
+    
+    Syntax(String function, int weight, byte status)
+    {
+        this(function, weight, status, (byte) 2);
+    }
+
+    Syntax(String function, int weight)
+    {
+        this(function, weight, (byte) 0);
+    }
+
+    public String getFunction() 
+    {
+        return function;
+    }
+
+    public int getWeight() 
+    {
+        return weight;
+    }
+
+    public boolean shouldStartLayer()
+    {
+        return status == 1 || status == 3;
+    }
+
+    public boolean shouldEndLayer()
+    {
+        return status == 2 || status == 4;
+    }
+    
+    public boolean isFunction()
+    {
+        return status >= 0;
+    }
+
+    public boolean isArray()
+    {
+        return status == 3 || status == 4;
+    }
+    
+    public boolean isIncOrDec()
+    {
+        return status == 5;
+    }
+    
+    public byte getParameters()
+    {
+        return pars;
+    }
+}

+ 0 - 1
src/me/hammerle/config/SnuviConfig.java

@@ -2,7 +2,6 @@ package me.hammerle.config;
 
 import java.io.File;
 import java.io.IOException;
-import java.nio.charset.Charset;
 import java.nio.charset.MalformedInputException;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;

+ 25 - 4
src/me/hammerle/snuviscript/SnuviScript.java

@@ -5,6 +5,7 @@ import me.hammerle.code.ISnuviScheduler;
 import me.hammerle.code.Script;
 import me.hammerle.code.SnuviParser;
 import me.hammerle.exceptions.PreScriptException;
+import me.hammerle.math.Fraction;
 
 public class SnuviScript 
 {
@@ -16,6 +17,7 @@ public class SnuviScript
             public void printException(Exception ex, String function, Script s, int line) 
             {
                 System.out.println("Exception " + ex);
+                System.out.println("function " + function);
                 System.out.println("Line: " + line);
             }
 
@@ -23,6 +25,7 @@ public class SnuviScript
             public void printException(Exception ex, String function, String s, int line) 
             {
                 System.out.println("Exception " + ex + " " + s + " " + line);
+                System.out.println("function " + function);
             }
 
             @Override
@@ -55,6 +58,7 @@ public class SnuviScript
             }
         });
         parser.registerConsumer("print", (o, sc) -> System.out.println(o[0]));
+        parser.registerFunction("get", (o, sc) -> new Fraction(1));
         //parser.registerFunction("ggv", (o, sc) -> o[0]);
         //parser.registerFunction("read.item", (o, sc) -> o[0]);
              
@@ -108,13 +112,30 @@ public class SnuviScript
             //String s = "wusi = 3; wusi /= 2; debug(wusi);";
             // array.set("wusi", 1, arrays.get("wusi", 1) + 4)
             //String s = "debug(wusi[1]);";
-            String s = "print(\"wusi\");\n" +
+            /*String s = "print(\"wusi\");\n" +
 "print(hallo(1, 3, 5));\n" +
 "term();\n" +
 "\n" +
-"@hallo;\n" +
-"pushArg(popArg() + popArg() + popArg() + popArg());\n" +
-"return;";
+"@hallo;\npopArg(); \n" +
+"pushArg(popArg() + popArg() + popArg());\n" +
+"return;";*/
+            
+            //String s = "print(1 + 2 * 3 * 5 + 2);";
+            //String s = "print(1 + get(3 - 2) + 1);";
+            //String s = "print(1 + get(1, 2) == 1 || get() == 1);";
+            //String s = "print(12 + 234 == 32 || 4 == 45);";           
+            //String s = "setvar(\"test\", 3); print(test + get(2, 5 + get(9, 8 + 3) + 6) == 4);";
+            
+            //String s = "print(array[2 + 3]);";
+            //String s = "a = 3; a++; print(a);";
+            //String s = "array[2 + 3] = 5;";
+            //String s = "a(1+b(2), c(3) + 3, d(7,e(10 + 3)))";
+            //String s = "++wusi[1];";
+            String s = "array.new(\"wusi\", 10); wusi[2] = 3; wusi[2]++; print(wusi[2]);";
+        
+            //String s = "print(1 + get() == 1);";
+            System.out.println(s);
+            System.out.println();
             //String s = "i = 0; while(i++ < 10) { debug(i);}";
             //String s = "error(); debug(1+1);";
             //System.out.println(s);