Răsfoiți Sursa

Merge branch 'master' into maven

Niklas Seyfarth 6 ani în urmă
părinte
comite
a8171f6298

+ 1 - 2
.gitignore

@@ -1,6 +1,5 @@
-.DS_Store
 /nbproject
 /build
 /dist
 /todo.html
-/target/
+/target/

+ 26 - 8
src/main/java/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;
@@ -183,22 +183,26 @@ public class Code
         return -1;
     }
 
-    public static int countChar(char find, int end, StringBuilder code)
+    public static int countChar(char find, int start, int end, StringBuilder code)
     {
         int counter = 0;
-        int pos = 0;
         end = Math.min(end, code.length());
-        while(pos < end)
+        while(start < end)
         {
-            if(code.charAt(pos) == find)
+            if(code.charAt(start) == find)
             {
                 counter++;
             }
-            pos++;
+            start++;
         }
         return counter;
     }
     
+    public static int countChar(char find, int end, StringBuilder code)
+    {
+        return countChar(find, 0, end, code);
+    }
+    
     @SuppressWarnings("")
     private static String removeNonSyntax(String s)
     {
@@ -219,10 +223,22 @@ public class Code
         return sb.toString();
     }
     
+    private static String getCommentString(int start, int end, StringBuilder code)
+    {
+        int i = countChar('\n', start, end, code);
+        StringBuilder sb = new StringBuilder();
+        for(; i > 0; i--)
+        {
+            sb.append('\n');
+        }
+        return sb.toString();
+    }
+    
     private static void removeComments(StringBuilder sb)
     {
         int old = 0;
         int pos;
+        String replace;
         while(true)
         {
             old = findSyntaxIgnoreString("/*", sb, old);
@@ -235,7 +251,8 @@ public class Code
             {
                 throw new PreScriptException(scriptName, countChar('\n', old, sb), "/* without */");
             }
-            sb.delete(old, pos + 2);
+            replace = getCommentString(old, pos + 2, sb);
+            sb.replace(old, pos + 2, replace);
         }
         old = 0;
         while(true)
@@ -251,7 +268,8 @@ public class Code
                 sb.delete(old, sb.length());
                 break;
             }
-            sb.delete(old, pos + 1);
+            replace = getCommentString(old, pos + 1, sb);
+            sb.replace(old, pos + 1, replace);
         }
     }
     

+ 199 - 366
src/main/java/me/hammerle/code/LineCompiler.java

@@ -9,428 +9,261 @@ 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;
     
+    // helper to support things like print(-3);
+    private boolean minus;
+    
     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;
+        minus = false;
         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;
+        minus = 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 == '#' || 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 '" + c + "'");
+                }
+                s = line.substring(i + 1, old).toLowerCase();
+                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, "or");
-                            j--;
-                            lastSpecial.push(j);
-                            j--;
-                            continue;
+                            stack.pop();
+                            stack.push(Syntax.POST_INC);
                         }
-                        break;
-                    }
-                    case '&': 
-                    {
-                        if(line.charAt(j - 1) == '&')
+                        else if(sy == Syntax.DEC)
                         {
-                            function = push(strings, co, j);
-                            nextFunction.put(bracketCounter, "and");
-                            j--;
-                            lastSpecial.push(j);
-                            j--;
-                            continue;
+                            stack.pop();
+                            stack.push(Syntax.POST_DEC);
                         }
-                        break;
                     }
-                    case ']':
-                    {
-                        bracketCounter++;
-                        lastSpecial.push(j);
-                        break;
-                    }
-                    case '[':
+                    co.add(new Code(Code.convertInput(strings, s, true), realLine, layer));
+                    minus = false;
+                }
+                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())
                     {
-                        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;
+                        doStackEmptying(co, currentStack.pop());
                     }
