updates to fleet grammar
authoradam <adam@megacz.com>
Tue, 28 Aug 2007 00:24:03 +0000 (01:24 +0100)
committeradam <adam@megacz.com>
Tue, 28 Aug 2007 00:24:03 +0000 (01:24 +0100)
src/edu/berkeley/fleet/assembler/Parser.java
src/edu/berkeley/fleet/assembler/fleet.g

index 28d3520..f59f03c 100644 (file)
@@ -40,9 +40,11 @@ public class Parser {
         if (grammar != null) return grammar;
         InputStream grammarStream =
             Parser.class.getClassLoader().getResourceAsStream("edu/berkeley/fleet/assembler/fleet.g");
-        CharParser metaGrammarParser   = new CharParser(MetaGrammar.newInstance());
+        CharParser metaGrammarParser   = new CharParser(GrammarAST.getMetaGrammar());
         Tree<String> parsedGrammar     = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
-        grammar                        = GrammarAST.buildFromAST(parsedGrammar, "s", new File[0]);
+        grammar                        = GrammarAST.buildFromAST(parsedGrammar, "s", new GrammarAST.ImportResolver() {
+                public InputStream getImportStream(String importname) { return null; }
+            });
         return grammar;
     }
 
@@ -89,7 +91,6 @@ public class Parser {
                     inst = new Instruction.CodeBagDescriptor(old.pump,
                                                                      offset,
                                                                      codeBags.get((int)old.offset).size());
-                    //System.out.println("cbd: " + offset + " " + codeBags.get((int)old.offset).size() + " " + codeBags.get((int)old.offset).name + " " + codeBags.get((int)old.offset));
                 }
                 fleet.writeInstruction(dos, inst);
                 count++;
@@ -112,10 +113,10 @@ public class Parser {
                 for(Tree<String> statement : t.child(1))
                     fillCodeBag(statement, cb);
    
-        } else if (head.equals("Import")) {
+        } else if (head.equals("#import")) {
             // ignored
 
-        } else if (head.equals("Ship")) {
+        } else if (head.equals("#ship")) {
             String name = name(t.child(0));
             String type = string(t.child(1));
             Ship ship = null;
@@ -130,16 +131,16 @@ public class Parser {
             }
             shipMap.put(name, ship);
 
-        } else if (head.equals("Include")) {
+        } else if (head.equals("#include")) {
             try {
                 walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))), cb);
             } catch (Exception e) {
                 throw new RuntimeException(e);
             }
             
-        } else if (head.equals("Expect")) {
-            expect.add(Long.parseLong(string(t.child(0))));
-        } else if (head.equals("Skip")) {
+        } else if (head.equals("#expect")) {
+            expect.add(number(t.child(0)));
+        } else if (head.equals("#skip")) {
             skip = true;
 
         }
@@ -153,12 +154,19 @@ public class Parser {
         return ret;
     }
 
