Browse Source

Fertigstellung von While, Implementierung von Syntax anstatt Funktionen: +,-,*,/,^,%,=,+=,-=,/=,*=,==,<,>,!=,<=,>=

Kajetan Johannes Hammerle 8 years ago
parent
commit
d66988161a

+ 2 - 0
nbproject/private/private.xml

@@ -3,6 +3,8 @@
     <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>
+            <file>file:/Users/kajetanjohannes/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/CodeParser.java</file>
+            <file>file:/Users/kajetanjohannes/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/Code.java</file>
             <file>file:/Users/kajetanjohannes/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/Script.java</file>
         </group>
     </open-files>

+ 335 - 17
src/me/hammerle/code/Code.java

@@ -1,14 +1,14 @@
 package me.hammerle.code;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Stack;
+import java.util.TreeSet;
 
 public class Code implements Comparable<Code>
 {
     private final int line;
-    private final int subline;
+    private int subline;
     
     private final String function;
     private final int level;
@@ -32,7 +32,7 @@ public class Code implements Comparable<Code>
         this.line = line;
         this.subline = subline;
         this.value = value;
-        this.jump = 0;
+        this.jump = jump;
     }
     
     public Code(String function, int level, int pars, int line, int subline)
@@ -93,6 +93,8 @@ public class Code implements Comparable<Code>
         }
         sb.append(" (");
         sb.append(line);
+        sb.append(",");
+        sb.append(subline);
         sb.append(") ");
         
         if(value != null)
@@ -177,15 +179,283 @@ public class Code implements Comparable<Code>
         return start;
     }
     
