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;
}
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++;
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;
}
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;
}
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));
}
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));
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);
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;
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));
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;
+ }
}
-// 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"