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);
}
}