def test_match_item(self): self.assertEqual( match_item(self.START).parse([self.START]), self.START) with self.assertRaises(ParseError) as err: match_item(self.START, "START").parse([]) ex = err.exception self.assertEqual(str(ex), "expected 'START' at 0")
def test_parse_tokens(self): other_vals = parsy_test_item(lambda i: i not in [self.START, self.STOP], "not START/STOP") bracketed = match_item(self.START) >> other_vals.many() << match_item(self.STOP) stream = [self.START, "hello", 1, 2, "goodbye", self.STOP] result = bracketed.parse(stream) self.assertEqual(result, ["hello", 1, 2, "goodbye"])
def pCAT_PAR(): """ A parsy parser and translator of parenthesized depccg categories into abstract representations of CG categories. """ yield parsy.match_item("(") cat = yield pCAT yield parsy.match_item(")") return cat
def multiplicative(): res = yield simple op = match_item('*') | match_item('/') while True: operation = yield op | success('') if not operation: break operand = yield simple if operation == '*': res *= operand elif operation == '/': res /= operand return res
def additive(): res = yield multiplicative sign = match_item('+') | match_item('-') while True: operation = yield sign | success('') if not operation: break operand = yield multiplicative if operation == '+': res += operand elif operation == '-': res -= operand return res
def eval_tokens(tokens): # This function parses and evaluates at the same time. lparen = match_item('(') rparen = match_item(')') @generate def additive(): res = yield multiplicative sign = match_item('+') | match_item('-') while True: operation = yield sign | success('') if not operation: break operand = yield multiplicative if operation == '+': res += operand elif operation == '-': res -= operand return res @generate def multiplicative(): res = yield simple op = match_item('*') | match_item('/') while True: operation = yield op | success('') if not operation: break operand = yield simple if operation == '*': res *= operand elif operation == '/': res /= operand return res @generate def number(): sign = yield match_item('+') | match_item('-') | success('+') value = yield test_item(lambda x: isinstance(x, (int, float)), 'number') return value if sign == '+' else -value expr = additive simple = (lparen >> expr << rparen) | number return expr.parse(tokens)
def pCAT_COMP_LEFT(): """ A parsy parser and translator of left-functor depccg categories into abstract representations of CG categories. Examples -------- "S[m]\\PP[s]\\PP[o]" -> { "type": "L", "antecedent": { "type": "Base", "lit": "PPo", }, "consequence": { "type": "L": "antecedent": { "type": "Base", "lit": "PPs", }, "consequence": { "type": "Base", "lit": "Sm", }, } """ cat1 = yield pCAT_COMP_RIGHT cat_others = yield ( parsy.match_item("\\") >> ( pCAT_COMP_RIGHT ) ).many() res = cat1 for cat_next in cat_others: res = { "type": "L", "antecedent": cat_next, "consequence": res, } return res
"", "nearby tickets:", "3,9,18", "15,1,5", "5,14,9", "", ] ) # Parsing Combinators optional_whitespace = regex(r"\s*") word = regex(r"\w+") number = regex(r"[-+]?\d+").map(int) rule_name = (letter | match_item(" ")).at_least(1).map(lambda x: "".join(x)) range_ = seq(number, match_item("-") >> number).map(lambda x: range(x[0], x[1] + 1)) range_pair = seq(range_, whitespace >> string("or") >> whitespace >> range_) rule = seq(rule_name, match_item(":") >> whitespace >> range_pair) rules = rule.sep_by(match_item("\n")).map(dict) fields = number.sep_by(match_item(","), min=1) your_ticket = string("your ticket:\n") >> fields nearby_tickets = string("nearby tickets:\n") >> fields.sep_by(match_item("\n")) all_of_it = ( seq(rules, string("\n\n") >> your_ticket, string("\n\n") >> nearby_tickets) << match_item("\n").optional() )
def statement(): cmd_name = yield test_item(lambda i: i in commands.keys(), "command") parameter = yield test_item(lambda i: isinstance(i, int), "number") yield match_item('\n') return commands[cmd_name](int(parameter))
from pyrsistent import s as S from pyrsistent import v as V from utils import puzzle_input example = "\n".join([ "mxmxvkd kfcds sqjhc nhms (contains dairy, fish)", "trh fvjkl sbzzf mxmxvkd (contains dairy)", "sqjhc fvjkl (contains soy)", "sqjhc mxmxvkd sbzzf (contains fish)", ]) ingredient = regex(r"\w+") allergen = regex(r"\w+") ingredient_list = ingredient.sep_by(match_item(" ")).map(set) allergen_list = ( string("contains") >> whitespace >> allergen.sep_by(string(", ")).map(set)) ingredients_line = seq( ingredient_list, whitespace >> match_item("(") >> allergen_list << match_item(")")).map(tuple) ingredients_lines = ( ingredients_line.sep_by(match_item("\n")) << match_item("\n").optional()) with puzzle_input(21, example, False) as f: data = ingredients_lines.parse(f.read()) # print(data) ingredients = reduce(op.or_, (i[0] for i in data)) allergens = reduce(op.or_, (i[1] for i in data))
def number(): sign = yield match_item('+') | match_item('-') | success('+') value = yield test_item(lambda x: isinstance(x, (int, float)), 'number') return value if sign == '+' else -value
if v == "X": mask_and |= 1 << i else: mask_or |= int(v) << i return mask_and, mask_or # Parsing Combinators optional_whitespace = regex(r"\s*") word = regex(r"\w+") number = regex(r"[-+]?\d+").map(int) mask_inst = seq( string("mask"), whitespace >> match_item("=") >> whitespace >> char_from("X01").at_least(1).map(build_mask), ) mem_inst = seq( string("mem"), match_item("[") >> number << match_item("]"), whitespace >> match_item("=") >> whitespace >> number, ) instruction = mask_inst | mem_inst program = instruction.sep_by(string("\n")) << string("\n").optional() with puzzle_input(14, example2, False) as f: data, remain = program.parse_partial(f.read()) # pprint(data) print("\n\n\nremaining:", repr(remain))