+    private static int findStartOfSyntax(String code, int pos)
+    {
+        int bracketCounter = 0;
+        char c;
+        boolean text = false;
+        while(code.charAt(pos) == ' ')
+        {
+            pos--;
+        }
+        while(pos >= 0)
+        {
+            c = code.charAt(pos);
+            if(text && c != '"')
+            {
+                pos--;
+                continue;
+            }
+            switch(c)
+            {
+                case ';':
+                case '{':
+                case '}':
+                case ' ':
+                case '+':
+                case '-':
+                case '*':
+                case '/':
+                case '^':
+                case '=':
+                    if(bracketCounter != 0)
+                    {
+                        break;
+                    }
+                    return pos + 1;
+                case '"':
+                    text = !text;
+                    break;
+                case ')':
+                    bracketCounter++;
+                    break;
+                case '(':
+                    if(bracketCounter == 0)
+                    {
+                        return pos + 1;
+                    }
+                    bracketCounter--;
+                    break;
+            }
+            pos--;
+        }
+        return 0;
+    }
+    
+    private static int findEndOfSyntax(String code, int pos)
+    {
+        int bracketCounter = 0;
+        char c;
+        boolean text = false;
+        while(code.charAt(pos) == ' ')
+        {
+            pos++;
+        }
+        while(pos < code.length())
+        {
+            c = code.charAt(pos);
+            if(text && c != '"')
+            {
+                pos++;
+                continue;
+            }
+            switch(c)
+            {
+                case ';':
+                case '{':
+                case '}':
+                case ' ':
+                case '+':
+                case '-':
+                case '*':
+                case '/':
+                case '^':
+                case '=':
+                    case '%':
+                    if(bracketCounter != 0)
+                    {
+                        break;
+                    }
+                    return pos;
+                case '"':
+                    text = !text;
+                    break;
+                case '(':
+                    bracketCounter++;
+                    break;
+                case ')':
+                    if(bracketCounter == 0)
+                    {
+                        return pos;
+                    }
+                    bracketCounter--;
+                    break;
+            }
+            pos++;
+        }
+        return code.length();
+    }
+    
+    private static int findSyntax(String find, String code, int pos)
+    {
+        int length = code.length();
+        char c;
+        boolean text = false;
+        String s;
+        while(pos < length)
+        {
+            c = code.charAt(pos);
+            if(text && c != '"')
+            {
+                pos++;
+                continue;
+            }
+            if(c == '"')
+            {
+                text = !text;
+                pos++;
+                continue;
+            }
+            s = code.substring(pos);
+            if(s.startsWith(find) && !s.startsWith(find + "=") && code.charAt(pos - 1) != '=')
+            {
+                return pos;
+            }
+            pos++;
+        }
+        return -1;
+    }
+    
+    private static String changeBiSyntax(String syntax, String f, String code, boolean b)
+    {
+        int pos = -1;
+        int end;
+        int start;
+        int slength = syntax.length();
+        StringBuilder sb = new StringBuilder(code);
+        StringBuilder newSyntax;
+        while(pos < sb.length())
+        {
+            pos = findSyntax(syntax, sb.toString(), pos + 1);
+            if(pos == -1)
+            {
+                break;
+            }
+            start = findStartOfSyntax(sb.toString(), pos - 1);
+            end = findEndOfSyntax(sb.toString(), pos + slength);
+            newSyntax = new StringBuilder(f);
+            newSyntax.append("(");
+            if(b)
+            {
+                newSyntax.append("\"");
+            }
+            newSyntax.append(sb.substring(start, pos).trim());
+            if(b)
+            {
+                newSyntax.append("\"");
+            }
+            if(end > pos)
+            {
+                newSyntax.append(",");
+                newSyntax.append(sb.substring(pos + slength, end).trim());
+            }
+            newSyntax.append(")");
+            sb.replace(start, end, newSyntax.toString());
+        }
+        return sb.toString();
+    }
+    
+    private static String changeUnSyntax(String syntax, String f, String code)
+    {
+        int pos = -1;
+        int end;
+        int start;
+        int slength = syntax.length();
+        String first;
+        StringBuilder sb = new StringBuilder(code);
+        StringBuilder newSyntax;
+        while(pos < sb.length())
+        {
+            pos = findSyntax(syntax, sb.toString(), pos + 1);
+            if(pos == -1)
+            {
+                break;
+            }
+            start = findStartOfSyntax(sb.toString(), pos - 1);
+            end = findEndOfSyntax(sb.toString(), pos + slength);
+            newSyntax = new StringBuilder("setvar(\"");
+            first = sb.substring(start, pos).trim();
+            newSyntax.append(first);
+            newSyntax.append("\",");
+            newSyntax.append(f);
+            newSyntax.append("(");
+            newSyntax.append(first);
+            newSyntax.append(",");
+            newSyntax.append(sb.substring(pos + slength, end).trim());
+            newSyntax.append("))");
+            sb.replace(start, end, newSyntax.toString());
+        }
+        return sb.toString();
+    }
+    
+    private static String replaceChar(char find, char replacement, String code)
+    {
+        char[] chars = code.toCharArray();
+        int length = code.length();
+        char c;
+        boolean text = false;
+        int pos = 0;
+        while(pos < length)
+        {
+            c = code.charAt(pos);
+            if(text && c != '"')
+            {
+                pos++;
+                continue;
+            }
+            if(c == '"')
+            {
+                text = !text;
+                pos++;
+                continue;
+            }
+            if(c == find)
+            {
+                chars[pos] = replacement;
+            }
+            pos++;
+        }
+        return new String(chars);
+    }
+    
     public static Code[] generate(String code, HashMap<String, Integer> gotos)
     {
+        // Anfängliches Austauschen mit Functionssyntax
+        code = changeBiSyntax("^", "math.pow", code, false);
+        code = changeBiSyntax("/", "div", code, false);
+        code = changeBiSyntax("%", "math.mod", code, false);
+        code = changeBiSyntax("*", "mul", code, false);
+        code = changeBiSyntax("-", "sub", code, false);
+        code = changeBiSyntax("+", "add", code, false);
+        
+        code = changeBiSyntax("==", "equal", code, false);
+        code = changeBiSyntax("!=", "notequal", code, false);
+        code = changeBiSyntax("<", "less", code, false);
+        code = changeBiSyntax(">", "greater", code, false);
+        code = changeBiSyntax(">=", "greaterequal", code, false);
+        code = changeBiSyntax("<=", "lessequal", code, false);
+        
+        code = changeUnSyntax("+=", "add", code);
+        code = changeUnSyntax("-=", "add", code);
+        code = changeUnSyntax("/=", "add", code);
+        code = changeUnSyntax("*=", "add", code);
+        
+        code = changeBiSyntax("=", "setvar", code, true);
+        
+        //code = replaceChar('[', '(', code);
+        //code = replaceChar(']', ')', code);
+        
+        System.out.println(code);
+        //System.exit(0);
+        // Ende des Austauschen
+        // Zerlegen des Codes in Zeilen
         ArrayList<Code> list = new ArrayList<>();
         sublines = 0;
         String actual;
         int length = code.length();
         int level = 1;
-        int pos = 0;
         int old;
+        int pos = 0;
         int line = 0;
         while(pos < length)
         {
@@ -215,13 +485,53 @@ public class Code implements Comparable<Code>
             }
             pos++;
         }