-                    case '=':
+                    old--;
+                    int pos = old;
+                    while(old >= 0 && isAllowedChar(chars[old]))
                     {
-                        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)
-                        {
-                            c = line.charAt(checker);
-                            if(c == ']')
-                            {
-                                break;
-                            }
-                            else if(!isAllowedChar(c))
-                            {
-                                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;
-                                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;
+                        old--;
                     }
-                    case ')':
+                    old++;
+                    s = line.substring(old, pos + 1).toLowerCase();
+                    minus = false;
+                    if(line.startsWith("()", pos + 1))
                     {
-                        bracketCounter++;
-                        lastSpecial.push(j);
-                        commaCounter.push(0);
-                        break;
+                        commaCounter.pop();
+                        co.add(new Code(s, 0, realLine, layer));
                     }
-                    case ',':
+                    else
                     {
-                        commaCounter.push(commaCounter.pop() + 1);
-                        function = push(strings, co, j);
-                        lastSpecial.push(j);
-                        break;
+                        co.add(new Code(s, commaCounter.pop() + 1, realLine, layer));
                     }
-                    case '(':
+                    continue;
+                }
+                else if(!syntaxStack.isEmpty())
+                {
+                    Stack<Syntax> currentStack = syntaxStack.peek();
+                    while(!currentStack.isEmpty() && currentStack.peek().getWeight() <= syntax.getWeight())
                     {
-                        commas = commaCounter.pop() + 1;
-                        if(line.charAt(j + 1) != ')')
-                        {
-                            if(j + 1 != lastSpecial.peek())
-                            {
-                                co.add(new Code(Code.convertInput(strings, line.substring(j + 1, lastSpecial.pop()), true), 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--;
-                        }
-                        j++;
-                        co.add(new Code(line.substring(j, old).toLowerCase(), commas, realLine, layer));
-                        lastSpecial.push(j);
+                        doStackEmptying(co, currentStack.pop());
                     }
+                    currentStack.push(syntax);
+                }
+                
+                if(syntax == Syntax.COMMA)
+                {
+                    commaCounter.push(commaCounter.pop() + 1);
+                }
+                else if(syntax == Syntax.SUB)
+                {
+                    minus = true;
+                }
+            }
+        }
+        
+        s = line.substring(0, old).toLowerCase();
+        if(!s.isEmpty())
+        {
+            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();
                 }
-                if(syntax != null)
+                co.add(new Code(sy.getFunction(), sy.getParameters(), realLine, layer));
+            }
+            else
+            {
+                if(minus)
                 {
-                    function = push(strings, co, j);
-                    nextFunction.put(bracketCounter, syntax);
-                    lastSpecial.push(j);
+                    minus = false;
+                    co.add(new Code(new Fraction(0), realLine, layer));
                 }
-                j--;
+                co.add(new Code(sy.getFunction(), sy.getParameters(), realLine, layer));
             }
         }
