finish compiler!

This commit is contained in:
Elizabeth Hunt 2023-11-17 12:09:44 -07:00
parent 7d897cb2b5
commit a54a7ba7c9
Signed by: simponic
GPG Key ID: 52B3774857EB24B1
7 changed files with 251 additions and 127 deletions

View File

@ -69,3 +69,14 @@ hr {
border-top: 2px solid black; border-top: 2px solid black;
border-bottom: none; border-bottom: none;
} }
pre {
white-space: pre-wrap;
word-wrap: break-word;
}
@media only screen and (max-width: 1000px) {
.source-container {
flex-direction: column;
}
}

View File

@ -1,9 +1,17 @@
Program = lines: (Line / (_/[\n]))* { Program = lines: (ProgramInstruction / (_/[\n]))* {
return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") }; return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") };
} }
Line = _? instruction: (LabeledInstruction / Instruction) _? [\n]? { ProgramInstruction = _? instruction: (LabeledInstruction / Instruction) _? [\n]? {
return instruction; let x = 0;
let y = 0;
if (instruction.label) {
x = instruction.label.godel;
y = instruction.instruction.godel;
} else {
y = instruction.godel;
}
return { instruction, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
} }
LabeledInstruction = label:Label _ instruction:Instruction { LabeledInstruction = label:Label _ instruction:Instruction {
@ -14,33 +22,41 @@ Label = "[" _? label:LABEL_V _? "]" {
return label; return label;
} }
Instruction = conditional: Conditional { return { conditional }; } Instruction = conditional: Conditional { return { conditional, godel: conditional.godel }; }
/ assignment: Assignment { return { assignment }; } / assignment: Assignment { return { assignment, godel: assignment.godel }; }
/ goto: Goto { return { goto }; } / goto: Goto { return { goto, godel: goto.godel }; }
Goto = GOTO _ label: LABEL_V { Goto = GOTO _ label: LABEL_V {
return { label }; return { label, godel: label.godel + 2 };
} }
Conditional = "IF" _ variable: VAR _? "!=" _? "0" _ goto: Goto { Conditional = "IF" _ variable: VAR _? "!=" _? "0" _ goto: Goto {
return { variable, goto }; const y = variable.godel - 1;
const x = goto.godel;
return { variable, goto, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
} }
Assignment = variable: VAR _ "<-" _ expr: Expression { Assignment = variable: VAR _ "<-" _ expr: Expression {
if (expr.left != variable) { if (expr.left.symbol != variable.symbol) {
error("left hand variable must match right hand"); error("left hand variable must match right hand");
} }
return { variable, expr }; const x = expr.instructionNumber;
const y = variable.godel - 1;
return { variable, expr, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
} }
Expression = left: VAR _ opr: OPERATION _ "1" { Expression = left: VAR _ opr: OPERATION _ "1" {
return { left, opr }; const instructionNumber = { "+" : 1, "-" : 2 }[opr];
return { left, opr, instructionNumber };
} / left: VAR { } / left: VAR {
return { left }; return { left, instructionNumber: 0 };
} }
VAR = symbol:"Y" { return symbol } / symbol:("X" / "Z") ind:Integer+ { VAR = symbol:"Y" { return { symbol, godel: 1 }; } / symbol:("X" / "Z") ind:Integer+ {
return symbol + ind; const index = parseInt(ind);
const order = ["X", "Z"];
const godel = index * order.length + order.indexOf(symbol);
return { symbol: symbol + ind, godel };
} }
GOTO = "GOTO" GOTO = "GOTO"
@ -48,10 +64,12 @@ GOTO = "GOTO"
OPERATION = "+" / "-" OPERATION = "+" / "-"
LABEL_V = symbol:END_LABEL { return symbol } / symbol:[A-E] ind:Integer+ { LABEL_V = symbol:END_LABEL { return symbol } / symbol:[A-E] ind:Integer+ {
return symbol + ind; const index = parseInt(ind);
const godel = (symbol.charCodeAt(0) - "A".charCodeAt(0) + 1) + 5*(index-1);
return { symbol: symbol + ind, godel };
} }
END_LABEL = "E" END_LABEL = "E1"
Integer "integer" Integer "integer"
= [0-9]+ { return parseInt(text(), 10); } = [0-9]+ { return parseInt(text(), 10); }

View File

@ -17,20 +17,22 @@
<textarea id= <textarea id=
"instructions">// 0. primitive instructions only "instructions">// 0. primitive instructions only
// 1. labels match the regex [A-E](:digit:)+. // 1. labels match the regex [A-E](:digit:)+.
// 2. variables are initialized to zero // 2. variables are initialized to zero and match
// and match (Y | (X|Z)(:digit:)+). // (Y | (X|Z)(:digit:)+).
// 3. instructions must be delimited by a newline. // 3. instructions must be delimited by a newline.
// 4. anything following the comment token "//" up to a // 4. anything following the comment token "//" up to a
// newline are ignored. // newline are ignored.
// 5. by default, a computation that takes more than 500_000 // 5. by default, a computation that takes more than 500_000
// "procedures", it will be halted. // "procedures", it will be halted.
// 6. the implicit exit label "E" exists; thus to exit // 6. the implicit exit label "E1" exists; thus to exit
// prematurely, "GOTO E". // prematurely, "GOTO E1".
// 7. input your initial snapshot in the "variables" map // 7. input your initial snapshot in the "variables" map
// on the Program in the compiled JS output // on the Program in the compiled JS output
// 8. for a more detailed view on the grammar, it's at // 8. for a more detailed view on the grammar, it's at
// /godel/grammar.peg // /godel/grammar.peg
// THIS PROGRAM COMPUTES X1 + X2
// Y &lt;- X1 // Y &lt;- X1
[ A1 ] IF X1 != 0 GOTO A2 [ A1 ] IF X1 != 0 GOTO A2
GOTO B1 GOTO B1
@ -47,7 +49,7 @@
// Y &lt;- Y + Z1 // Y &lt;- Y + Z1
[ C1 ] IF Z1 != 0 GOTO C2 [ C1 ] IF Z1 != 0 GOTO C2
GOTO E GOTO E1
[ C2 ] Z1 &lt;- Z1 - 1 [ C2 ] Z1 &lt;- Z1 - 1
Y &lt;- Y + 1 Y &lt;- Y + 1
GOTO C1</textarea> GOTO C1</textarea>
@ -71,6 +73,17 @@
</div> </div>
</div> </div>
</div> </div>
<div class="textarea-container">
<h3>Godel</h3>
<p>Sequence:</p>
<pre id="godel_sequence"></pre>
<div>
<p>Number: <button id="godel_number_comp" style=
"display: none">Compute (this might take a
while)</button></p>
</div>
<pre id="godel_number"></pre>
</div>
</div> </div>
<script src="codemirror/codemirror.js"></script> <script src="codemirror/codemirror.js"></script>
<script src="js-beautify/js-beautify.js"></script> <script src="js-beautify/js-beautify.js"></script>

View File

@ -11,11 +11,14 @@ class StringBuilder {
} }
const compileGoto = (gotoNode, stringBuilder) => { const compileGoto = (gotoNode, stringBuilder) => {
stringBuilder.add(`this.followGoto("${gotoNode.label}");\nreturn;\n`); stringBuilder.add(`this.followGoto("${gotoNode.label.symbol}");\nreturn;\n`);
}; };
const compileConditional = (conditionalNode, stringBuilder) => { const compileConditional = (conditionalNode, stringBuilder) => {
const { variable, goto: gotoNode } = conditionalNode; const {
variable: { symbol: variable },
goto: gotoNode,
} = conditionalNode;
stringBuilder.add(`if (this.get("${variable}") != 0) {\n`); stringBuilder.add(`if (this.get("${variable}") != 0) {\n`);
compileGoto(gotoNode, stringBuilder); compileGoto(gotoNode, stringBuilder);
@ -23,7 +26,10 @@ const compileConditional = (conditionalNode, stringBuilder) => {
}; };
const compileAssignment = (assignmentNode, stringBuilder) => { const compileAssignment = (assignmentNode, stringBuilder) => {
const { variable, expr } = assignmentNode; const {
variable: { symbol: variable },
expr,
} = assignmentNode;
if (expr.opr) { if (expr.opr) {
if (expr.opr == "+") stringBuilder.add(`this.addOne("${variable}");\n`); if (expr.opr == "+") stringBuilder.add(`this.addOne("${variable}");\n`);
else if (expr.opr == "-") else if (expr.opr == "-")
@ -49,6 +55,8 @@ const compileInstruction = (instruction, stringBuilder) => {
}; };
const compile = (ast) => { const compile = (ast) => {
const godelSequence = [];
const stringBuilder = new StringBuilder(); const stringBuilder = new StringBuilder();
stringBuilder.add(` stringBuilder.add(`
class Program { class Program {
@ -65,8 +73,8 @@ const compile = (ast) => {
this.finalInstruction = ${ this.finalInstruction = ${
ast.instructions.length + 1 ast.instructions.length + 1
}; // instruction of the implied "exit" label }; // instruction of the implied "exit" label
// "E" is the exit label // "E1" is the exit label
this.labelInstructions.set("E", this.finalInstruction); this.labelInstructions.set("E1", this.finalInstruction);
} }
get(variable) { get(variable) {
@ -122,25 +130,31 @@ const compile = (ast) => {
stringBuilder.add("// -- build label -> instruction map --\n"); stringBuilder.add("// -- build label -> instruction map --\n");
for (let i = 0; i < ast.instructions.length; i++) { for (let i = 0; i < ast.instructions.length; i++) {
const line = ast.instructions[i]; const instruction = ast.instructions[i];
godelSequence.push(instruction.godel);
const line = instruction.instruction;
const instructionIdx = i + 1; const instructionIdx = i + 1;
if (line.label) { if (line.label) {
const symbol = line.label.symbol;
stringBuilder.add( stringBuilder.add(
`this.instructions.set(${instructionIdx}, () => this.${line.label}());\n` `this.instructions.set(${instructionIdx}, () => this.${symbol}());\n`
); );
stringBuilder.add( stringBuilder.add(
`this.labelInstructions.set("${line.label}", ${instructionIdx});\n` `this.labelInstructions.set("${symbol}", ${instructionIdx});\n`
); );
} }
} }
stringBuilder.add("// -- compiled instructions --\n"); stringBuilder.add("// -- compiled instructions --\n");
for (let i = 0; i < ast.instructions.length; i++) { for (let i = 0; i < ast.instructions.length; i++) {
let instruction = ast.instructions[i]; let instruction = ast.instructions[i].instruction;
const instructionIdx = i + 1; const instructionIdx = i + 1;
if (instruction.label) { if (instruction.label) {
const symbol = instruction.label.symbol;
stringBuilder.add( stringBuilder.add(
` this.followGoto("${instruction.label}");\n}\n\n${instruction.label}() {\n` ` this.followGoto("${symbol}");\n}\n\n${symbol}() {\n`
); );
stringBuilder.add(`this.instructionPointer = ${instructionIdx};\n`); stringBuilder.add(`this.instructionPointer = ${instructionIdx};\n`);
instruction = instruction.instruction; instruction = instruction.instruction;
@ -152,14 +166,17 @@ const compile = (ast) => {
stringBuilder.add(` }\n}\n`); stringBuilder.add(` }\n}\n`);
stringBuilder.add("// -- \n"); stringBuilder.add("// -- \n");
stringBuilder.add("const program = new Program();\n\n"); stringBuilder.add("const program = new Program();\n\n");
stringBuilder.add("// set the initial Snapshot here\n"); stringBuilder.add("// !! set the initial Snapshot here !!\n");
stringBuilder.add('// program.variables.set("X1", 2);\n\n'); stringBuilder.add('// program.variables.set("X1", 2);\n\n');
stringBuilder.add("program.run();\n"); stringBuilder.add("program.run();\n");
stringBuilder.add("console.log(program.variables);\n"); stringBuilder.add("console.log(program.variables);\n");
stringBuilder.add("program.getResult();\n"); stringBuilder.add("program.getResult();\n");
return js_beautify(stringBuilder.build(), { return {
indent_size: 2, js: js_beautify(stringBuilder.build(), {
wrap_line_length: 100, indent_size: 2,
}); wrap_line_length: 100,
}),
godelSequence,
};
}; };

27
godel/js/godelWorker.js Normal file
View File

@ -0,0 +1,27 @@
const isPrime = (n) =>
!Array(Math.ceil(Math.sqrt(n)))
.fill(0)
.map((_, i) => i + 2) // first prime is 2
.some((i) => n !== i && n % i === 0);
const primesCache = [2];
const p = (i) => {
if (primesCache.length <= i) {
let x = primesCache.at(-1);
while (primesCache.length <= i) {
if (isPrime(++x)) primesCache.push(x);
}
}
return primesCache.at(i - 1);
};
const computeGodelNumber = (godelSequence) =>
godelSequence.reduce((acc, num, i) => {
const prime = p(i + 1);
return BigInt(acc) * BigInt(prime) ** BigInt(num);
}, 1) - BigInt(1);
self.addEventListener("message", (e) => {
const godelNumber = computeGodelNumber(e.data);
postMessage(godelNumber);
});

View File

@ -18,15 +18,19 @@ const main = () => {
if (msg.type == MESSAGES.COMPILE) { if (msg.type == MESSAGES.COMPILE) {
const { value } = msg; const { value } = msg;
const source = prepareSource(value); const source = prepareSource(value);
try { try {
const ast = parser.parse(source); const ast = parser.parse(source);
const program = compile(ast); const { js, godelSequence } = compile(ast);
state.notify({ state.notify({
type: MESSAGES.COMPILE_RESULT, type: MESSAGES.COMPILE_RESULT,
value: program, success: true,
js,
godelSequence,
}); });
} catch (e) { } catch (e) {
console.error(e);
state.notify({ state.notify({
type: MESSAGES.COMPILE_RESULT, type: MESSAGES.COMPILE_RESULT,
error: e.toString(), error: e.toString(),
@ -39,6 +43,7 @@ const main = () => {
const result = eval(source); const result = eval(source);
state.notify({ state.notify({
type: MESSAGES.EVAL_RESULT, type: MESSAGES.EVAL_RESULT,
success: true,
value: result, value: result,
}); });
} catch (e) { } catch (e) {
@ -54,33 +59,46 @@ main();
// -- a bit of some hacky ui code -- // -- a bit of some hacky ui code --
const instructionsEl = document.getElementById("instructions"); const codeMirrorConfig = {
const instructionsEditorEl = CodeMirror.fromTextArea(instructionsEl, {
lineNumbers: true, lineNumbers: true,
}); };
const instructionsEl = document.getElementById("instructions");
const instructionsEditorEl = CodeMirror.fromTextArea(
instructionsEl,
codeMirrorConfig
);
const compileButton = document.getElementById("compile"); const compileButton = document.getElementById("compile");
const evalButton = document.getElementById("eval"); const evalButton = document.getElementById("eval");
const evalStatusEl = document.getElementById("eval_status"); const evalStatusEl = document.getElementById("eval_status");
const compileStatusEl = document.getElementById("compile_status"); const compileStatusEl = document.getElementById("compile_status");
const compiledEl = document.getElementById("compiled"); const compiledEl = document.getElementById("compiled");
const compiledEditorEl = CodeMirror.fromTextArea(compiledEl, { const compiledEditorEl = CodeMirror.fromTextArea(compiledEl, codeMirrorConfig);
lineNumbers: true, const godelSequenceEl = document.getElementById("godel_sequence");
}); const godelNumberEl = document.getElementById("godel_number");
const godelNumberComputeBtn = document.getElementById("godel_number_comp");
state.subscribe((msg) => { state.subscribe((msg) => {
if (msg.type == MESSAGES.COMPILE_RESULT) { if (msg.type == MESSAGES.COMPILE_RESULT) {
evalStatusEl.classList.remove("error"); evalStatusEl.classList.remove("error");
evalStatusEl.classList.remove("success"); evalStatusEl.classList.remove("success");
evalStatusEl.innerHTML = ""; evalStatusEl.innerHTML = "";
if (typeof msg.value !== "undefined") { if (msg.success) {
compiledEditorEl.setValue(msg.value); const { js, godelSequence } = msg;
compiledEditorEl.setValue(js);
godelSequenceEl.innerHTML = `[${godelSequence.join(", ")}]`;
godelNumberComputeBtn.style.display = "inline";
compileStatusEl.classList.add("success"); compileStatusEl.classList.add("success");
compileStatusEl.classList.remove("error"); compileStatusEl.classList.remove("error");
compileStatusEl.innerHTML = `Successful compile at ${new Date().toLocaleString()}!`; compileStatusEl.innerHTML = `Successful compile at ${new Date().toLocaleString()}!`;
} else if (msg.error) { } else if (msg.error) {
compiledEditorEl.setValue(""); compiledEditorEl.setValue("");
godelSequenceEl.innerHTML = "";
godelNumberEl.innerHTML = "";
godelNumberComputeBtn.style.display = "none";
compileStatusEl.classList.remove("success"); compileStatusEl.classList.remove("success");
compileStatusEl.classList.add("error"); compileStatusEl.classList.add("error");
@ -88,9 +106,33 @@ state.subscribe((msg) => {
} }
} }
}); });
state.subscribe((msg) => {
if (msg.type == MESSAGES.COMPILE_RESULT) {
if (msg.success) {
const { godelSequence } = msg;
godelNumberComputeBtn.onclick = () => {
godelNumberEl.innerHTML = "working...";
const worker = new Worker("js/godelWorker.js");
worker.addEventListener("message", (e) => {
const godelNumber = e.data;
godelNumberEl.innerHTML = godelNumber.toString();
});
worker.postMessage(godelSequence);
};
} else if (msg.error) {
godelNumberComputeBtn.onclick = () => {};
}
}
});
state.subscribe((msg) => { state.subscribe((msg) => {
if (msg.type == MESSAGES.EVAL_RESULT) { if (msg.type == MESSAGES.EVAL_RESULT) {
if (typeof msg.value !== "undefined") { if (msg.success) {
evalStatusEl.classList.add("success"); evalStatusEl.classList.add("success");
evalStatusEl.classList.remove("error"); evalStatusEl.classList.remove("error");
evalStatusEl.innerHTML = `Result: ${msg.value}`; evalStatusEl.innerHTML = `Result: ${msg.value}`;

View File

@ -147,7 +147,15 @@ parser = /*
return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") }; return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") };
}, },
peg$c3 = function(instruction) { peg$c3 = function(instruction) {
return instruction; let x = 0;
let y = 0;
if (instruction.label) {
x = instruction.label.godel;
y = instruction.instruction.godel;
} else {
y = instruction.godel;
}
return { instruction, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
}, },
peg$c4 = function(label, instruction) { peg$c4 = function(label, instruction) {
return { label, instruction }; return { label, instruction };
@ -159,11 +167,11 @@ parser = /*
peg$c9 = function(label) { peg$c9 = function(label) {
return label; return label;
}, },
peg$c10 = function(conditional) { return { conditional }; }, peg$c10 = function(conditional) { return { conditional, godel: conditional.godel }; },
peg$c11 = function(assignment) { return { assignment }; }, peg$c11 = function(assignment) { return { assignment, godel: assignment.godel }; },
peg$c12 = function(goto) { return { goto }; }, peg$c12 = function(goto) { return { goto, godel: goto.godel }; },
peg$c13 = function(label) { peg$c13 = function(label) {
return { label }; return { label, godel: label.godel + 2 };
}, },
peg$c14 = "IF", peg$c14 = "IF",
peg$c15 = peg$literalExpectation("IF", false), peg$c15 = peg$literalExpectation("IF", false),
@ -172,33 +180,41 @@ parser = /*
peg$c18 = "0", peg$c18 = "0",
peg$c19 = peg$literalExpectation("0", false), peg$c19 = peg$literalExpectation("0", false),
peg$c20 = function(variable, goto) { peg$c20 = function(variable, goto) {
return { variable, goto }; const y = variable.godel - 1;
const x = goto.godel;
return { variable, goto, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
}, },
peg$c21 = "<-", peg$c21 = "<-",
peg$c22 = peg$literalExpectation("<-", false), peg$c22 = peg$literalExpectation("<-", false),
peg$c23 = function(variable, expr) { peg$c23 = function(variable, expr) {
if (expr.left != variable) { if (expr.left.symbol != variable.symbol) {
error("left hand variable must match right hand"); error("left hand variable must match right hand");
} }
return { variable, expr }; const x = expr.instructionNumber;
const y = variable.godel - 1;
return { variable, expr, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
}, },
peg$c24 = "1", peg$c24 = "1",
peg$c25 = peg$literalExpectation("1", false), peg$c25 = peg$literalExpectation("1", false),
peg$c26 = function(left, opr) { peg$c26 = function(left, opr) {
return { left, opr }; const instructionNumber = { "+" : 1, "-" : 2 }[opr];
return { left, opr, instructionNumber };
}, },
peg$c27 = function(left) { peg$c27 = function(left) {
return { left }; return { left, instructionNumber: 0 };
}, },
peg$c28 = "Y", peg$c28 = "Y",
peg$c29 = peg$literalExpectation("Y", false), peg$c29 = peg$literalExpectation("Y", false),
peg$c30 = function(symbol) { return symbol }, peg$c30 = function(symbol) { return { symbol, godel: 1 }; },
peg$c31 = "X", peg$c31 = "X",
peg$c32 = peg$literalExpectation("X", false), peg$c32 = peg$literalExpectation("X", false),
peg$c33 = "Z", peg$c33 = "Z",
peg$c34 = peg$literalExpectation("Z", false), peg$c34 = peg$literalExpectation("Z", false),
peg$c35 = function(symbol, ind) { peg$c35 = function(symbol, ind) {
return symbol + ind; const index = parseInt(ind);
const order = ["X", "Z"];
const godel = index * order.length + order.indexOf(symbol);
return { symbol: symbol + ind, godel };
}, },
peg$c36 = "GOTO", peg$c36 = "GOTO",
peg$c37 = peg$literalExpectation("GOTO", false), peg$c37 = peg$literalExpectation("GOTO", false),
@ -208,16 +224,19 @@ parser = /*
peg$c41 = peg$literalExpectation("-", false), peg$c41 = peg$literalExpectation("-", false),
peg$c42 = /^[A-E]/, peg$c42 = /^[A-E]/,
peg$c43 = peg$classExpectation([["A", "E"]], false, false), peg$c43 = peg$classExpectation([["A", "E"]], false, false),
peg$c44 = "E", peg$c44 = function(symbol, ind) {
peg$c45 = peg$literalExpectation("E", false), const index = parseInt(ind);
peg$c46 = peg$otherExpectation("integer"), const godel = (symbol.charCodeAt(0) - "A".charCodeAt(0) + 1) + 5*(index-1);
peg$c47 = /^[0-9]/, return { symbol: symbol + ind, godel };
peg$c48 = peg$classExpectation([["0", "9"]], false, false), },
peg$c49 = function() { return parseInt(text(), 10); }, peg$c45 = peg$otherExpectation("integer"),
peg$c50 = peg$otherExpectation("whitespace"), peg$c46 = /^[0-9]/,
peg$c51 = /^[ \t]/, peg$c47 = peg$classExpectation([["0", "9"]], false, false),
peg$c52 = peg$classExpectation([" ", "\t"], false, false), peg$c48 = function() { return parseInt(text(), 10); },
peg$c53 = function() { }, peg$c49 = peg$otherExpectation("whitespace"),
peg$c50 = /^[ \t]/,
peg$c51 = peg$classExpectation([" ", "\t"], false, false),
peg$c52 = function() { },
peg$currPos = 0, peg$currPos = 0,
peg$savedPos = 0, peg$savedPos = 0,
@ -360,7 +379,7 @@ parser = /*
s0 = peg$currPos; s0 = peg$currPos;
s1 = []; s1 = [];
s2 = peg$parseLine(); s2 = peg$parseProgramInstruction();
if (s2 === peg$FAILED) { if (s2 === peg$FAILED) {
s2 = peg$parse_(); s2 = peg$parse_();
if (s2 === peg$FAILED) { if (s2 === peg$FAILED) {
@ -375,7 +394,7 @@ parser = /*
} }
while (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) {
s1.push(s2); s1.push(s2);
s2 = peg$parseLine(); s2 = peg$parseProgramInstruction();
if (s2 === peg$FAILED) { if (s2 === peg$FAILED) {
s2 = peg$parse_(); s2 = peg$parse_();
if (s2 === peg$FAILED) { if (s2 === peg$FAILED) {
@ -398,7 +417,7 @@ parser = /*
return s0; return s0;
} }
function peg$parseLine() { function peg$parseProgramInstruction() {
var s0, s1, s2, s3, s4; var s0, s1, s2, s3, s4;
s0 = peg$currPos; s0 = peg$currPos;
@ -895,58 +914,35 @@ parser = /*
var s0, s1, s2, s3; var s0, s1, s2, s3;
s0 = peg$currPos; s0 = peg$currPos;
s1 = peg$parseEND_LABEL(); if (peg$c42.test(input.charAt(peg$currPos))) {
if (s1 !== peg$FAILED) { s1 = input.charAt(peg$currPos);
peg$savedPos = s0; peg$currPos++;
s1 = peg$c30(s1); } else {
s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c43); }
} }
s0 = s1; if (s1 !== peg$FAILED) {
if (s0 === peg$FAILED) { s2 = [];
s0 = peg$currPos; s3 = peg$parseInteger();
if (peg$c42.test(input.charAt(peg$currPos))) { if (s3 !== peg$FAILED) {
s1 = input.charAt(peg$currPos); while (s3 !== peg$FAILED) {
peg$currPos++; s2.push(s3);
s3 = peg$parseInteger();
}
} else { } else {
s1 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c43); }
} }
if (s1 !== peg$FAILED) { if (s2 !== peg$FAILED) {
s2 = []; peg$savedPos = s0;
s3 = peg$parseInteger(); s1 = peg$c44(s1, s2);
if (s3 !== peg$FAILED) { s0 = s1;
while (s3 !== peg$FAILED) {
s2.push(s3);
s3 = peg$parseInteger();
}
} else {
s2 = peg$FAILED;
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
s1 = peg$c35(s1, s2);
s0 = s1;
} else {
peg$currPos = s0;
s0 = peg$FAILED;
}
} else { } else {
peg$currPos = s0; peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
} }
}
return s0;
}
function peg$parseEND_LABEL() {
var s0;
if (input.charCodeAt(peg$currPos) === 69) {
s0 = peg$c44;
peg$currPos++;
} else { } else {
peg$currPos = s0;
s0 = peg$FAILED; s0 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c45); }
} }
return s0; return s0;
@ -958,22 +954,22 @@ parser = /*
peg$silentFails++; peg$silentFails++;
s0 = peg$currPos; s0 = peg$currPos;
s1 = []; s1 = [];
if (peg$c47.test(input.charAt(peg$currPos))) { if (peg$c46.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos); s2 = input.charAt(peg$currPos);
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c48); } if (peg$silentFails === 0) { peg$fail(peg$c47); }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
while (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) {
s1.push(s2); s1.push(s2);
if (peg$c47.test(input.charAt(peg$currPos))) { if (peg$c46.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos); s2 = input.charAt(peg$currPos);
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c48); } if (peg$silentFails === 0) { peg$fail(peg$c47); }
} }
} }
} else { } else {
@ -981,13 +977,13 @@ parser = /*
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s1 = peg$c49(); s1 = peg$c48();
} }
s0 = s1; s0 = s1;
peg$silentFails--; peg$silentFails--;
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c46); } if (peg$silentFails === 0) { peg$fail(peg$c45); }
} }
return s0; return s0;
@ -999,22 +995,22 @@ parser = /*
peg$silentFails++; peg$silentFails++;
s0 = peg$currPos; s0 = peg$currPos;
s1 = []; s1 = [];
if (peg$c51.test(input.charAt(peg$currPos))) { if (peg$c50.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos); s2 = input.charAt(peg$currPos);
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c52); } if (peg$silentFails === 0) { peg$fail(peg$c51); }
} }
if (s2 !== peg$FAILED) { if (s2 !== peg$FAILED) {
while (s2 !== peg$FAILED) { while (s2 !== peg$FAILED) {
s1.push(s2); s1.push(s2);
if (peg$c51.test(input.charAt(peg$currPos))) { if (peg$c50.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos); s2 = input.charAt(peg$currPos);
peg$currPos++; peg$currPos++;
} else { } else {
s2 = peg$FAILED; s2 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c52); } if (peg$silentFails === 0) { peg$fail(peg$c51); }
} }
} }
} else { } else {
@ -1022,13 +1018,13 @@ parser = /*
} }
if (s1 !== peg$FAILED) { if (s1 !== peg$FAILED) {
peg$savedPos = s0; peg$savedPos = s0;
s1 = peg$c53(); s1 = peg$c52();
} }
s0 = s1; s0 = s1;
peg$silentFails--; peg$silentFails--;
if (s0 === peg$FAILED) { if (s0 === peg$FAILED) {
s1 = peg$FAILED; s1 = peg$FAILED;
if (peg$silentFails === 0) { peg$fail(peg$c50); } if (peg$silentFails === 0) { peg$fail(peg$c49); }
} }
return s0; return s0;