+    String stringBody(Tree<String> t) {
+        String ret = "";
+        for(Tree<String> c : t)
+            ret += string(c);
+        return ret;
+    }
+
     String name(Tree<String> t) {
         return string(t.child(0))+string(t.child(1));
     }
 
     Destination portReference(Tree<String> t) {
-        if (!"Port".equals(t.head()) && !"SubPort".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null;
+        if (!"Pump".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head())) return null;
         String shipName = name(t.child(0));
         String portName = name(t.child(1));
         String subPort = t.size()<3 ? null : name(t.child(2));
@@ -182,7 +190,7 @@ public class Parser {
     }
 
     Pump pump(Tree<String> t) {
-        if (!"Port".equals(t.head()) && !"SubPort".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head()))
+        if (!"Pump".equals(t.head()) && !"Destination".equals(t.head()) && !"ShipSpecificLiteral".equals(t.head()))
             throw new RuntimeException(t+"");
         String shipName = name(t.child(0));
         String portName = name(t.child(1));
@@ -229,14 +237,15 @@ public class Parser {
         long literal = 0;
         for(int i=0; i<specs.size(); i++) {
             Tree tt = specs.child(i);
-            literal |= chosenport.resolveLiteral(string(tt));
+            literal |= chosenport.resolveLiteral(stringBody(tt));
         }
         return literal;
     }
 
+    private int anoncount = 1;
     void fillCodeBag(Tree<String> t, CodeBag cb) {
         if (t.head()==null) return;
-        else if (t.head().equals("NamedCodeBag")) {
+        else if (t.head().equals("CodeBagDef")) {
             CodeBag cb2 = getCodeBag(name(t.child(0)));
             for(Tree<String> statement : t.child(1))
                 fillCodeBag(statement, cb2);
@@ -246,24 +255,61 @@ public class Parser {
             
             OUTER: for(Tree tt : t.child(1)) {
                 int count = 1;
-                Tree ttx = null;
-                boolean requeue = false;
-                ttx = tt.child(1);
-                if (tt.size() > 1 && tt.child(0).size()>0) {
-                    tt = tt.child(0).child(0);
-                    if (tt.head().equals("BrackStar")) {
-                        count = 0;
-                        requeue = false;
-                    } else if (tt.head().equals("ParenStar")) {
+                if ("unclog".equals(tt.head()))    {
+                    cb.add(new Instruction.UnClog(pump));
+                    continue;
+                } else if ("clog".equals(tt.head()))    {
+                    cb.add(new Instruction.Clog(pump));
+                    continue;
+                } else if ("kill".equals(tt.head()))    {
+                    count = tt.size()==0 ? 1 : (int)number(tt.child(0));
+                    cb.add(new Instruction.Kill(pump, count));
+                    continue;
+                } else if ("literal".equals(tt.head()))  {
+                    long literal = 0;
+                    if (tt.child(0).head().equals("CodeBagBody")) {
+                        Tree<String> tq = tt;
+                        CodeBag cb2 = getCodeBag("anon"+(anoncount++));
+                        for(Tree<String> statement : tq.child(0))
+                            fillCodeBag(statement, cb2);
+                        cb.add(new Instruction.CodeBagDescriptor(pump, cb2.getFakeAddress(), 0));
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("Name")) {
+                        String refname = name(tt.child(0));
+                        CodeBag cb2 = getCodeBag(refname);
+                        cb.add(new Instruction.CodeBagDescriptor(pump, cb2.getFakeAddress(), 0));
+                        continue OUTER;
+                    } else if (tt.child(0).head().equals("[")) {
+                        literal = parseSSL(tt.child(0));
+                    } else {
+                        literal = number(tt.child(0));
+                    }
+                    count = 1;
+                    if ("int".equals(tt.child(1).head())) {
+                        count = (int)number(tt.child(1));
+                    } else if ("forever".equals(tt.child(1).head())) {
                         count = 0;
-                        requeue = true;
-                    } else if (tt.head().equals("Brack")) {
-                        count = Integer.parseInt(string(tt.child(0)));
-                        requeue = false;
-                    } else if (tt.head().equals("Paren")) {
-                        count = Integer.parseInt(string(tt.child(0)));
-                        requeue = true;
                     }
+                    cb.add(new Instruction.LocalLiteral(pump, literal, count));
+                    continue;
+                }
+                Tree ttx = null;
+                boolean requeue = false;
+                ttx = tt.child(1).head().equals("Commands") ? tt.child(1) : tt;
+                if ("int".equals(tt.child(2).head())) {
+                    count = (int)number(tt.child(2));
+                    requeue = true;
+                } else if ("forever".equals(tt.child(2).head())) {
+                    count = 0;
+                    requeue = true;
+                }
+                tt = tt.child(0);
+                if (tt.head().equals("[*]")) {
+                    count = 0;
+                    requeue = false;
+                } else if (tt.head().equals("int")) {
+                    count = (int)number(tt);
+                    requeue = false;
                 }
                 boolean tokenIn = false;
                 boolean dataIn = false;
@@ -277,39 +323,21 @@ public class Parser {
                 Destination dest = null;
                 for(int i=0; i<ttx.size(); i++) {
                     Tree ttt = ttx.child(i);
-                    if      ("Wait".equals(ttt.head()))    { tokenIn = true; }
-                    else if ("Nop".equals(ttt.head()))     { }
-                    else if ("KillStar".equals(ttt.head()))    {
-                        cb.add(new Instruction.UnClog(pump));
-                        continue OUTER;
-                    } else if ("Clog".equals(ttt.head()))    {
-                        cb.add(new Instruction.Clog(pump));
-                        continue OUTER;
-                    } else if ("Kill".equals(ttt.head()))    {
+                    if      ("wait".equals(ttt.head()))    { tokenIn = true; }
+                    else if ("nop".equals(ttt.head()))     { }
+                    else if ("kill".equals(ttt.head()))    {
                         cb.add(new Instruction.Kill(pump, count));
                         continue OUTER;
                     }
-                    else if ("Discard".equals(ttt.head())) { dataIn = true; latch = false; }
-                    else if ("Take".equals(ttt.head()))    { dataIn = true; latch = true; }
-                    else if ("SendTo".equals(ttt.head()))  { dataOut = true; dest = portReference(ttt.child(0)); }
-                    else if ("LocalLiteral".equals(ttt.head()))  { localLiteral = true; literal = Long.parseLong(string(ttt.child(0))); }
-                    else if ("LocalLiteralCodeBag".equals(ttt.head()))  {
-                        String refname = name(ttt.child(0).child(0));
-                        CodeBag cb2 = getCodeBag(refname);
-                        cb.add(new Instruction.CodeBagDescriptor(pump, cb2.getFakeAddress(), 0));
-                        continue OUTER;
-                    } else if ("LocalLiteralConst".equals(ttt.head()))  {
-                        localLiteral = true;
-                        literal = parseSSL(ttt.child(0));
-                    }
-                    else if ("DataOutDest".equals(ttt.head()))  { dataOutDest = true; }
-                    else if ("Deliver".equals(ttt.head())) { dataOut = true;  }
-                    else if ("Ack".equals(ttt.head()))     { tokenOut = true; dest = portReference(ttt.child(0)); }
-                    else if ("AckLast".equals(ttt.head()))     { tokenOut = true; ignoreUntilLast = true; dest = portReference(ttt.child(0)); }
+                    else if ("discard".equals(ttt.head())) { dataIn = true; latch = false; }
+                    else if ("take".equals(ttt.head()))    { dataIn = true; latch = true; }
+                    else if ("recieve".equals(ttt.head()))    { dataIn = true; latch = true; }
+                    else if ("send".equals(ttt.head()))  { dataOutDest = true; }
+                    else if ("sendto".equals(ttt.head()))  { dataOut = true; dest = portReference(ttt.child(0)); }
+                    else if ("deliver".equals(ttt.head())) { dataOut = true;  }
+                    else if ("notify".equals(ttt.head()))     { tokenOut = true; dest = portReference(ttt.child(0)); }
+                    else if ("notifyLast".equals(ttt.head()))     { tokenOut = true; ignoreUntilLast = true; dest = portReference(ttt.child(0)); }
                 }
-                if (localLiteral)
-                    cb.add(new Instruction.LocalLiteral(pump, literal, count));
-                else
                     cb.add(new Instruction.Executable(pump,
                                                       dest, count, tokenIn, dataIn,
                                                       latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast));
@@ -330,4 +358,16 @@ public class Parser {
     public static ArrayList<Long> expect;
     public static boolean         skip;
 
+    private static long number(Tree t) {
+        String ret = "";
+        for(Object c : t.child(2)) ret += ((Tree)c).head();
+        boolean negative = "-".equals(t.child(0).head());
+        ret = ret.trim();
+        long val = 0;
+        if      ("0x".equals(t.child(1).head())) val = Long.parseLong(ret, 16);
+        else if ("0b".equals(t.child(1).head())) val = Long.parseLong(ret, 2);
+        else                                     val = Long.parseLong(ret);
+        if (negative) val = -1L * val;
+        return val;
+    }
 }
index 0aeb910..4964224 100644 (file)
@@ -1,76 +1,71 @@
-// The FLEET Assembly Language Grammar
-// Updated 05-Nov-2006
+// The FLEET Assembly Language Grammar [26-Aug-2007]
 
 // Note that this is the *entire, complete* formal specification of
 // the grammar.  An equivalent lex+yacc grammar and support code would
 // be several times as long.
 
-Comment        = "//" ~[\n\r]!* [\r\n]!
-               | "/*" ~[\n\r]!* "*/"
-ws             = ([\r\n ] | Comment)!* -> ~[\r\n ]
+s               = ws Program ws
+Program::       = Directives CodeBagBody /ws
+Directives::    = Directive */ ws
+CodeBagBody::   = (Fiber | CodeBagDef) */ ws
+CodeBagDef::    = CodeBagName ":" "{" CodeBagBody "}" /ws
+Fiber::         = Pump        ":" Instructions        /ws
 
-s               = ws! Program ws!
-Program         = Program:: Directive+/ws
-                | Program:: ("":: Directive+/ws) ws! CodeBagBody
+Instructions::  = Instruction +/ ws
+Instruction     = ^"unclog"                          ";" /ws
+                | ^"clog"                            ";" /ws
+                | ^"kill"                            ";" /ws
+                | ^"kill"     int                    ";" /ws
+                | ^"literal"  Literal  RequeueCount  ";" /ws
+                | RepeatCount Commands RequeueCount ^";" /ws
+RepeatCount     = "" | ^"[*]" | "[" int "]"
+RequeueCount    = ""
+                | "," "requeue" (^"forever" | int ws "times") /ws
 
-Statement       = Fiber::                  Source  ":" ("":: Instruction +/ ws)     /ws
-                | NamedCodeBag::           name    ":" "{" CodeBagBody "}"     /ws
+// FIXME: ordering constraint on these
+Commands::      = Command +/ (ws "," ws)
+Command         = ^"wait"
+                | ^"nop"
+                | ^"discard"
+                | ^"recieve"
+                | ^"take"
+                | ^"deliver"
+                | ^"send"
+                | ^"sendto"     Destination /ws
+                | ^"notify"     Destination /ws
+                | ^"notifyLast" Destination /ws
 
-CountField      = Brack::     "[" int "]"
-                | Paren::     "(" int ")"
-                | BrackStar:: "[*]"
-                | ParenStar:: "(*)"
-Instruction     = Instruction::
-                        ("":: (CountField ws!)?)
-                        ("":: Command +/ (ws! "," ws!) ws! ";"!)
-Command         = Nop::      "nop"
-                | Kill::     "kill"
-                | KillStar:: "unclog"
-                | Clog::     "clog"
-                | Wait::     "wait"
-                | Discard::           "dismiss"
-                | Take::              ("take"|"receive")
-                | SendTo::            "sendto" ws! Port
-                | DataOutDest::       "send"
-                | Deliver::           "deliver"
-                | LocalLiteral::      "literal" ws! int
-                | LocalLiteralConst:: "literal" ws! SSL
-                | LocalLiteralCodeBag:: "literal" ws! CodeBag
-                | Ack::               "notify" ws! Port
-                | AckLast::               "notifyLast" ws! Port
+Literal         = int
+                | ShipType "." PortName ^"[" Constants "]"
+                | CodeBagName
+                | "{" CodeBagBody "}" /ws
 
-Source         = Port
-               | ShipSpecific
+Pump::          = ShipName "." PortName
+Destination::   = ShipName "." PortName
+Constants::     = Constant +/ ","
+Constant::      = [a-zA-Z0-9=_\-]++
 
-SSL            = ShipSpecificLiteral:: shiptype "." portname "[" SSLSpec "]"
-Port           = Port::     shipname "." portname
-               | SubPort::  shipname "." portname "." portname
-               |           ^"()"
+CodeBagName     = UpcaseWord
+ShipType        = UpcaseWord
+ShipName        = DowncaseWord
+PortName        = DowncaseWord
+Word            = UpcaseWord | DowncaseWord
+UpcaseWord      = Name:: [A-Z]    ("":: [A-Za-z0-9_]**)
+DowncaseWord    = Name:: [a-z]    ("":: [A-Za-z0-9_]**)
+int::           = (^"-"|^"") (^"0x"|^"0b"|^"") (digits:: [0-9]++)
 
-SSLSpec::      = SSLElement +/ ","
-SSLElement     = "":: [a-zA-Z0-9=_\-]++
+ws!             = wsx -> ~[\r\n ]
+wsx!            = ()
+                | wsx [\r\n ]
+                | wsx Comment
+Comment!        = "//" ~[\n\r]* [\r\n]
+                | "/*" ~[\n\r]* "*/"
 
-CodeBagBody::  = Statement +/ ws
-CodeBag        = CodeBagRef:: CodeBagName
-               | AnonymousCodeBag:: "{" CodeBagBody "}" /ws
-
-CodeBagName         = name
-shipname            = name
-shiptype            = Name:: [A-Z]    ("":: [A-Za-z0-9_]**)
-ShipSpecificLiteral = Name:: [A-Z]    ("":: [A-Z0-9_]**)
-portname            = Name:: [a-z]    ("":: [A-Za-z0-9_]**)
-name                = Name:: [A-Za-z] ("":: [A-Za-z0-9_]**)
-index               = "[" ("":: [0-9]+) "]" | ("":: [0-9]+)
-int                 = "":: [\-0-9]++
-ShipSpecific        = ShipSpecific:: "\"" (~[\"])++ "\""
-
-// the following are not part of the official FLEET syntax and are
-// specific to Adam's interpreter.
-
-Directive      =           "#memory" "{" (Memory:: int +/ (ws! "," ws!)) "}" /ws
-               | Import::  "#import" [A-Za-z_.]++ /ws
-               | Include:: "#include" ws! "\"" ~[\"]+ "\""
-               | Ship::    "#ship" shipname ":" ("":: [0-9A-Za-z_.]++) /ws
-               | Expect::  "#expect" int /ws
-               | Skip::    "#skip"
+// the following extensions are not part of the official FLEET syntax
 
+Directive      = ^"#memory" "{" (Memory:: int +/ (ws! "," ws!)) "}" /ws
+               | ^"#import" [A-Za-z_.]++ /ws
+               | ^"#include" ws! "\"" ~[\"]+ "\""
+               | ^"#ship" ShipName ":" ("":: [0-9A-Za-z_.]++) /ws
+               | ^"#expect" int /ws
+               | ^"#skip"