-        catch(StringIndexOutOfBoundsException ex)
+    }
+    
+    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))
         {
-            throw new PreScriptException(scriptName, realLine, "unexpected character");
+            case '(': return Syntax.OPEN_BRACKET;
+            case ')': return Syntax.CLOSE_BRACKET;
+            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/main/java/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()

+ 189 - 80
src/main/java/me/hammerle/code/SnuviParser.java

@@ -24,6 +24,7 @@ import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
+import me.hammerle.config.SnuviConfig;
 import me.hammerle.exceptions.FileIOException;
 import me.hammerle.exceptions.GotoLabelNotFoundException;
 import me.hammerle.exceptions.PreScriptException;
@@ -116,40 +117,31 @@ public class SnuviParser
         // bit
         // ------------------------------------------------------------------------------- 
         
-        registerFunction("bit.rightshiftn", (args, qd) -> 
-                ((Fraction) args[0]).rightShiftNumerator(getInt(args[1])));
-        registerFunction("bit.rightshiftd", (args, qd) -> 
-                ((Fraction) args[0]).rightShiftDenominator(getInt(args[1])));
-        registerFunction("bit.leftshiftn", (args, qd) -> 
-                ((Fraction) args[0]).leftShiftNumerator(getInt(args[1])));
-        registerFunction("bit.leftshiftd", (args, qd) -> 
-                ((Fraction) args[0]).leftShiftDenominator(getInt(args[1])));
-        registerFunction("bit.and", (args, qd) -> 
+        registerFunction(">>", (args, qd) -> 
+                ((Fraction) args[0]).rightShift(getInt(args[1])));
+        registerFunction("<<", (args, qd) -> 
+                ((Fraction) args[0]).leftShift(getInt(args[1])));
+        registerFunction("&", (args, qd) -> 
                 ((Fraction) args[0]).and((Fraction) args[1]));
-        registerFunction("bit.or", (args, qd) -> 
+        registerFunction("|", (args, qd) -> 
                 ((Fraction) args[0]).or((Fraction) args[1]));
-        registerFunction("bit.xor", (args, qd) -> 
+        registerFunction("^", (args, qd) -> 
                 ((Fraction) args[0]).xor((Fraction) args[1]));
-        registerFunction("bit.invert", (args, qd) -> 
-                ((Fraction) args[0]).invert());
-        registerFunction("bit.setn", (args, qd) -> 
-                ((Fraction) args[0]).setNumeratorBit(getInt(args[1])));
-        registerFunction("bit.setd", (args, qd) -> 
-                ((Fraction) args[0]).setDenominatorBit(getInt(args[1])));
-        registerFunction("bit.unsetn", (args, qd) -> 
-                ((Fraction) args[0]).unsetNumeratorBit(getInt(args[1])));
-        registerFunction("bit.unsetd", (args, qd) -> 
-                ((Fraction) args[0]).unsetDenominatorBit(getInt(args[1])));
-        registerFunction("bit.getn", (args, qd) -> 
-                ((Fraction) args[0]).getNumeratorBit(getInt(args[1])));
-        registerFunction("bit.getd", (args, qd) -> 
-                ((Fraction) args[0]).getDenominatorBit(getInt(args[1])));
+        registerFunction("~", (args, qd) -> 
+                ((Fraction) args[0]).invertBits());
+        registerFunction("bit.set", (args, qd) -> 
+                ((Fraction) args[0]).setBit(getInt(args[1])));
+        registerFunction("bit.unset", (args, qd) -> 
+                ((Fraction) args[0]).unsetBit(getInt(args[1])));
+        registerFunction("bit.get", (args, qd) -> 
+                ((Fraction) args[0]).getBit(getInt(args[1])));
         
         // -------------------------------------------------------------------------------    
         // math
         // -------------------------------------------------------------------------------    
-        registerFunction("math.mod", (args, sc) -> 
+        registerFunction("%", (args, sc) -> 
                 new Fraction(getInt(args[0]) % getInt(args[1])));
+        registerAlias("math.mod", "%");
         registerFunction("math.abs", (args, sc) -> 
                 ((Fraction) args[0]).abs());
         registerFunction("math.pow", (args, sc) -> 
@@ -175,7 +167,7 @@ public class SnuviParser
         registerFunction("math.ln", (args, sc) -> 
                 ((Fraction) args[0]).log());
         registerFunction("math.log", (args, sc) -> 
-                ((Fraction) args[0]).log());
+                ((Fraction) args[0]).log10());
         registerFunction("math.random", (args, sc) -> 
                 new Fraction(ScriptUtils.randomInt(getInt(args[0]), getInt(args[1]))));
         registerFunction("math.round", (args, sc) -> 
@@ -222,27 +214,28 @@ public class SnuviParser
         // -------------------------------------------------------------------------------  
         // arrays
         // -------------------------------------------------------------------------------    
-        registerConsumer("array.new", (args, sc) ->                                                
-                sc.setVar(args[0].toString(), new Object[ScriptUtils.getInt(args[1])]));
-        registerConsumer("array.set", (args, sc) ->                            
+        /*registerConsumer("array.new", (args, sc) ->                                                
+                sc.setVar(args[0].toString(), new Object[ScriptUtils.getInt(args[1])]));      
+        registerConsumer("array.=", (args, sc) ->                            
                 ((Object[]) sc.getVar(args[0].toString()))[ScriptUtils.getInt(args[1])] = args[2]);
+        registerAlias("array.set", "array.=");
         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 +243,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,32 +251,68 @@ 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]);
                     o[i] = ((Fraction) o[i]).div((Fraction) args[2]);
                 });
+        registerConsumer("array.%=", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ScriptUtils.getInt(o[i]) % ScriptUtils.getInt(args[2]);
+                });
+        registerConsumer("array.<<=", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).leftShift(ScriptUtils.getInt(args[2]));
+                });
+        registerConsumer("array.>>=", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).rightShift(ScriptUtils.getInt(args[2]));
+                });
+        registerConsumer("array.&=", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).and((Fraction) args[2]);
+                });
+        registerConsumer("array.^=", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).xor((Fraction) args[2]);
+                });
+        registerConsumer("array.|=", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).or((Fraction) args[2]);
+                });
         registerFunction("array.getsize", (args, sc) ->                            
-                ((Object[]) args[0]).length);
+                new Fraction(((Object[]) args[0]).length));
         registerConsumer("array.swap", (args, sc) ->                                           
                 {
                     Object[] o = (Object[]) args[0];
@@ -332,7 +361,7 @@ public class SnuviParser
                     {
                         Arrays.fill((Object[]) args[0], ScriptUtils.getInt(args[2]), ScriptUtils.getInt(args[3]), args[1]); 
                     }
-                });
+                });*/
                 
 
         // -------------------------------------------------------------------------------  
@@ -343,21 +372,23 @@ public class SnuviParser
         registerFunction("map.exists", (args, sc) ->                                                
                 args[0] instanceof Map);  
         registerConsumer("map.add", (args, sc) ->                            
-                ((HashMap) args[0]).put(args[1], args[2]));
+                ((Map) args[0]).put(args[1], args[2]));
         registerConsumer("map.remove", (args, sc) ->                            
-                ((HashMap) args[0]).remove(args[1]));
+                ((Map) args[0]).remove(args[1]));
         registerFunction("map.contains", (args, sc) ->                            
-                ((HashMap) args[0]).containsKey(args[1]));
+                ((Map) args[0]).containsKey(args[1]));
         registerFunction("map.getsize", (args, sc) ->                            
-                new Fraction(((HashMap) args[0]).size()));
+                new Fraction(((Map) args[0]).size()));
         registerFunction("map.get", (args, sc) ->                            
-                ((HashMap) args[0]).get(args[1]));
+                ((Map) args[0]).get(args[1]));
+        registerFunction("map.getordefault", (args, sc) ->                            
+                ((Map) args[0]).getOrDefault(args[1], args[2]));
         registerConsumer("map.clear", (args, sc) ->                            
-                ((HashMap) args[0]).clear());
+                ((Map) args[0]).clear());
         registerConsumer("map.keys", (args, sc) ->                            
-                sc.setVar(args[0].toString(), ((HashMap) args[1]).keySet().stream().collect(Collectors.toList())));
+                sc.setVar(args[0].toString(), ((Map) args[1]).keySet().stream().collect(Collectors.toList())));
         registerConsumer("map.values", (args, sc) ->                            
-                sc.setVar(args[0].toString(), ((HashMap) args[1]).values().stream().collect(Collectors.toList())));
+                sc.setVar(args[0].toString(), ((Map) args[1]).values().stream().collect(Collectors.toList())));
         
         // -------------------------------------------------------------------------------  
         // sets
