def main(): grammar = Grammar() # core grammar grammar.extend(create_core_grammar()) # combinator grammars grammar.extend(create_combinator_grammar()) # add macro grammar. e.g. expr grammar.add_parser('macro', 'name:Name "::=" combinator: combinator_sequence') # # dump grammar # dump_grammar(sys.stdout, grammar) content = """ expr ::= 1 2 3 ; | def main(): pass """.strip() # scanner = DefaultScanner(grammar, '<example>', content) parser = Parser(scanner) try: parser.parse(grammar.parselets['macro']) except ParserError as ex: ex.to_stream(create_writer(sys.stderr), content) exit(1)
def __call__(self, parser: Parser, priority: int) -> ParseletResult: parselets = self.prefixes.get(parser.current_token.id, ()) if not parselets: raise parser.error(self.prefix_tokens) left, error = parser.choice(parselets) while True: parselets = tuple( itertools.takewhile( lambda parselet: priority < parselet.priority, self.postfixes.get(parser.current_token.id, ()))) if not parselets: break try: left, last_error = parser.choice(parselets, left) except ParserError as last_error: error = ParserError.merge(error, last_error) break else: error = ParserError.merge(error, last_error) return left, error
def __call__(self, parser: Parser, context: Parselet) -> CombinatorResult: items = [] error = None namespace = {} while True: try: with parser.backtrack(): result, last_namespace, last_error = self.combinator( parser, context) except ParserError as last_error: error = ParserError.merge(error, last_error) break else: error = ParserError.merge(error, last_error) items.append(result) for name, value in last_namespace.items(): namespace[name] = [*namespace[name], *value ] if name in namespace else value return tuple(items), namespace, error
def parse_expr(grammar: Grammar, content: str): scanner = DefaultScanner(grammar, '<example>', content) parser = Parser(scanner) result = parser.parse(grammar.parselets['expr']) return result
def __call__(self, parser: Parser, context: Parselet) -> CombinatorResult: result, error = parser.parselet(self.parser_id, self.priority) return result, {}, error
def __call__(self, parser: Parser, context: Parselet) -> CombinatorResult: return parser.consume(self.token_id), {}, None
def __call__(self, parser: Parser, context: Parselet) -> CombinatorResult: with parser.backtrack(): try: return self.combinator(parser, context) except ParserError as error: return None, {}, error
def parse_combinator(content: str): scanner = DefaultScanner(combinator_grammar, '<example>', content) parser = Parser(scanner) return parser.parse(combinator_grammar.parselets['combinator_sequence'])
def __call__(self, parser: Parser, priority: int) -> ParseletResult: return parser.choice(self.__parselets)