def specific_pc_parser(pc): """ Make a parser for a specific PC. """ name = epp.literal(misc.normalize(pc.name)) aliases = epp.multi(pc.aliases) eff = epp.effect(lambda val, st: val.update({Capture.PC: pc})) return epp.chain( [epp.branch([name, aliases], save_iterator=False), eff], save_iterator=False)
def variant(bg): """ Make a parser for the background. """ fullname = epp.literal(misc.normalize(bg.name)) shortname = epp.literal(misc.normalize(bg.shortname)) eff = epp.effect(lambda val, st: val.update({Capture.BACKGROUND: bg})) return epp.chain( [epp.branch([fullname, shortname], save_iterator=False), eff], save_iterator=False)
def variant(species): """ Make a parser for the species. """ fullname = epp.literal(misc.normalize(species.name)) shortname = epp.literal(misc.normalize(species.shortname)) eff = epp.effect( lambda val, st: val.update({Capture.SPECIES: species})) return epp.chain( [epp.branch([fullname, shortname], save_iterator=False), eff], save_iterator=False)
def parser_generator(): """ Generate a PC parser. """ variants = map(specific_pc_parser, game.party.characters) catchall = epp.chain([ epp.greedy(epp.everything()), epp.effect(lambda val, st: val.update({Capture.PC: None})) ], save_iterator=False) return epp.branch(chain(variants, [catchall]))
def make_parser(alternative_strings, game): """ Create and return a parser that will be able to query 'game' GameState object for data and which grammar will be given by 'alternative_strings'. """ alternatives = deque() for string in alternative_strings: alternatives.append(_make_alternative(string, game)) return epp.branch(alternatives, save_iterator=False)
def _make_bg(game): """ Make a background parser. """ def variant(bg): """ Make a parser for the background. """ fullname = epp.literal(misc.normalize(bg.name)) shortname = epp.literal(misc.normalize(bg.shortname)) eff = epp.effect(lambda val, st: val.update({Capture.BACKGROUND: bg})) return epp.chain( [epp.branch([fullname, shortname], save_iterator=False), eff], save_iterator=False) catchall = epp.chain([ epp.greedy(epp.everything()), epp.effect(lambda val, st: val.update({Capture.BACKGROUND: None})) ], save_iterator=False) total = chain(map(variant, game.data.backgrounds), [catchall]) output_parser = epp.branch(total) return epp.chain( [epp.literal("{bg}"), epp.effect(lambda val, st: output_parser)], save_iterator=False)
def _make_alternative(string, game, require_eoi=True): """ Create and return a parser from a particular grammar. """ white = _make_whitespace() literal = _make_literal() optional = _make_optional(game) # capturing parsers bg = _make_bg(game) name = _make_name() pc = _make_pc(game) species = _make_species(game) topic = _make_topic() # parsers = deque() piece = epp.chain( [ epp.branch( [ # generic white, optional, literal, # captures bg, name, pc, species, topic ], save_iterator=False), epp.effect(lambda val, st: parsers.append(val)) ], save_iterator=False) total = epp.many(piece, 1) output = epp.parse(None, string, total) if output is None: raise RuntimeError(f"Failed to construct a parser from: '{string}'") if require_eoi: parsers.append(epp.end_of_input()) return epp.chain(parsers)
def _make_species(game): """ Make a species parser. """ def variant(species): """ Make a parser for the species. """ fullname = epp.literal(misc.normalize(species.name)) shortname = epp.literal(misc.normalize(species.shortname)) eff = epp.effect( lambda val, st: val.update({Capture.SPECIES: species})) return epp.chain( [epp.branch([fullname, shortname], save_iterator=False), eff], save_iterator=False) catchall = epp.chain([ epp.greedy(epp.everything()), epp.effect(lambda val, st: val.update({Capture.SPECIES: None})) ], save_iterator=False) total = chain(map(variant, game.data.species), [catchall]) output_parser = epp.branch(total) return epp.chain( [epp.literal("{species}"), epp.effect(lambda val, st: output_parser)], save_iterator=False)