@@ -367,15 +398,15 @@ public class SnuviParser
         registerFunction("set.exists", (args, sc) ->                                                
                 args[0] instanceof Set);  
         registerConsumer("set.add", (args, sc) ->                            
-                ((HashSet) args[0]).add(args[1]));
+                ((Set) args[0]).add(args[1]));
         registerConsumer("set.remove", (args, sc) ->                            
-                ((HashSet) args[0]).remove(args[1]));
+                ((Set) args[0]).remove(args[1]));
         registerFunction("set.contains", (args, sc) ->                            
-                ((HashSet) args[0]).contains(args[1]));
+                ((Set) args[0]).contains(args[1]));
         registerFunction("set.getsize", (args, sc) ->                            
-                new Fraction(((HashSet) args[0]).size()));
+                new Fraction(((Set) args[0]).size()));
         registerConsumer("set.tolist", (args, sc) ->                            
-                sc.setVar(args[0].toString(), ((HashSet) args[1]).stream().collect(Collectors.toList())));
+                sc.setVar(args[0].toString(), ((Set) args[1]).stream().collect(Collectors.toList())));
 
         // -------------------------------------------------------------------------------  
         // time
@@ -400,6 +431,8 @@ public class SnuviParser
         // -------------------------------------------------------------------------------    
         // text
         // -------------------------------------------------------------------------------   
