1e320595bd5779d0a99802ce4ed670b20cbfefa3
[fleet.git] / src / edu / berkeley / fleet / FleetParser.java
1 package edu.berkeley.fleet;
2
3 import edu.berkeley.sbp.*;
4 import edu.berkeley.sbp.chr.*;
5 import edu.berkeley.sbp.misc.*;
6 import edu.berkeley.sbp.meta.*;
7 import edu.berkeley.sbp.bind.*;
8 import edu.berkeley.sbp.util.*;
9 import java.util.*;
10 import java.io.*;
11 import static edu.berkeley.fleet.Instruction.IgnoreCopyTake.*;
12
13 /**
14  *  @author Adam Megacz <megacz@cs.berkeley.edu>
15  *  @author Thomas Kho <tkho@eecs.berkeley.edu>
16  */
17 public class FleetParser {
18
19     public static void main(String[] s) throws Exception {
20         for(int i=0; i<s.length; i++) {
21             if (s[i].startsWith("--color=")) {
22                 String val = s[i].substring(s[i].indexOf('=')+1);
23                 if (val.equals("on")) {
24                     Log.ansi_color = true;
25                     continue;
26                 } else if (val.equals("off")) {
27                     Log.ansi_color = false;
28                     continue;
29                 }
30             } else if (s[i].startsWith("--inboxes=")) {
31                 String val = s[i].substring(s[i].indexOf('=')+1);
32                 if (val.equals("configured")) {
33                     DataInbox.defaultInstruction =
34                         new Instruction(null, null, Integer.MAX_VALUE, TAKE, false, false, true);
35                     continue;
36                 } else if (val.equals("unconfigured")) {
37                     DataInbox.defaultInstruction = null;
38                     continue;
39                 }
40             } else if (s[i].startsWith("--memory=")) {
41                 String val = s[i].substring(s[i].indexOf('=')+1);
42                 if (val.equals("hide")) {
43                     debugMemory = false;
44                     continue;
45                 } else if (val.equals("show")) {
46                     debugMemory = true;
47                     continue;
48                 }
49             }
50             System.out.println("Fleeterpreter usage:");
51             System.out.println("");
52             System.out.println("  --color={on|off}");
53             System.out.println("  --inboxes={configured|unconfigured}");
54             System.out.println("  --memory={hide|show}");
55             System.exit(-1);
56         }
57         go(new InputStreamReader(System.in));
58     }
59
60     public static void go(Reader r) throws Exception {
61         Fleet fleet = new Fleet();
62         FleetParser fp = new FleetParser(fleet);
63         fp.walk((Tree<String>)parse(r));
64         fp.done();
65     }
66
67     public static Tree<String> parse(Reader r) throws Exception {
68         InputStream grammarStream =
69             FleetParser.class.getClassLoader().getResourceAsStream("fleet.g");
70         Parser metaGrammarParser   = new CharParser(MetaGrammar.newInstance());
71         Tree<String> parsedGrammar = metaGrammarParser.parse(new CharInput(grammarStream)).expand1();
72         Union   grammar            = Grammar.create(parsedGrammar, "s", new Grammar.Bindings() { });
73         Parser  parser             = new CharParser(grammar);
74         Tree tree = parser.parse(new CharInput(r)).expand1();
75         return tree;
76     }
77
78     private Fleet fleet;
79     private ArrayList<String> imports = new ArrayList<String>();
80     private CodeBag rootCodeBag;
81     private static boolean debugMemory = true;
82
83     public FleetParser(Fleet fleet) {
84         this.fleet = fleet;
85     }
86
87     public void done() {
88         if (rootCodeBag != null) {
89             if (debugMemory) { fleet.dumpMem(); }
90             System.out.println(rootCodeBag);
91             rootCodeBag.dispatch(fleet);
92             fleet.go();
93             if (debugMemory) { fleet.dumpMem(); }
94         }
95     }
96
97     public void walk(Tree<String> t) {
98         String head = t.head();
99         if (head==null) {
100         } else if (head.equals("Program")) {
101             for(Tree<String> tc : t.child(0))
102                 walk(tc);
103             CodeBag cb = new CodeBag(null, null);
104             if (t.size()>1)
105                 for(Tree<String> statement : t.child(1))
106                     fillCodeBag(statement, cb);
107             rootCodeBag = cb;
108    
109         } else if (head.equals("Import")) {
110             imports.add(string(t.child(0)));
111
112         } else if (head.equals("Ship")) {
113             String name = name(t.child(0));
114             String classname = string(t.child(1));
115             boolean good = false;
116             for(String s : imports)
117                 if (fleet.tryCreate(s+"."+classname, name)) {
118                     good = true;
119                     break;
120                 }
121             if (!good)
122                 throw new RuntimeException("couldn't find a ship called \""+classname+"\"");
123
124         } else if (head.equals("Include")) {
125             try {
126                 walk(parse(new InputStreamReader(new FileInputStream(string(t.child(0))))));
127             } catch (Exception e) {
128                 throw new RuntimeException(e);
129             }
130             
131         } else if (head.equals("Memory")) {
132             if (fleet.mem.length != 0)
133                 throw new RuntimeException("multiple memory directives found");
134             Tree<String> m = t.child(0);
135             int[] mem = new int[m.size()];
136             for(int i=0; i<mem.length; i++)
137                 mem[i] = Integer.parseInt(string(m.child(i)));
138             fleet.mem = mem;
139         }
140     }
141
142     public String string(Tree<String> t) {
143         String ret = "";
144         if (t.head() != null) ret += t.head();
145         for(Tree<String> c : t)
146             ret += string(c);
147         return ret;
148     }
149
150     public String name(Tree<String> t) {
151         return string(t.child(0))+string(t.child(1));
152     }
153
154     public PortReference portReference(Tree<String> t) {
155         if (!"Port".equals(t.head())) return null;
156         return new PortReference(name(t.child(0)), name(t.child(1)));
157     }
158
159     public void fillCodeBag(Tree<String> t, CodeBag cb) {
160         if (t.head()==null) return;
161         else if (t.head().equals("NamedCodeBag")) {
162             CodeBag cb2 = new CodeBag(cb, name(t.child(0)));
163             for(Tree<String> statement : t.child(1))
164                 fillCodeBag(statement, cb2);
165
166         } else if (t.head().equals("Instruction")) {
167             Tree<String> opcode = t.child(0);
168             boolean trigger = opcode != null && opcode.size()>0 && "Triggered".equals(opcode.child(0).head());
169
170             int count = 0;
171             Tree arrow = t.child(2);
172             if      (arrow.head().equals("->"))     count = 1;
173             else if (arrow.head().equals("-[*]->")) count = Integer.MAX_VALUE;
174             else if (arrow.head().equals("-["))     count = Integer.parseInt(string(arrow.child(0)));
175
176             Tree opcodebody = opcode.size()==0 ? null : opcode.child(0).child(opcode.size()-1);
177             
178             PortReference d = portReference(t.child(3));
179             if (t.child(1).head() == null) {
180                 int literal = Integer.parseInt(string(t.child(1)));
181                 cb.add(new Literal.LiteralDatum(literal, d, false, count));
182
183             } else if ("AnonymousCodeBag".equals(t.child(1).head())) {
184                 CodeBag cb3 = new CodeBag(cb, null);
185                 for(Tree<String> tc : t.child(1).child(0))
186                     fillCodeBag(tc, cb3);
187                 cb.add(new Literal.LiteralDatum(cb3.getDescriptor(), d, true));
188
189             } else if ("CodeBagRef".equals(t.child(1).head())) {
190                 cb.add(new Literal.CodeBagRef(name(t.child(1).child(0)), cb, d));
191
192             } else if ("ShipSpecific".equals(t.child(1).head())) {
193                 cb.add(new Literal.ShipSpecific(string(t.child(1).child(0)), d, count));
194
195             } else {
196                 PortReference s = portReference(t.child(1));
197                 Instruction inst = null;
198                 if (opcodebody==null)         inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
199                 else if (opcodebody.head().equals("nop"))            inst = new Instruction(s, d, count, IGNORE, false,  trigger, false);
200                 else if (opcodebody.head().equals("synthesize"))     inst = new Instruction(s, d, count, IGNORE, false,  trigger, true);
201                 else if (opcodebody.head().equals("synthesize+ack")) inst = new Instruction(s, d, count, IGNORE, true,   trigger, true);
202                 else if (opcodebody.head().equals("wait"))           inst = new Instruction(s, d, count, COPY,   false,  trigger, false);
203                 else if (opcodebody.head().equals("discard"))        inst = new Instruction(s, d, count, TAKE,   false,  trigger, false);
204                 else if (opcodebody.head().equals("nop+ack"))        inst = new Instruction(s, d, count, IGNORE, true,   trigger, false);
205                 else if (opcodebody.head().equals("wait+ack"))       inst = new Instruction(s, d, count, COPY,   true,   trigger, false);
206                 else if (opcodebody.head().equals("discard+ack"))    inst = new Instruction(s, d, count, TAKE,   true,   trigger, false);
207                 else if (opcodebody.head().equals("copy"))           inst = new Instruction(s, d, count, COPY,   false,  trigger, true);
208                 else if (opcodebody.head().equals("copy+ack"))       inst = new Instruction(s, d, count, COPY,   true,   trigger, true);
209                 else if (opcodebody.head().equals("move"))           inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
210                 else if (opcodebody.head().equals("move+ack"))       inst = new Instruction(s, d, count, TAKE,   true,   trigger, true);
211                 else if (opcodebody.head().equals("accept"))         inst = new Instruction(s, d, count, TAKE,   false,  trigger, true);
212                 else if (opcodebody.head().equals("accept+ack"))     inst = new Instruction(s, d, count, TAKE,   true,   trigger, true);
213                 cb.add(inst);
214             }
215         }
216     }
217
218 }