Program = lines: (Line / (_/[\n]))* { return { instructions: lines.filter((line) => typeof line !== "string" || line.trim() != "") }; } Line = _? instruction: (LabeledInstruction / Instruction) _? [\n]? { return instruction; } LabeledInstruction = label:Label _ instruction:Instruction { return { label, instruction }; } Label = "[" _? label:LABEL_V _? "]" { return label; } Instruction = conditional: Conditional { return { conditional }; } / assignment: Assignment { return { assignment }; } / goto: Goto { return { goto }; } Goto = GOTO _ label: LABEL_V { return { label }; } Conditional = "IF" _ variable: VAR _? "!=" _? "0" _ goto: Goto { return { variable, goto }; } Assignment = variable: VAR _ "<-" _ expr: Expression { if (expr.left != variable) { error("left hand variable must match right hand"); } return { variable, expr }; } Expression = left: VAR _ opr: OPERATION _ "1" { return { left, opr }; } / left: VAR { return { left }; } VAR = symbol:"Y" { return symbol } / symbol:("X" / "Z") ind:Integer+ { return symbol + ind; } GOTO = "GOTO" OPERATION = "+" / "-" LABEL_V = symbol:END_LABEL { return symbol } / symbol:[A-E] ind:Integer+ { return symbol + ind; } END_LABEL = "E" Integer "integer" = [0-9]+ { return parseInt(text(), 10); } _ "whitespace" = [ \t]+ { }