+        registerFunction("text.matches", (args, sc) ->         
+                args[0].toString().matches(args[1].toString())); 
         registerFunction("text.number", (args, sc) ->         
                 fractionToDoubleString((Fraction) args[0])); 
         registerFunction("text.class", (args, sc) ->         
@@ -450,16 +483,14 @@ public class SnuviParser
         // files
         // ------------------------------------------------------------------------------- 
         
-        registerFunction("file.new", (args, sc) ->         
-                new File(args[0].toString()));
+        registerConsumer("file.new", (args, sc) ->    
+                sc.setVar(args[0].toString(), new File(args[1].toString())));
         registerFunction("file.exists", (args, sc) ->         
                 ((File) args[0]).exists());
         registerFunction("file.delete", (args, sc) ->         
                 ((File) args[0]).delete());
         registerFunction("file.getname", (args, sc) ->         
                 ((File) args[0]).getName());
-        registerFunction("file.", (args, sc) ->         
-                ((File) args[0]).renameTo(new File(args[1].toString())));
         registerConsumer("file.getlist", (args, sc) ->         
                 sc.setVar(args[0].toString(),  Arrays.asList(((File) args[0]).listFiles())));
         registerConsumer("file.read", (args, sc) ->         
@@ -467,33 +498,86 @@ public class SnuviParser
         registerConsumer("file.write", (args, sc) ->         
                 writeFile(args, sc));
         
+        // ---------------------------------------------------------------------  
+        // config
+        // ---------------------------------------------------------------------
+        
+        registerConsumer("config.new", (args, sc) ->         
+                sc.setVar(args[0].toString(), new SnuviConfig(logger, args[1].toString(), args[2].toString())));
+        registerFunction("config.exists", (args, sc) ->         
+                ((SnuviConfig) args[0]).exists());
+        registerFunction("config.save", (args, sc) ->         
+                ((SnuviConfig) args[0]).save());
+        registerFunction("config.delete", (args, sc) ->         
+                ((SnuviConfig) args[0]).delete());
+        registerConsumer("config.set", (args, sc) ->         
+                ((SnuviConfig) args[0]).set(args[1].toString(), args[2]));
+        registerFunction("config.getbool", (args, sc) ->         
+                ((SnuviConfig) args[0]).getBoolean(args[1].toString(), args[2] == null ? null : (boolean) args[2]));
+        registerFunction("config.getfraction", (args, sc) ->         
+                ((SnuviConfig) args[0]).getFraction(args[1].toString(), (Fraction) args[2]));
+        registerFunction("config.getstring", (args, sc) ->         
+                ((SnuviConfig) args[0]).getString(args[1].toString(), args[2] == null ? null : args[2].toString()));
+        
         // -------------------------------------------------------------------------------    
         // commands without library
         // -------------------------------------------------------------------------------    
-        registerFunction("add", (args, sc) -> 
+        registerFunction("+", (args, sc) -> 
                 ((Fraction) args[0]).add((Fraction) args[1]));
-        registerFunction("sub", (args, sc) -> 
+        registerAlias("add", "+");
+        registerFunction("-", (args, sc) -> 
                 ((Fraction) args[0]).sub((Fraction) args[1]));
-        registerConsumer("addvar", (args, sc) -> 
+        registerAlias("sub", "-");
+        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]));
                 });
+        registerConsumer("%=", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ScriptUtils.getInt(sc.getVar(s)) % ScriptUtils.getInt(args[1]));
+                });
+        registerConsumer("<<=", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).leftShift(ScriptUtils.getInt(args[1])));
+                });
+        registerConsumer(">>=", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).rightShift(ScriptUtils.getInt(args[1])));
+                });
+        registerConsumer("&=", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).and((Fraction) args[1]));
+                });
+        registerConsumer("^=", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).xor((Fraction) args[1]));
+                });
+        registerConsumer("|=", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).or((Fraction) args[1]));
+                });
         registerFunction("inc", (args, sc) -> 
                 {
                     String s = args[0].toString();
@@ -501,6 +585,7 @@ public class SnuviParser
                     sc.setVar(s, n);
                     return n;
                 });