-        Collections.sort(list);
+        // Ende der Zeilenzerlegung
         
+        // Anlegen eines Trees zum sortieren und einfügen von Code
+        TreeSet<Code> tree = new TreeSet(list);
+        Code[] helper = tree.toArray(new Code[tree.size()]);
+        
+        // Einfügen von "gotoline" bei while-Schleifen
         String function;
         int baseLevel;
-        for(int i = 0; i < list.size(); i++)
+        for(int i = 0; i < helper.length; i++)
         {
-            function = list.get(i).function;
+            function = helper[i].function;
+            if(function == null || !function.equals("while"))
+            {
+                continue;
+            }
+            baseLevel = helper[i].level;
+            for(int j = i + 1; j < helper.length; j++)
+            {
+                if(helper[j].level <= baseLevel)
+                {
+                    helper[i].jump = j - i + 1;
+                    Code c = new Code("gotoline", helper[i].level, 0, helper[j].line, helper[j].subline + 1);
+                    while(tree.contains(c)) // Damit keine Whiles, die gleich enden, sich überschreiben
+                    {
+                        c.subline++;
+                    }
+                    tree.add(c);
+                    break;
+                }
+            }
+        }
+        // Ende des While-Handlings
+        // Erstellen der Sprungmarken der Schlüsselwörter
+        helper = tree.toArray(new Code[tree.size()]);
+        
+        boolean whileCheck = false;
+        int lastLineChange = 0;
+        line = 0;
+        for(int i = 0; i < helper.length; i++)
+        {
+            function = helper[i].function;
+            if(helper[i].line != line)
+            {
+                line = helper[i].line;
+                lastLineChange = i;
+            }
             if(function == null)
             {
                 continue;
@@ -230,32 +540,40 @@ public class Code implements Comparable<Code>
             {
                 case "if":
                 case "else":
-                case "while":
                 case "try":
                 case "catch":
                     break;
+                case "while":
+                    whileCheck = true;
+                    break;
                 default:
                     continue;
             }
-            baseLevel = list.get(i).level;
-            for(int j = i + 1; j < list.size(); j++)
+            baseLevel = helper[i].level;
+            for(int j = i + 1; j < helper.length; j++)
             {
-                if(list.get(j).level == baseLevel)
+                if(helper[j].level <= baseLevel)
                 {
-                    list.get(i).jump = j - i;
+                    helper[i].jump = j - i;
+                    if(whileCheck)
+                    {
+                        whileCheck = false;
+                        helper[j].jump = lastLineChange - j;
+                    }
                     break;
                 }
             }
-            if(list.get(i).jump == 0)
+            if(helper[i].jump == 0)
             {
-               list.get(i).jump = list.size() - i; 
+               helper[i].jump = list.size() - i; 
             }
         }
+        // Ende
         
-        //list.forEach(c -> System.out.println(c.toString()));
+        //tree.stream().forEach(c -> System.out.println(c.toString()));
         //gotos.forEach((k, v) -> System.out.println(k + "   " + v));
         //System.exit(0);
-        return list.toArray(new Code[list.size()]);
+        return tree.toArray(new Code[list.size()]);
     } 
     
     private static int findOpenBracket(String code, int pos)
@@ -391,7 +709,7 @@ public class Code implements Comparable<Code>
         }
         splitted.forEach(s -> splitFunctions(list, s, level, line));
     }
