def test_lex(cards): """ Test the lexer against the given cards' text, logging failures. """ card.map_multi(_lex, cards)
def parse_helper(cards, name, rulename, yesregex=None, noregex=None): """ Parse a given subset of text on a given subset of cards. This function may override some re flags on the provided regex objects. cards: An iterable of cards to search for matching text. To save time, the provided regexes will be used to pare down this list to just those that will actually have text to attempt to parse. name: The function will be named _parse_{name} and the results for card c will be saved to c.parsed_{name}. rulename: The name of the parser rule to run. yesregex: If provided, run the parser rule on each match within each line of the card. The text selected is group 1 if it exists, or group 0 (the entire match) otherwise. If not provided, use each line in its entirety. noregex: Any text found after considering yesregex (or its absence) is skipped if it matches this regex. """ def _parse_helper(c): """ Returns a pair (number of errors, set of unique errors). """ results = [] errors = 0 uerrors = set() for lineno, line in enumerate(c.rules.split('\n')): lineno += 1 if yesregex: texts = [ m.group(1) if m.groups() else m.group(0) for m in yesregex.finditer(line) ] else: texts = [line] if noregex: texts = [text for text in texts if not noregex.match(text)] for text in texts: p, parse_result = _parse(rulename, text, c.name, lineno) tree = parse_result.tree results.append(tree) if p.getNumberOfSyntaxErrors(): mcase = _crawl_tree_for_errors(c.name, lineno, text, tree) if mcase: uerrors.add(mcase) errors += 1 return (c.name, [t.toStringTree() for t in results], errors, uerrors) _parse_helper.__name__ = '_parse_{}'.format(name) if yesregex: pattern = yesregex.pattern if noregex: ccards = { card.get_card(c[0]) for c in card.search_text(pattern, cards=cards) if not noregex.match(c[1]) } else: ccards = { card.get_card(c[0]) for c in card.search_text(pattern, cards=cards) } elif noregex: ccards = { c for c in cards if not all(noregex.match(line) for line in c.rules.split('\n')) } else: ccards = set(cards) errors = 0 uerrors = set() plog.removeHandler(_stdout) # list of (cardname, parsed result trees, number of errors, set of errors) results = card.map_multi(_parse_helper, ccards) cprop = 'parsed_{}'.format(name) for cname, pc, e, u in results: setattr(card.get_card(cname), cprop, pc) errors += e uerrors |= u plog.addHandler(_stdout) print('{} total errors.'.format(errors)) if uerrors: print('{} unique cases missing.'.format(len(uerrors))) plog.debug('Missing cases: ' + '; '.join(sorted(uerrors)))
def parse_helper(cards, name, rulename, yesregex=None, noregex=None): """ Parse a given subset of text on a given subset of cards. This function may override some re flags on the provided regex objects. cards: An iterable of cards to search for matching text. To save time, the provided regexes will be used to pare down this list to just those that will actually have text to attempt to parse. name: The function will be named _parse_{name} and the results for card c will be saved to c.parsed_{name}. rulename: The name of the parser rule to run. yesregex: If provided, run the parser rule on each match within each line of the card. The text selected is group 1 if it exists, or group 0 (the entire match) otherwise. If not provided, use each line in its entirety. noregex: Any text found after considering yesregex (or its absence) is skipped if it matches this regex. """ def _parse_helper(c): """ Returns a pair (number of errors, set of unique errors). """ results = [] errors = 0 uerrors = set() for lineno, line in enumerate(c.rules.split('\n')): lineno += 1 if yesregex: texts = [m.group(1) if m.groups() else m.group(0) for m in yesregex.finditer(line)] else: texts = [line] if noregex: texts = [text for text in texts if not noregex.match(text)] for text in texts: p, parse_result = _parse(rulename, text, c.name, lineno) tree = parse_result.tree results.append(tree) if p.getNumberOfSyntaxErrors(): mcase = _crawl_tree_for_errors(c.name, lineno, text, tree) if mcase: uerrors.add(mcase) errors += 1 return (c.name, [t.toStringTree() for t in results], errors, uerrors) _parse_helper.__name__ = '_parse_{}'.format(name) if yesregex: pattern = yesregex.pattern if noregex: ccards = {card.get_card(c[0]) for c in card.search_text(pattern, cards=cards) if not noregex.match(c[1])} else: ccards = {card.get_card(c[0]) for c in card.search_text(pattern, cards=cards)} elif noregex: ccards = {c for c in cards if not all(noregex.match(line) for line in c.rules.split('\n'))} else: ccards = set(cards) errors = 0 uerrors = set() plog.removeHandler(_stdout) # list of (cardname, parsed result trees, number of errors, set of errors) results = card.map_multi(_parse_helper, ccards) cprop = 'parsed_{}'.format(name) for cname, pc, e, u in results: setattr(card.get_card(cname), cprop, pc) errors += e uerrors |= u plog.addHandler(_stdout) print('{} total errors.'.format(errors)) if uerrors: print('{} unique cases missing.'.format(len(uerrors))) plog.debug('Missing cases: ' + '; '.join(sorted(uerrors)))