+        registerAlias("++", "inc");
         registerFunction("dec", (args, sc) -> 
                 {
                     String s = args[0].toString();
@@ -508,28 +593,32 @@ public class SnuviParser
                     sc.setVar(s, n);
                     return n;
                 });
-        registerFunction("postinc", (args, sc) -> 
+        registerAlias("--", "dec");
+        registerFunction("p+", (args, sc) -> 
                 {
                     String s = args[0].toString();
                     Fraction n = (Fraction) sc.getVar(s);
                     sc.setVar(s, n.add(new Fraction(1)));
                     return n;
                 });
-        registerFunction("postdec", (args, sc) -> 
+        registerFunction("p-", (args, sc) -> 
                 {
                     String s = args[0].toString();
                     Fraction n = (Fraction) sc.getVar(s);
                     sc.setVar(s, n.add(new Fraction(-1)));
                     return n;
                 });
-        registerFunction("mul", (args, sc) -> 
+        registerFunction("*", (args, sc) -> 
                 ((Fraction) args[0]).mul((Fraction) args[1]));
-        registerFunction("div", (args, sc) -> 
+        registerAlias("mul", "*");
+        registerFunction("/", (args, sc) -> 
                 ((Fraction) args[0]).div((Fraction) args[1]));
+        registerAlias("div", "/");
         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 +628,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,25 +678,34 @@ 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) -> 
+        registerAlias("equal", "==");
+        registerAlias("equals", "==");
+        registerFunction("<", (args, sc) -> 
                 ((Fraction) args[0]).compareTo((Fraction) args[1]) < 0);
-        registerFunction("greater", (args, sc) -> 
+        registerAlias("less", "<");
+        registerFunction(">", (args, sc) -> 
                 ((Fraction) args[0]).compareTo((Fraction) args[1]) > 0);
-        registerFunction("notequal", (args, sc) -> 
+        registerAlias("greater", ">");
+        registerFunction("!=", (args, sc) -> 
                 !isEqual(args));
-        registerFunction("lessequal", (args, sc) -> 
+        registerAlias("notequal", "!=");
+        registerFunction("<=", (args, sc) -> 
                 ((Fraction) args[0]).compareTo((Fraction) args[1]) <= 0);
-        registerFunction("greaterequal", (args, sc) -> 
+        registerAlias("lessequal", "<=");
+        registerFunction(">=", (args, sc) -> 
                 ((Fraction) args[0]).compareTo((Fraction) args[1]) >= 0);
-        registerFunction("invert", (args, sc) -> 
+        registerAlias("greaterequal", ">=");
+        registerFunction("!", (args, sc) -> 
                 !((boolean) args[0]));
-        registerFunction("and", (args, sc) -> 
+        registerAlias("invert", "!");
+        registerFunction("&&", (args, sc) -> 
                 Arrays.stream(args).allMatch(s -> s.equals(true)));
-        registerFunction("or", (args, sc) -> 
+        registerAlias("and", "&&");
+        registerFunction("||", (args, sc) -> 
                 Arrays.stream(args).anyMatch(s -> s.equals(true)));
+        registerAlias("or", "||");
         registerConsumer("waitfor", (args, sc) ->     
                 waitFor(args, sc));
         registerConsumer("term", (args, sc) -> 
@@ -620,6 +718,14 @@ public class SnuviParser
                     sc.setVar(first, sc.getVar(sec));
                     sc.setVar(sec, helper);
                 });
+        registerFunction("islong", (args, sc) ->                                           
+                {
+                    if(args[0] instanceof Fraction)
+                    {
+                        return ((Fraction) args[0]).isLong();
+                    }
+                    return false;
+                });
     }
     
     @SuppressWarnings("unchecked")
@@ -758,6 +864,7 @@ public class SnuviParser
         }
     }
     
+    @SuppressWarnings(value = "unchecked")
     public <T extends Script> T startScript(Class<T> c, String scriptName, String code, boolean b, Object... o)
     { 
         try
@@ -898,7 +1005,7 @@ public class SnuviParser
             }
             try
             {
-                sc.gotoLabel(args[1].toString(), true);
+                sc.gotoLabel(args[1].toString(), true, true);
                 sc.runCode();
             }
             catch(Exception ex)
@@ -962,6 +1069,7 @@ public class SnuviParser
         }
     }
     
+    @SuppressWarnings(value = "unchecked")
     private void writeFile(Object[] args, Script sc)
     {
         try
@@ -982,7 +1090,8 @@ public class SnuviParser
                     throw new FileIOException(ex.getMessage());
                 }
             }
-            Files.write(Paths.get(f.toURI()), (List) args[1], StandardCharsets.UTF_8);
+            Files.write(Paths.get(f.toURI()), ((List<Object>) args[1])
+                    .stream().map(o -> String.valueOf(o)).collect(Collectors.toList()), StandardCharsets.UTF_8);
         }
         catch(UnsupportedOperationException | SecurityException | IOException ex)
         {

+ 5 - 1
src/main/java/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;
@@ -190,6 +189,11 @@ public class SnuviConfig
         return get(key, Fraction.class, Fraction.fromDouble(error)).intValue();
     }
     
+    public final Fraction getFraction(String key, Fraction error)
+    {
+        return get(key, Fraction.class, error);
+    }
+    
     public final boolean getBoolean(String key, boolean error)
     {
         return get(key, Boolean.class, error);

+ 35 - 43
src/main/java/me/hammerle/math/Fraction.java

@@ -286,6 +286,11 @@ public final class Fraction extends Number implements Comparable<Fraction>
         return numerator < 0;
     }
     
+    public boolean isLong()
+    {
+        return denominator == 1;
+    }
+    
     // -------------------------------------------------------------------------
     // functions from math library
     // -------------------------------------------------------------------------
@@ -598,81 +603,68 @@ public final class Fraction extends Number implements Comparable<Fraction>
     // bit stuff
     // -------------------------------------------------------------------------
     
-    public Fraction rightShiftNumerator(int times)
-    {
-        return new Fraction(numerator >> times, denominator);
-    }
-    
-    public Fraction rightShiftDenominator(int times)
+    private void noFraction()
     {
-        return new Fraction(numerator, denominator >> times);
+        if(denominator != 1 && numerator != 0)
+        {
+            throw new UnsupportedOperationException("the number must not be a fraction");
+        }
     }
     
-    public Fraction leftShiftNumerator(int times)
+    public Fraction rightShift(int times)
     {
-        return new Fraction(numerator << times, denominator);
+        noFraction();
+        return new Fraction(numerator >> times);
     }
     
-    public Fraction leftShiftDenominator(int times)
+    public Fraction leftShift(int times)
     {
-        return new Fraction(numerator, denominator << times);
+        noFraction();
+        return new Fraction(numerator << times);
     }
     
     public Fraction and(Fraction f)
     {
-        return new Fraction(numerator & f.numerator, denominator & f.denominator);
+        noFraction();
+        return new Fraction(numerator & f.numerator);
     }
     
     public Fraction or(Fraction f)
     {
-        return new Fraction(numerator | f.numerator, denominator | f.denominator);
+        noFraction();
+        return new Fraction(numerator | f.numerator);
     }
     
     public Fraction xor(Fraction f)
     {
-        return new Fraction(numerator ^ f.numerator, denominator ^ f.denominator);
-    }
-    
-    public Fraction invertNumerator()
-    {
-        return new Fraction(~numerator, denominator);
+        noFraction();
+        return new Fraction(numerator ^ f.numerator);
     }
     
-    public Fraction invertDenominator()
+    public Fraction invertBits()
     {
-        return new Fraction(numerator, ~denominator);
+        noFraction();
+        return new Fraction(~numerator);
     }
-    
-    public Fraction setNumeratorBit(int n)
-    {
-        return new Fraction(numerator | 1 << n, denominator);
-    }
-    
-    public Fraction setDenominatorBit(int n)
-    {
-        return new Fraction(numerator, denominator | 1 << n);
-    }
-    
-    public Fraction unsetNumeratorBit(int n)
+
+    public Fraction setBit(int n)
     {
-        return new Fraction(numerator & ~(1 << n), denominator);
+        noFraction();
+        return new Fraction(numerator | 1 << n);
     }
     
-    public Fraction unsetDenominatorBit(int n)
+    public Fraction unsetBit(int n)
     {
-        return new Fraction(numerator, denominator & ~(1 << n));
-    }
+        noFraction();
+        return new Fraction(numerator & ~(1 << n));
+    }   
     
-    public boolean getNumeratorBit(int n)
+    public boolean getBit(int n)
     {
+        noFraction();
         return (numerator & (1 << n)) != 0;
     }
     
-    public boolean getDenominatorBit(int n)
-    {
-        return (denominator & (1 << n)) != 0;
-    }
-    
     // -------------------------------------------------------------------------
     // number stuff
     // ------------------------------------------------------------------------- 

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

@@ -0,0 +1,102 @@
+package me.hammerle.code;
+
+public enum Syntax
+{
+    UNKNOWN(" ", 0),
+    OPEN_BRACKET("(", 1, (byte) 2),
+    CLOSE_BRACKET(")", 1, (byte) 1),
+    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;
+    }
+
+    public boolean shouldEndLayer()
+    {
+        return status == 2;
+    }
+    
+    public boolean isFunction()
+    {
+        return status >= 0;
+    }
+
+    public boolean isIncOrDec()
+    {
+        return status == 5;
+    }
+    
+    public byte getParameters()
+    {
+        return pars;
+    }
+}

