package jazz.circuit.esterel; ////////////////////////////////////////////////////////////////////////////// // // Parsing of Pure Esterel programs // // The Syntax is that of "A Hardware Implementation of Pure Esterel" by // Gérard Berry, except for brackets which are used to parenthesize the // parallel construct // // [ stmt ; ... ; stmt || stmt ; ... ; stmt ] // // instead of being the grouping symbols for statements. // // Since parsing is, in essence, a sequential operation, we make heavy use of // explicit serialization of the evaluation of expressions // // (e1 ; e2 ; ... ; en) // // which evaluates, in sequence, e1, ..., and en to head-normal form. This // explicit serialization is required when the ei's have side effects. When // the values vi of ei is used in ej (j > i) the recommended programming // style, used below, is the following // // v = (v1 ; v2 ; ... ; vn) { // v1 = e1; // v2 = e2; // ... // vn = en; // } // // which is equivalent to the following C or Java statement // // { // T1 v1 = e1; // T2 v2 = e2; // ... // Tn vn = e2; // // v = vn; // } // // where Ti is the type of ei. // ////////////////////////////////////////////////////////////////////////////// import jazz.circuit.*; import jazz.io.FileReader; import jazz.util.List; import jazz.unsafe.Hashtable; Module.parse(fileName: String) = ( table.put(POS, 0) ; nextToken() ; module() ) { POS = 0; TOKEN = 1; table = Hashtable.create(); file = FileReader.open(fileName).readString(); len = file.length(); fun syntax() = error("syntax error"); fun beg() = ( char ; table.put(POS, pos + 1) ; spc ? beg() : pos ) { pos = table.get(POS, 0); char = (pos >= len) ? -1 : file.charAt(pos); spc = (char == 32 || char == 10 || char == 13); } fun end() = done ? pos : (table.put(POS, pos + 1) ; end()) { pos = table.get(POS, 0); char = (pos >= len) ? -1 : file.charAt(pos); done = (char == -1 || char == 32 || char == 10 || char == 13 || char == 58 || char == 124 || char == 59 || char == 91 || char == 93 || char == 44); } fun nextToken() = ( tbeg ; tend ; table.put(TOKEN, token) ; token ) { tbeg = beg(); tend = end(); token = (tbeg < len && tend <= len ? file.substring(tbeg, tend) : ""); } fun currentToken() = (String) table.get(TOKEN, ""); fun stmt() = (s1; (t2 == ";" ? seq : s1)) { t1 = currentToken(); if (t1 == "halt") { s1 = new HaltStmt(); t2 = nextToken(); } else if (t1 == "nothing") { s1 = new NothingStmt(); t2 = nextToken(); } else if (t1 == "emit") { s1 = (sig; s2) { sig = nextToken(); s2 = new EmitStmt(sig = sig); } t2 = nextToken(); } else if (t1 == "exit") { s1 = (sig; s2) { sig = nextToken(); s2 = new ExitStmt(sig = sig); } t2 = nextToken(); } else if (t1 == "loop") { s1 = (nextToken(); s2; t2; s3) { s2 = stmt(); t2 = currentToken() == "end" ? nextToken() : syntax(); s3 = new LoopStmt(stmt = s2); } t2 = currentToken(); } else if (t1 == "present") { s1 = (sig; t2; s2; t3; t4; s3; s5) { sig = nextToken(); t2 = nextToken() == "then" ? nextToken() : syntax(); s2 = stmt(); t3 = currentToken(); t4 = (t3 == "end" || t3 == "else") ? nextToken() : syntax(); s3 = t3 == "end" ? new NothingStmt() : (s4; t5; s4); s4 = stmt(); t5 = currentToken() == "end" ? nextToken() : syntax(); s5 = new PresentStmt(sig = sig, stmt1 = s2, stmt2 = s3); } t2 = currentToken(); } else if (t1 == "trap") { s1 = (sig; t2; s2; t3; s3) { sig = nextToken(); t2 = nextToken() == "in" ? nextToken() : syntax(); s2 = stmt(); t3 = currentToken() == "end" ? nextToken() : syntax(); s3 = new TrapStmt(sig = sig, stmt = s2); } t2 = currentToken(); } else if (t1 == "signal") { s1 = (sig; t2; s2; t3; s3) { sig = nextToken(); t2 = nextToken() == "in" ? nextToken() : syntax(); s2 = stmt(); t3 = currentToken() == "end" ? nextToken() : syntax(); s3 = new SignalStmt(sig = sig, stmt = s2); } t2 = currentToken(); } else if (t1 == "do") { s1 = (nextToken(); s2; sig; s3) { s2 = stmt(); sig = currentToken() == "watching" ? nextToken() : syntax(); s3 = new WatchStmt(sig = sig, stmt = s2); } t2 = nextToken(); } else if (t1 == "[") { s1 = (nextToken(); s2; t2; t3; s3; t4; s4) { s2 = stmt(); t2 = currentToken() == "|" ? nextToken() : syntax(); t3 = currentToken() == "|" ? nextToken() : syntax(); s3 = stmt(); t4 = currentToken() == "]" ? nextToken() : syntax(); s4 = new ParallelStmt(stmt1 = s2, stmt2 = s3); } t2 = currentToken(); } else { s1 = syntax(); } seq = ( nextToken() ; s2 ; new SequenceStmt(stmt1 = s1, stmt2 = s2)) { s2 = stmt(); } } fun ios(keyword) = currentToken() == keyword ? l : List.nil { l = (nextToken(); ios(List.nil)); fun ios(l) = t1 == ";" ? l1 : l2 { t1 = currentToken(); l1 = (nextToken(); l); l2 = (nextToken(); t1 == "," ? ios(l) : ios(l.cons(t1))); } } fun module() = (t1; t2; i; o; s; d; mod) { t1 = currentToken() == "module" ? nextToken() : syntax(); t2 = nextToken() == ":" ? nextToken() : syntax(); i = ios("input").reverse(); o = ios("output").reverse(); s = stmt(); d = currentToken() == "." ? () : syntax(); mod = new Module(name = t1, inputs = i, outputs = o, stmt = s); } }