def parse_program(): integer_arg = p.regex(r"[+-][0-9]+").parsecmap(int) expression = (((p.string("nop") << p.space()) + integer_arg) | ((p.string("acc") << p.space()) + integer_arg) | ((p.string("jmp") << p.space()) + integer_arg)) return (yield p.many(expression << p.optional(p.string("\n"))))
def bag_parser(): modifier = yield word yield p.space() color = yield word yield p.regex(r" bags?") return f"{modifier} {color}"
def line_parser(): color = yield bag_parser yield p.string(" contain") contents = yield p.many(p.space() >> (number << p.space()) + bag_parser << p.regex(r"[,.]")) return (color, contents)
def apply_args(ctor): return (parsec.space() .compose(parse_args.parsecmap(lambda args: ctor(*args))))
return '[reg %s]' % self.reg class Computer: def __init__(self, program, registers): self.program = program self.registers = registers self.ip = 0 def run_program(self): while self.ip < len(self.program): self.program[self.ip].apply(self) self.ip = self.ip + 1 parse_value = parsec.choice(parsec.letter().parsecmap(Register), parsec.regex(r'-?\d+').parsecmap(int).parsecmap(Literal)) parse_args = parsec.separated(parse_value, parsec.space(), 1, maxt=2) instructions = {'cpy': Cpy, 'inc': Inc, 'dec': Dec, 'jnz': Jnz} parse_instr = reduce(parsec.choice, [parsec.string(k).result(v) for (k, v) in instructions.items()]) def apply_args(ctor): return (parsec.space() .compose(parse_args.parsecmap(lambda args: ctor(*args)))) parse_line = parse_instr.bind(apply_args) def regex_parse(line): def arg(x): m = regex.match(r'-?\d+', x) if m: return Literal(int(x)) return Register(x)
def parse_list(): """Parse a list as a ()-enclosed sequence of expressions.""" yield parsec.string('(') vals = yield parsec.sepBy(parse_expr, parsec.many1(parsec.space())) yield parsec.string(')') return wtypes.List(vals)