+ 76 - 0
src/me/hammerle/snuviscript/SnuviScript.java

@@ -0,0 +1,76 @@
+package me.hammerle.snuviscript;
+
+import me.hammerle.code.ISnuviLogger;
+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 
+{
+    public static void main(String[] args) 
+    {
+        ISnuviLogger logger = new ISnuviLogger() 
+        {
+            @Override
+            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);
+            }
+
+            @Override
+            public void printException(Exception ex, String function, String s, int line) 
+            {
+                System.out.println("Exception " + ex);
+                System.out.println("function " + function);
+                System.out.println("Line: " + line);
+            }
+
+            @Override
+            public void printWarning(String s) 
+            {
+                System.out.println("Warning: " + s);
+            }
+
+            @Override
+            public void printInfo(String s) 
+            {
+                System.out.println("Info: " + s);
+            }
+        };
+        
+        SnuviParser parser = new SnuviParser(logger, new ISnuviScheduler() 
+        {
+            @Override
+            public int scheduleTask(Runnable r) 
+            {
+                System.out.println("Schedule");
+                return 0;
+            }
+
+            @Override
+            public int scheduleTask(Runnable r, long delay) 
+            {
+                System.out.println("Schedule");
+                return 0;
+            }
+        });
+        parser.registerConsumer("print", (o, sc) -> System.out.println(o[0]));
+        parser.registerFunction("get", (o, sc) -> new Fraction(1));
+            
+        String s = "print(5*(-3));";
+        System.out.println(s);
+        System.out.println();
+        try
+        {
+            parser.startScript("test", s);
+        }
+        catch(PreScriptException ex)
+        {
+            logger.printException(ex, "none" , "test", ex.getLine());
+        }
+    }   
+}

+ 0 - 21
start.snuvi

@@ -1,21 +0,0 @@
-x = 0;
-while(x < 256)
-{
-    print(read.color(0,0,x), "■■■■■■■■■■■");
-    x += 1;
-    reset();
-}
-wait();
-
-/*size = 500;
-g.new(size, size);
-x = 0;
-
-while(x < 256)
-{
-    g.newRectangle(x, read.color(0,0,x), x * 2, 0, x * 2 + 1, size);
-    x += 1;
-    reset();
-}
-g.repaint();
-wait();*/

+ 0 - 1
test.snuvic

@@ -1 +0,0 @@
-f=1.23

+ 0 - 3
testfile.snuvic

@@ -1,3 +0,0 @@
-number=4
-test=true
-text="Das ist ein Text"