This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

55 lines
1.6 KiB

  1. from .lexer import Lexer
  2. from .parsers.lalr_analysis import GrammarAnalyzer
  3. from .common import is_terminal
  4. from .parsers import lalr_parser, earley
  5. class WithLexer:
  6. def __init__(self, lexer_conf):
  7. self.lexer_conf = lexer_conf
  8. self.lexer = Lexer(lexer_conf.tokens, ignore=lexer_conf.ignore)
  9. def lex(self, text):
  10. stream = self.lexer.lex(text)
  11. if self.lexer_conf.postlex:
  12. return self.lexer_conf.postlex.process(stream)
  13. else:
  14. return stream
  15. class LALR(WithLexer):
  16. def __init__(self, lexer_conf, parser_conf):
  17. WithLexer.__init__(self, lexer_conf)
  18. analyzer = GrammarAnalyzer(parser_conf.rules, parser_conf.start)
  19. analyzer.analyze()
  20. self.parser = lalr_parser.Parser(analyzer, parser_conf.callback)
  21. def parse(self, text):
  22. tokens = list(self.lex(text))
  23. return self.parser.parse(tokens)
  24. class Earley(WithLexer):
  25. def __init__(self, lexer_conf, parser_conf):
  26. WithLexer.__init__(self, lexer_conf)
  27. rules = [{'name':n,
  28. 'symbols': self._process_expansion(x),
  29. 'postprocess': getattr(parser_conf.callback, a)}
  30. for n,x,a in parser_conf.rules]
  31. self.parser = earley.Parser(rules, parser_conf.start)
  32. def parse(self, text):
  33. tokens = list(self.lex(text))
  34. res = self.parser.parse(tokens)
  35. assert len(res) ==1 , 'Ambiguious Parse! Not handled yet'
  36. return res[0]
  37. @staticmethod
  38. def _process_expansion(x):
  39. return [{'literal': s} if is_terminal(s) else s for s in x]
  40. ENGINE_DICT = { 'lalr': LALR, 'earley': Earley }