diff --git a/MVaP/MVaP-v0/MVaP/index.html b/MVaP/MVaP-v0/MVaP/index.html
new file mode 100644
index 0000000..7b40946
--- /dev/null
+++ b/MVaP/MVaP-v0/MVaP/index.html
@@ -0,0 +1,72 @@
+
+
+
+
+ MVàP
+
+
+
+
+
+
+
+
+ Machine Virtuelle à Pile
+
+ Historique
+ Blabla sur la MVàP...
+
+ Documentation
+ Toute la doc
+
+ lorem ipsum
+
La MVàP
+ Entrez le code
+
+
+
+
+ Exécution
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MVaP/MVaP-v0/MVaP/js/CBaP.js b/MVaP/MVaP-v0/MVaP/js/CBaP.js
new file mode 100644
index 0000000..9864c57
--- /dev/null
+++ b/MVaP/MVaP-v0/MVaP/js/CBaP.js
@@ -0,0 +1,216 @@
+/**
+ * Code Binaire pour Machine Virtuelle à Pile.
+ * Les flottants sont des double qui prennent la place de 2 ints.
+ * Les adresses sont des int.
+ * CALL empile l'adresse de retour et la vauler du framePointer dans la pile.
+ */
+public class CBaP {
+
+
+
+ pc = 0;
+ fp = 0;
+ stack;
+ program;
+ const SizeofDouble = 2;
+
+ _debug = false;
+
+ CBaP(program, debug, stackSize) {
+ this.program = program;
+ this._debug = debug;
+ this.stack = new Pile(stackSize);
+ }
+
+ dumpInstruction(ii, out) {
+ let i = ii;
+ switch(program.get_int(i)) {
+ case AssembleMVaP.ADD: out.print("ADD "); break;
+ case AssembleMVaP.SUB: out.print("SUB "); break;
+ case AssembleMVaP.MUL: out.print("MUL "); break;
+ case AssembleMVaP.DIV: out.print("DIV "); break;
+ case AssembleMVaP.INF: out.print("INF "); break;
+ case AssembleMVaP.INFEQ: out.print("INFEQ "); break;
+ case AssembleMVaP.SUP: out.print("SUP "); break;
+ case AssembleMVaP.SUPEQ: out.print("SUPEQ "); break;
+ case AssembleMVaP.EQUAL: out.print("EQUAL "); break;
+ case AssembleMVaP.NEQ: out.print("NEQ "); break;
+
+ case AssembleMVaP.FADD: out.print("FADD "); break;
+ case AssembleMVaP.FSUB: out.print("FSUB "); break;
+ case AssembleMVaP.FMUL: out.print("FMUL "); break;
+ case AssembleMVaP.FDIV: out.print("FDIV "); break;
+ case AssembleMVaP.FINF: out.print("FINF "); break;
+ case AssembleMVaP.FINFEQ: out.print("FINFEQ"); break;
+ case AssembleMVaP.FSUP: out.print("FSUP "); break;
+ case AssembleMVaP.FSUPEQ: out.print("FSUPEQ"); break;
+ case AssembleMVaP.FEQUAL: out.print("FEQUAL"); break;
+ case AssembleMVaP.FNEQ: out.print("FNEQ "); break;
+ case AssembleMVaP.ITOF: out.print("ITOF "); break;
+ case AssembleMVaP.FTOI: out.print("FTOI "); break;
+
+ case AssembleMVaP.RETURN: out.print("RETURN"); break;
+ case AssembleMVaP.POP: out.print("POP "); break;
+ case AssembleMVaP.READ: out.print("READ "); break;
+ case AssembleMVaP.WRITE: out.print("WRITE "); break;
+ case AssembleMVaP.WRITEF: out.print("WRITEF"); break;
+ case AssembleMVaP.PADD: out.print("PADD "); break;
+ case AssembleMVaP.PUSHGP: out.print("PUSHGP"); break;
+ case AssembleMVaP.PUSHFP: out.print("PUSHFP"); break;
+ case AssembleMVaP.DUP: out.print("DUP "); break;
+
+ case AssembleMVaP.PUSHI: out.print("PUSHI "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.PUSHG: out.print("PUSHG "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.STOREG: out.print("STOREG"); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.PUSHL: out.print("PUSHL "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.STOREL: out.print("STOREL"); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.PUSHR: out.print("PUSHR "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.STORER: out.print("STORER"); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.FREE: out.print("FREE "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.ALLOC: out.print("ALLOC "); out.format("%7d ", program.get_int(++i)); break;
+
+ case AssembleMVaP.PUSHF: out.print("PUSHF "); ++i; out.format("%7.3f ", program.get_double(++i)); break;
+
+ case AssembleMVaP.JUMP: out.print("JUMP "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.JUMPF: out.print("JUMPF "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.JUMPI: out.print("JUMPI "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.CALL: out.print("CALL "); out.format("%7d ", program.get_int(++i)); break;
+ case AssembleMVaP.HALT: out.print("HALT "); break;
+ default: System.err.println("Code inconnu "+program.get_int(i)+" ligne "+i);
+ }
+ if (i == ii) out.print(" ");
+ return i;
+ }
+
+ public void dumpProgram(PrintStream out) {
+ // out.println(program.toString(true));
+ // out.println(program.toString());
+ out.println(" Adr | Instruction");
+ out.println("-----+---------------");
+ for(int i = 0; i < program.getSize(); i++) {
+ out.format("%4d | ", i);
+ i = dumpInstruction(i, out);
+ out.println();
+ }
+ }
+
+ private void _call(int label) {
+ push(pc+1);
+ push(fp);
+ fp = size();
+ pc = label;
+ }
+
+ private void _return() {
+ while(size() > fp)
+ pop();
+ fp = pop();
+ pc = pop();
+ }
+
+ private BufferedReader input = null;
+ private int _read() {
+ try {
+ if (input == null)
+ input = new BufferedReader(new InputStreamReader(System.in));
+ return Integer.parseInt(input.readLine());
+ } catch (Exception e) {
+ System.err.println(e);
+ System.exit(1);
+ return 0;
+ }
+ }
+
+ public boolean execute() {
+ if (_debug) {
+ dumpProgram(System.out);
+ System.err.println();
+ System.err.println(" pc | | fp pile");
+ System.err.println("====================================================");
+ }
+ pc = 0;
+ while (true) {
+ if (_debug) {
+ System.err.format("%4d | ", pc);
+ dumpInstruction(pc, System.err);
+ System.err.format("| %4d %s\n", fp, stack.toString());
+ }
+ try {
+ int p1, p2; // utile pour être sûr de l'ordre des pop() !
+ double d1, d2;
+ switch(program.get_int(pc++)) {
+ case AssembleMVaP.ADD: p1 = pop(); p2 = pop(); push(p2 + p1); break;
+ case AssembleMVaP.SUB: p1 = pop(); p2 = pop(); push(p2 - p1); break;
+ case AssembleMVaP.MUL: p1 = pop(); p2 = pop(); push(p2 * p1); break;
+ case AssembleMVaP.DIV: p1 = pop(); p2 = pop(); push(p2 / p1); break;
+ case AssembleMVaP.INF: p1 = pop(); p2 = pop(); push(p2 < p1 ? 1 : 0); break;
+ case AssembleMVaP.INFEQ: p1 = pop(); p2 = pop(); push(p2 <= p1 ? 1 : 0); break;
+ case AssembleMVaP.SUP: p1 = pop(); p2 = pop(); push(p2 > p1 ? 1 : 0); break;
+ case AssembleMVaP.SUPEQ: p1 = pop(); p2 = pop(); push(p2 >= p1 ? 1 : 0); break;
+ case AssembleMVaP.EQUAL: p1 = pop(); p2 = pop(); push(p2 == p1 ? 1 : 0); break;
+ case AssembleMVaP.NEQ: p1 = pop(); p2 = pop(); push(p2 != p1 ? 1 : 0); break;
+
+ case AssembleMVaP.FADD: d1 = pop_double(); d2 = pop_double(); push(d2 + d1); break;
+ case AssembleMVaP.FSUB: d1 = pop_double(); d2 = pop_double(); push(d2 - d1); break;
+ case AssembleMVaP.FMUL: d1 = pop_double(); d2 = pop_double(); push(d2 * d1); break;
+ case AssembleMVaP.FDIV: d1 = pop_double(); d2 = pop_double(); push(d2 / d1); break;
+ case AssembleMVaP.FINF: d1 = pop_double(); d2 = pop_double(); push(d2 < d1 ? 1 : 0); break;
+ case AssembleMVaP.FINFEQ: d1 = pop_double(); d2 = pop_double(); push(d2 <= d1 ? 1 : 0); break;
+ case AssembleMVaP.FSUP: d1 = pop_double(); d2 = pop_double(); push(d2 > d1 ? 1 : 0); break;
+ case AssembleMVaP.FSUPEQ: d1 = pop_double(); d2 = pop_double(); push(d2 >= d1 ? 1 : 0); break;
+ case AssembleMVaP.FEQUAL: d1 = pop_double(); d2 = pop_double(); push(d2 == d1 ? 1 : 0); break;
+ case AssembleMVaP.FNEQ: d1 = pop_double(); d2 = pop_double(); push(d2 != d1 ? 1 : 0); break;
+
+ case AssembleMVaP.FTOI: push((int)pop_double()); break;
+ case AssembleMVaP.ITOF: push((double)pop()); break;
+
+ case AssembleMVaP.RETURN: _return(); break;
+ case AssembleMVaP.POP: pop(); break;
+ case AssembleMVaP.READ: push(_read()); break;
+ case AssembleMVaP.WRITE: System.out.format("%7d\n", peek()); break;
+ case AssembleMVaP.WRITEF: System.out.format("%7.3f\n", peek_double()); break;
+ case AssembleMVaP.PADD: p1 = pop(); p2 = pop(); push(p2 + p1); break;
+ case AssembleMVaP.PUSHGP: push(0); break;
+ case AssembleMVaP.PUSHFP: push(fp); break;
+ case AssembleMVaP.DUP: push(peek()); break;
+
+ case AssembleMVaP.PUSHI: push(program.get_int(pc++)); break;
+ case AssembleMVaP.PUSHG: push(get(program.get_int(pc++))); break;
+ case AssembleMVaP.STOREG: set(program.get_int(pc++), pop()); break;
+ // ajouter -2 si adresse négative ?
+ case AssembleMVaP.PUSHL: push(get(fp+program.get_int(pc++))); break;
+ case AssembleMVaP.STOREL:set(fp+program.get_int(pc++), pop()); break;
+ case AssembleMVaP.PUSHR: push(get(pop()+program.get_int(pc++)));break;
+ case AssembleMVaP.STORER:p1 = pop(); p2 = pop(); set(p2+program.get_int(pc++), p1); break;
+ case AssembleMVaP.FREE: doPop(program.get_int(pc++)); break;
+ case AssembleMVaP.ALLOC: doPush(program.get_int(pc++)); break;
+
+ case AssembleMVaP.PUSHF: push(program.get_int(pc++)); push(program.get_int(pc++)); break;
+
+ case AssembleMVaP.JUMP: pc = program.get_int(pc); break;
+ case AssembleMVaP.JUMPF: if (pop() == 0) pc = program.get_int(pc); else pc++; break;
+ case AssembleMVaP.JUMPI: pc = program.get_int(pc)+pop(); break;
+ case AssembleMVaP.CALL: _call(program.get_int(pc)); break;
+ case AssembleMVaP.HALT: return true;
+ default: System.err.println("Code inconnu "+program.get_int(pc)+" ligne "+pc); return false;
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ System.err.println(stack.getException());
+ return false;
+ }
+ }
+ }
+
+ void push(int i) { stack.push(i); }
+ int pop() { return stack.pop_int(); }
+ void push(double d) { stack.push(d); }
+ double pop_double() { return stack.pop_double(); }
+ int peek() { return stack.peek_int(); }
+ double peek_double() { return stack.peek_double(); }
+ int size() { return stack.getSize(); }
+ void set(int index, int i) { stack.set(index, i); }
+ int get(int index) { return stack.get_int(index); }
+
+ void doPop(int nb) { for(; nb > 0; nb--) stack.pop_int(); }
+ void doPush(int nb) { for(; nb > 0; nb--) stack.push(0); }
+}
diff --git a/MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot b/MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot
new file mode 100644
index 0000000..be9c7c5
--- /dev/null
+++ b/MVaP/MVaP-v0/MVaP/js/LexerMVaP.dot
@@ -0,0 +1,33 @@
+digraph LexerMVaP {
+ Start -> Start [label="space "];
+ Start -> Id [label="[A-Z]"];
+ Id -> Id [label="[A-Z]"];
+
+ Start -> Int [label="[-+0-9]"];
+ Int -> Int [label="[0-9]"];
+ Int -> Decimal [label="."];
+ Int -> E [label="E"];
+
+ Decimal -> Decimal [label="[0-9]"];
+ Decimal -> E [label="E"];
+
+ E -> Exponent [label="[-+0-9]"];
+ Exponent -> Exponent [label="[0-9]"];
+
+ Start -> error [label="*"];
+ Id -> error [label="*"];
+ Int -> error [label="*"];
+ Decimal -> error [label="*"];
+ E -> error [label="*"];
+ Exponent -> error [label="*"];
+
+edge [color=red, fontcolor=red];
+
+ Start -> Start [label="NL/[Newline] "];
+ Id -> Start [label="space/ID"];
+ Int -> Start [label="space/Int"];
+ Decimal -> Start [label="space/Float"];
+ Exponent -> Start [label="space/Float"];
+
+ { rank = same; Decimal E Exponent }
+}
diff --git a/MVaP/MVaP-v0/MVaP/js/LexerMVaP.png b/MVaP/MVaP-v0/MVaP/js/LexerMVaP.png
new file mode 100644
index 0000000..684d618
Binary files /dev/null and b/MVaP/MVaP-v0/MVaP/js/LexerMVaP.png differ
diff --git a/MVaP/MVaP-v0/MVaP/js/MVaP.js b/MVaP/MVaP-v0/MVaP/js/MVaP.js
new file mode 100644
index 0000000..6466a56
--- /dev/null
+++ b/MVaP/MVaP-v0/MVaP/js/MVaP.js
@@ -0,0 +1,374 @@
+// MVàP
+
+let debugLexer = false;
+let debug = true;
+
+/** token lexicaux */
+const T_ID = 0;
+const T_INT = 1;
+const T_FLOAT = 2;
+const T_SPACE = 3;
+const T_NL = 4;
+const T_ERROR = 5;
+const T_EOF = 6;
+
+T_Text = [ "T_ID", "T_INT", "T_FLOAT", "T_SPACE", "T_NL", "T_ERROR", "T_EOF" ];
+
+/** token grammaticaux */
+const INSTR1 = 0;
+const INSTR2 = 1;
+const INT = 2;
+const INSTR2F = 3;
+const FLOAT = 4;
+const LABEL = 5;
+const JUMP = 6;
+const NEWLINE = 7;
+
+class MVaP {
+
+ codes = [ // pour l'interprète de MVàP
+ [ "ADD", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2+p1); } ],
+ [ "SUB", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2-p1); } ],
+ [ "MUL", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2*p1); } ],
+ [ "DIV", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(Math.floor(p2/p1)); } ],
+ [ "INF", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2 { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2<=p1?1:0); } ],
+ [ "SUP", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2>p1?1:0); } ],
+ [ "SUPEQ", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2>=p1?1:0); } ],
+ [ "EQUAL", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2==p1?1:0); } ],
+ [ "NEQ", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2!=p1?1:0); } ],
+ [ "FADD", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2+d1); } ],
+ [ "FSUB", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2-d1); } ],
+ [ "FMUL", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2*d1); } ],
+ [ "FDIV", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.pushFloat64(d2/d1); } ],
+ [ "FINF", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2 { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2<=d1?1:0); } ],
+ [ "FSUP", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2>d1?1:0); } ],
+ [ "FSUPEQ", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2>=d1?1:0); } ],
+ [ "FEQUAL", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2==d1?1:0); } ],
+ [ "FNEQ", INSTR1, () => { let d1 = this.stack.popFloat64(); let d2 = this.stack.popFloat64(); this.stack.push(d2!=d1?1:0); } ],
+ [ "ITOF", INSTR1, () => { let p1 = this.stack.pop(); this.trace("ITOF "+p1); this.stack.pushFloat64(p1); } ],
+ [ "FTOI", INSTR1, () => { this.stack.push(Math.round(this.stack.popFloat64())); } ],
+ [ "RETURN", INSTR1, () => { while(this.stack.getSize() > this.fp) this.stack.pop();
+ this.fp = this.stack.pop(); this.pc = this.stack.pop(); } ],
+ [ "POP", INSTR1, () => { this.stack.pop(); } ],
+ [ "READ", INSTR1, () => { this.stack.push(0); } ], // on lit toujours 0 (idée : prendre le contenu d'un input de type text spécial
+ [ "WRITE", INSTR1, () => { this.trace(this.stack.peek()+"\n"); } ],
+ [ "WRITEF", INSTR1, () => { this.trace(this.stack.peekFloat64()+"\n"); } ],
+ [ "PADD", INSTR1, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.push(p2+p1); } ],
+ [ "PUSHGP", INSTR1, () => { this.stack.push(0); } ],
+ [ "PUSHFP", INSTR1, () => { this.stack.push(this.fp); } ],
+ [ "DUP", INSTR1, () => { this.stack.push(this.stack.peek()); } ],
+
+ [ "PUSHI", INSTR2, () => { this.stack.push(this.program.get(this.pc++)); } ],
+ [ "PUSHG", INSTR2, () => { this.stack.push(this.stack.get(this.program.get(this.pc++)));} ],
+ [ "STOREG", INSTR2, () => { this.stack.set(this.program.get(this.pc++), this.stack.pop())} ],
+ [ "PUSHL", INSTR2, () => { this.stack.push(this.stack.get(this.fp+this.program.get(this.pc++))); } ],
+ [ "STOREL", INSTR2, () => { this.stack.set(this.fp+this.program.get(this.pc++), this.stack.pop()); } ],
+ [ "PUSHR", INSTR2, () => { this.stack.push(this.stack.get(this.stack.pop()+this.program.get(this.pc++))); } ],
+ [ "STORER", INSTR2, () => { let p1 = this.stack.pop(); let p2 = this.stack.pop(); this.stack.set(p2+this.program.get(this.pc++)); } ],
+ [ "FREE", INSTR2, () => { this.stack.doPop(this.program.get(this.pc++)); } ],
+ [ "ALLOC", INSTR2, () => { this.stack.doPush(this.program.get(this.pc++)); } ],
+ [ "PUSHF", INSTR2F, () => { this.stack.pushFloat64(this.program.getFloat64(this.pc)); this.pc += 2; } ],
+ [ "CALL", JUMP, () => { this.stack.push(this.pc+1); this.stack.push(this.fp);
+ this.fp = this.stack.getSize();
+ this.pc = this.program.get(this.pc); } ],
+ [ "JUMP", JUMP, () => { this.pc = this.program.get(this.pc); } ],
+ [ "JUMPF", JUMP, () => { if (this.stack.pop()==0) this.pc = this.program.get(this.pc);
+ else this.pc++; } ],
+ [ "JUMPI", JUMP, () => { this.pc = this.program.get(this.pc)+this.stack.pop();} ],
+
+ [ "HALT", INSTR1, () => { return true; } ],
+
+ [ "LABEL", LABEL, /* erreur interne */ ]
+ ];
+ /*** Ajouter instr : READF WRITEF POPF */
+
+ tokens = []; // indexe le tableau codes sur son premier élément
+
+ text = "";
+
+ //
+ // see LexerMVaP.png for the DFA diagram
+ state = "Start";
+ text; // le texte à analyser
+ index = 0; // index dans la chaîne text
+ lineNumber = 1;
+
+ transitions = [
+ { state: "Start", next: "Start", test: (c) => { return c == "\n"; }, token: T_NL },
+ { state: "Start", next: "Start", test: (c) => { return c.trim() == ""; }, token: false },
+ { state: "Start", next: "Id", test: (c) => { return "A" <= c && c <= "Z"; }, token: false },
+ { state: "Id", next: "Id", test: (c) => { return "A" <= c && c <= "Z"; }, token: false},
+ { state: "Id", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_ID},
+ { state: "Start", next: "Int", test: (c) => { return ("0" <= c && c <= "9")||c=="-"||c=="+"; }, token: false },
+ { state: "Int", next: "Int", test: (c) => { return "0" <= c && c <= "9"; }, token: false },
+ { state: "Int", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_INT },
+ { state: "Int", next: "Decimal", test: (c) => { return c == "."; }, token: false },
+ { state: "Int", next: "E", test: (c) => { return c == "E"; }, token: false },
+ { state: "Decimal", next: "Decimal", test: (c) => { return "0" <= c && c <= "9"; }, token: false },
+ { state: "Decimal", next: "E", test: (c) => { return c == "E"; }, token: false },
+ { state: "Decimal", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_FLOAT },
+ { state: "E", next: "Exponent", test: (c) => { return ("0"<=c && c<="9")||c=="-"||c=="+"; }, token: false },
+ { state: "Exponent", next: "Exponent", test: (c) => { return "0" <= c && c <= "9"; }, token: false },
+ { state: "Exponent", next: "Start", test: (c) => { return c.trim() == ""; }, token: T_FLOAT }
+ // else: error
+ ];
+
+ initLexer() {
+ this.index = 0;
+ this.lineNumber = 1
+ console.log("*****************\n* C'est parti *\n*****************");
+ }
+
+ // Donne la transition correspondante à l'état courant et au caractère entrant
+ transition(c) {
+ for (let v of this.transitions.values()) {
+ // on aurait pu indexer les transitions sur state au lieu de tout énumérer
+ if (this.state == v.state && v.test(c)) {
+ return v;
+ }
+ }
+ return T_ERROR;
+ }
+
+ yytext = ""; // contient le texte du jeton syntaxique (nommé comme dans lex/yacc)
+
+
+ nextToken() {
+ let c;
+ let trans;
+ while (true) {
+ c = this.text[this.index];
+ if (c === undefined)
+ return T_EOF;
+ c = c.toUpperCase();
+ trans = this.transition(c);
+ if (trans == T_ERROR) { this.yytext += c; return T_ERROR; }
+ if (this.state != trans.next && this.state == "Start") this.yytext ="";
+
+ this.state = trans.next;
+ this.index++;
+
+ if (Number.isInteger(trans.token)) {
+ break;
+ }
+ this.yytext += c;
+ }
+
+ // séparateur significatif
+ if (c == "\n") {
+ if (trans.token != T_NL) {
+ this.index--; // ne pas manger la fin de ligne non prise en compte
+ // une autre façon de dire est que l'on n'incrémente pas l'index sur le renvoi de token
+ // sauf en cas de token constitué de séparateur
+ } else
+ this.lineNumber++; // on en profite pour compter la ligne
+ }
+ // console.log(" line " + this.lineNumber + " " + trans.token + " '" + yytex + "' i="+i);
+ return trans.token;
+ }
+ //
+
+ //
+
+ /** Grammaire des instructions
+ instr
+ : INSTR1 T_NL
+ | INSTR2 T_INT T_NL
+ | JUMP T_INT T_NL
+ | INSTR2F T_FLOAT T_NL
+ | LABEL T_NL
+ | T_NL
+ ;
+ */
+
+ program;// Pile contenant le programme compilé
+ adressesLabels; // adresse des étiquettes pour l'assemblage
+
+ analyse() {
+
+ this.initLexer();
+
+ let token; // le jeton lexical courant
+ let state = NEWLINE; // état de l'analyseur grammatical (ici le précédent syntagme grammatical)
+ this.program = new Pile();
+ this.adressesLabels = [];
+
+ while (true) {
+ this.yytext = "";
+ token = this.nextToken();
+ if (debugLexer)
+ console.log("** nextToken line "+this.lineNumber+" token "+token+" "+T_Text[token]+" '" +this.yytext+"' index "+this.index+" state "+state);
+
+ switch(token) {
+ case T_EOF:
+ return true;
+ case T_ID:
+ let k = this.tokens[this.yytext];
+ if (k === undefined || state != NEWLINE) return false;
+ state = this.codes[k][1];
+ if (state != LABEL) { // pas d'instruction LABEL dans le code
+ this.program.push(k);
+ }
+ break;
+ case T_INT:
+ if (state == LABEL) { // on mémorise juste l'adresse pour la passe d'assemblage
+ this.adressesLabels[Number(this.yytext)] = this.program.getSize(); // ± 1 who knows?
+ } else if(state == INSTR2 || state == JUMP) {
+ this.program.push(Number(this.yytext));
+ } else return false;
+ state = INT;
+ break;
+ case T_FLOAT:
+ if (state != INSTR2F) return false;
+ state = FLOAT;
+ this.program.pushFloat64(Number(this.yytext));
+ break;
+ case T_NL:
+ if (state == INSTR2 || state == JUMP || state == INSTR2F) return false;
+ state = NEWLINE;
+ break;
+ case T_ERROR:
+ return false;
+ default:
+ alert("Erreur interne prévenir la maintenance d'urgence");
+ return false;
+ }
+ }
+ console.log("Programme correct syntaxiquement");
+ return true;
+ }
+
+ assemble() {
+ // change les numéros d'étiquettes par les adresses des instructions pointées.
+ console.log("Label "+this.adressesLabels);
+ console.log(this.dumpProgram());
+
+ for (let i = 0; i < this.program.getSize(); i++) {
+ let k = this.program.get(i);
+ // Attention il faut compter si par malchance un entier = code d'un saut
+ switch (this.codes[k][1]) {
+ case INSTR1:
+ break;
+ case INSTR2:
+ i++; // on saute l'entier qui suit
+ break;
+ case INSTR2F:
+ i += 2; // on saute le flottant qui suit
+ break;
+ case JUMP: // met à jour l'adresse du saut
+ i++;
+ console.log("--- set "+i);
+ this.program.set(i, this.adressesLabels[this.program.get(i)]);
+ break;
+ default:
+ alert("Erreur assemblage");
+ }
+ }
+ // console.log(this.dumpProgram());
+ }
+ //
+
+
+ dumpInstruction(i, result) {
+ let code = this.codes[this.program.get(i)];
+ result += code[0].padEnd(6, ' ');
+ switch (code[1]) {
+ case INSTR2:
+ case JUMP:
+ result += this.program.get(++i).toString().padStart(7, ' ');
+ break;
+ case INSTR2F:
+ result += this.program.getFloat64(++i).toString().padStart(7, ' ');
+ i++;
+ break;
+ default:
+ result += " ";
+ }
+
+ return [i, result];
+ }
+
+ dumpProgram() {
+ let result = "";
+ result += this.program + "\n";
+
+ result += " Adr | Instruction\n-----+---------------\n";
+ for(let i = 0; i < this.program.getSize(); i++) {
+ result += i.toString().padStart(4, " ")+" | ";
+ [i, result] = this.dumpInstruction(i, result);
+ result += "\n";
+ }
+ return result;
+ }
+
+ constructor() {
+ // init tokens
+ for (let k of this.codes.keys())
+ this.tokens[this.codes[k][0]] = k;
+ }
+
+ // charge et compile le code
+ load(text) {
+ this.text = text;
+ // on insère une fin de ligne si le texte n'en a pas à sa fin
+ if (text[text.length-1] != "\n") this.text = text+"\n";
+ if (! this.analyse()) {
+ alert("Erreur ligne "+this.lineNumber+" sur '" +this.yytext+"'");
+ return;
+ }
+ this.assemble();
+ }
+
+ pc = 0;
+ fp = 0;
+ stack;
+
+ runcode(maxSteps, d) {
+ debug = d;
+ //for (let i = 0; i < this.codes.length; i++) console.log(i+ " "+ this.codes[i][0]);
+ this.pc = 0;
+ this.fp = 0;
+ this.stack = new Pile();
+
+ try {
+ if (debug)
+ this.trace("Programme\n"+this.dumpProgram() + "\nTraces exécution\n"
+ + " pc | Instruction | fp pile\n"
+ + "=====+===============+=============================\n");
+
+ for (let i= 0; i < maxSteps; i++) // while (true)
+ {
+ if (this.pc < 0 || this.pc >= this.program.getSize())
+ break;
+
+ if (debug) {
+ let s = this.pc.toString().padStart(4, " ")+" | ";
+ let junk;
+ [junk, s] = this.dumpInstruction(this.pc, s);
+ s += " |"+this.fp.toString().padStart(4,' ')+' '+this.stack.toString()+"\n";
+ this.trace(s);
+ }
+
+ if (this.codes[this.program.get(this.pc++)][2]() === true)
+ break;
+ }
+ } catch(e) {
+ this.trace(e);
+ console.error(e);
+ }
+ }
+
+ trace(s) {
+ traces.innerText += s;
+ console.log(s);
+ }
+
+}
+
+
+
+
+
+
diff --git a/MVaP/MVaP-v0/MVaP/js/Pile.js b/MVaP/MVaP-v0/MVaP/js/Pile.js
new file mode 100644
index 0000000..f78f210
--- /dev/null
+++ b/MVaP/MVaP-v0/MVaP/js/Pile.js
@@ -0,0 +1,153 @@
+// Class Pile
+// Auteur : Jacques Madelaine
+
+// Une Pile est essentiellement une pile d'entiers ("int32")
+// Elle peut aussi empiler et dépiler des flottants définis sur 64 bits.
+// L'index est sur les entiers.
+
+// Rappel : en JavaScript les Number sont tous stockés comme des flottants 64 bits.
+// Il faut donc voir cette Pile comme un objet pédagogique
+// et non une implémentation optimale en JavaScipt.
+
+"use strict";
+
+class Pile {
+ buffer; // ArrayBuffer de bytes
+ pile; // On va utiliser 4 bytes pour les entiers et 8 pour les flottants
+ haut = 0; // index de sommet de pile en bytes
+
+ // size : taille en bytes de la pile
+ constructor(size) {
+ if (size === undefined)
+ size = 1000;
+
+ this.buffer = new ArrayBuffer(size);
+ this.pile = new DataView(this.buffer);
+ }
+
+ push(i) {
+ if (! Number.isInteger(i))
+ throw new TypeError("Try to push a non integer");
+ this.pile.setInt32(this.haut, i);
+ this.haut += 4;
+ }
+
+ doPush(nb) { for(; nb > 0; nb--) this.push(0); }
+
+ pop() {
+ this.haut -= 4;
+ return this.pile.getInt32(this.haut);
+ }
+
+ doPop(nb) { for(; nb > 0; nb--) this.pop(); }
+
+ peek() {
+ return this.pile.getInt32(this.haut-4);
+ }
+
+ set(index, i) {
+ if (! Number.isInteger(i))
+ throw new TypeError("Try to set a non integer");
+ this.pile.setInt32(index*4, i);
+ }
+
+ get(index) {
+ return this.pile.getInt32(index*4);
+ }
+
+
+ pushFloat64(f) {
+ this.pile.setFloat64(this.haut, f);
+ this.haut += 8;
+ }
+
+ popFloat64() {
+ this.haut -= 8;
+ return this.pile.getFloat64(this.haut);
+ }
+
+ peekFloat64() {
+ return this.pile.getFloat64(this.haut-8);
+ }
+
+ setFloat64(index, f) {
+ this.pile.setFloat64(index*4, f);
+ }
+
+ getFloat64(index) {
+ return this.pile.getFloat64(index*4);
+ }
+
+ getMaxSize() {
+ return this.buffer.byteLength/2;
+ }
+
+ getSize() {
+ return this.haut/4;
+ }
+
+ toString() {
+ let out = "[ ";
+ for (let i = 0; i < this.getSize(); i++)
+ out += this.get(i) + ", ";
+ return out + " ] " + this.getSize();
+ }
+
+}
+
+
+/*
+
+let p = new Pile();
+try {
+ let d = 12.34;
+ let i = 0x7FFFFFFF;
+ let j = 0;
+ p.push(i);
+ j = p.peek();
+ console.log(i + " =?= " + j);
+
+ let N = 5;
+ for(let n = 0; n < N; n++) {
+ p.push(n);
+ console.log("push "+n+" " + n);
+ }
+
+ console.log("get(2) " + p.get(2));
+ console.log(p.toString());
+
+ for(let n = N; n > 0; n--) {
+ let m = p.pop();
+ // if (2*n != m)
+ console.log("push "+ n + " pop " + m);
+ }
+ p.pop();
+
+ p.push(40);
+ p.pushFloat64(d);
+ p.pushFloat64(13.34);
+ p.push(i);
+ console.log(p.toString());
+
+ for (let n = 0; n<6;n++)
+ console.log("p.getFloat64("+n+") = "+p.getFloat64(n));
+
+ p.pop();
+ p.popFloat64();
+ let e = p.popFloat64();
+ console.log(d + " =?= " + e);
+
+
+ d = -1;
+ p.pushFloat64(d);
+ e = p.popFloat64();
+ console.log(d + " =?= " + e);
+ //
+ // for (i = 0 ; i < 1000000; i++)
+ // p.push(i);
+} catch(e) {
+ console.error(e);
+}
+*/
+
+