-     
+    
     public static Object convertInput(String s)
     {
         if(s == null)

+ 6 - 2
src/me/hammerle/code/CodeParser.java

@@ -48,6 +48,8 @@ public class CodeParser
     {
         registerFunction("nothing", (args, sc) -> 
                 0);
+        registerFunction("", (args, sc) -> 
+                args[0]);
         
         // -------------------------------------------------------------    
         // Script-Consolen-Bibliothek 
@@ -103,7 +105,7 @@ public class CodeParser
         registerFunction("math.log", (args, sc) -> 
                 Math.log10((double) args[0]));
         registerFunction("math.random", (args, sc) -> 
-                ScriptUtils.randomInt(getInt(args[0]), getInt(args[1])));
+                (double) ScriptUtils.randomInt(getInt(args[0]), getInt(args[1])));
         registerFunction("math.round", (args, sc) -> 
                 Math.round((double) args[0]));
         registerFunction("math.rounddown", (args, sc) -> 
@@ -230,6 +232,8 @@ public class CodeParser
                 { sc.resetLoopCounter(); throw new HoldCodeException(); });
         registerConsumer("goto", (args, sc) -> 
                 sc.gotoLabel(args[0].toString()));
+        registerConsumer("gotoline", (args, sc) -> 
+                { sc.gotoSpecialJumpLine(); sc.incLoopCounter();});
         registerConsumer("sgoto", (args, sc) -> 
                 scheduleGoto(args, sc));
         registerConsumer("gosub", (args, sc) -> 
@@ -279,7 +283,7 @@ public class CodeParser
                 waitFor(args, sc));
     }
     
-    public static boolean printStack = false;
+    public static boolean printStack = true;
 
     @SuppressWarnings("unchecked")
     public static Object parseFunction(Script sc, String function, Object[] args) throws HoldCodeException

+ 20 - 8
src/me/hammerle/code/Script.java

@@ -5,6 +5,7 @@ import java.util.HashSet;
 import java.util.Stack;
 import me.hammerle.exceptions.CodeTooLongException;
 import me.hammerle.exceptions.GotoLabelNotFoundException;
+import me.hammerle.exceptions.HoldCodeException;
 
 public class Script 
 {
@@ -127,8 +128,10 @@ public class Script
             }
             catch(Exception ex)
             {
-                //ex.printStackTrace();
-                // Nothing to do here, Exception wird für Benutzer ausgegeben
+                if(ex.getClass() != HoldCodeException.class)
+                {
+                    CodeParser.printQuestException(this, ex, code[position].toString());
+                }
             }
         }
     }
@@ -156,17 +159,22 @@ public class Script
     // Goto, Return
     // -----------------------------------------------------------------------------------
     
+    public void incLoopCounter()
+    {
+        loopCounter++;
+        if(loopCounter > 50)
+        {
+            resetLoopCounter();
+            throw new CodeTooLongException();
+        }
+    }
+    
     public void gotoLabel(String label)
     {
         try
         {
             int i = gotos.get(label);
-            loopCounter++;
-            if(loopCounter > 50)
-            {
-                resetLoopCounter();
-                throw new CodeTooLongException();
-            }
+            incLoopCounter();
             position = i - 1;
         }
         catch(NullPointerException ex)
@@ -198,6 +206,10 @@ public class Script
     
     public void jumpNextIfElse()
     {
+        if(code.length <= position + 1)
+        {
+            return;
+        }
         String s = code[position + 1].getFunction();
         if(s == null || !s.equals("else"))
         {

+ 12 - 2
src/me/hammerle/console/BlackBox.java

@@ -35,7 +35,7 @@ public class BlackBox extends JScrollPane
         doc = area.getStyledDocument();
     }
     
-    public void append(String s, Color c)
+    public void insert(String s, Color c, int pos)
     {
         Style style = null;
         if(c != null)
@@ -49,7 +49,7 @@ public class BlackBox extends JScrollPane
         }
         try 
         {
-            doc.insertString(doc.getLength(), s, style);
+            doc.insertString(pos, s, style);
         } 
         catch (BadLocationException ex) 
         {
@@ -57,6 +57,16 @@ public class BlackBox extends JScrollPane
         scrollToBottom();
     }
     
+    public void append(String s, Color c)
+    {
+        insert(s, c, doc.getLength());
+    }
+    
+    public void insertAtCaret(String s, Color c)
+    {
+        insert(s, c, area.getCaretPosition());
+    }
+    
     protected void scrollToBottom()
     {
         JScrollBar v = this.getVerticalScrollBar();

+ 1 - 1
src/me/hammerle/console/InputBox.java

@@ -19,7 +19,7 @@ public class InputBox extends BlackBox
                 {
                     if(e.isShiftDown())
                     {
-                        append("\n", null);
+                        insertAtCaret("\n", null);
                         e.consume();
                     }
                     else