2023-11-17 14:09:44 -05:00
|
|
|
Program = lines: (ProgramInstruction / (_/[\n]))* {
|
2023-11-16 21:06:35 -05:00
|
|
|
return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") };
|
2023-11-16 16:56:56 -05:00
|
|
|
}
|
|
|
|
|
2023-11-17 14:09:44 -05:00
|
|
|
ProgramInstruction = _? instruction: (LabeledInstruction / Instruction) _? [\n]? {
|
|
|
|
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) };
|
2023-11-16 16:56:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
LabeledInstruction = label:Label _ instruction:Instruction {
|
|
|
|
return { label, instruction };
|
|
|
|
}
|
|
|
|
|
|
|
|
Label = "[" _? label:LABEL_V _? "]" {
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
|
2023-11-17 14:09:44 -05:00
|
|
|
Instruction = conditional: Conditional { return { conditional, godel: conditional.godel }; }
|
|
|
|
/ assignment: Assignment { return { assignment, godel: assignment.godel }; }
|
|
|
|
/ goto: Goto { return { goto, godel: goto.godel }; }
|
2023-11-16 16:56:56 -05:00
|
|
|
|
2023-11-16 21:06:35 -05:00
|
|
|
Goto = GOTO _ label: LABEL_V {
|
2023-11-17 14:09:44 -05:00
|
|
|
return { label, godel: label.godel + 2 };
|
2023-11-16 21:06:35 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Conditional = "IF" _ variable: VAR _? "!=" _? "0" _ goto: Goto {
|
2023-11-17 14:09:44 -05:00
|
|
|
const y = variable.godel - 1;
|
|
|
|
const x = goto.godel;
|
|
|
|
return { variable, goto, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
|
2023-11-16 16:56:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Assignment = variable: VAR _ "<-" _ expr: Expression {
|
2023-11-17 14:09:44 -05:00
|
|
|
if (expr.left.symbol != variable.symbol) {
|
2023-11-16 16:56:56 -05:00
|
|
|
error("left hand variable must match right hand");
|
|
|
|
}
|
2023-11-17 14:09:44 -05:00
|
|
|
const x = expr.instructionNumber;
|
|
|
|
const y = variable.godel - 1;
|
|
|
|
return { variable, expr, godel: ((2 ** x) * ((2 * y) + 1) - 1) };
|
2023-11-16 16:56:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
Expression = left: VAR _ opr: OPERATION _ "1" {
|
2023-11-17 14:09:44 -05:00
|
|
|
const instructionNumber = { "+" : 1, "-" : 2 }[opr];
|
|
|
|
return { left, opr, instructionNumber };
|
2023-11-16 21:06:35 -05:00
|
|
|
} / left: VAR {
|
2023-11-17 14:09:44 -05:00
|
|
|
return { left, instructionNumber: 0 };
|
2023-11-16 16:56:56 -05:00
|
|
|
}
|
|
|
|
|
2023-11-17 14:09:44 -05:00
|
|
|
VAR = symbol:"Y" { return { symbol, godel: 1 }; } / symbol:("X" / "Z") ind:Integer+ {
|
|
|
|
const index = parseInt(ind);
|
|
|
|
const order = ["X", "Z"];
|
|
|
|
const godel = index * order.length + order.indexOf(symbol);
|
|
|
|
return { symbol: symbol + ind, godel };
|
2023-11-16 16:56:56 -05:00
|
|
|
}
|
|
|
|
|
2023-11-16 21:06:35 -05:00
|
|
|
GOTO = "GOTO"
|
|
|
|
|
2023-11-16 16:56:56 -05:00
|
|
|
OPERATION = "+" / "-"
|
|
|
|
|
2023-11-16 21:06:35 -05:00
|
|
|
LABEL_V = symbol:END_LABEL { return symbol } / symbol:[A-E] ind:Integer+ {
|
2023-11-17 14:09:44 -05:00
|
|
|
const index = parseInt(ind);
|
|
|
|
const godel = (symbol.charCodeAt(0) - "A".charCodeAt(0) + 1) + 5*(index-1);
|
|
|
|
return { symbol: symbol + ind, godel };
|
2023-11-16 16:56:56 -05:00
|
|
|
}
|
|
|
|
|
2023-11-17 14:09:44 -05:00
|
|
|
END_LABEL = "E1"
|
2023-11-16 21:06:35 -05:00
|
|
|
|
2023-11-16 16:56:56 -05:00
|
|
|
Integer "integer"
|
2023-11-16 21:06:35 -05:00
|
|
|
= [0-9]+ { return parseInt(text(), 10); }
|
2023-11-16 16:56:56 -05:00
|
|
|
|
2023-11-16 21:06:35 -05:00
|
|
|
_ "whitespace" = [ \t]+ { }
|