This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 

116 řádky
3.0 KiB

  1. import re
  2. import sys
  3. from .utils import get_regexp_width
  4. Py36 = (sys.version_info[:2] >= (3, 6))
  5. ###{standalone
  6. def is_terminal(sym):
  7. return sym.isupper()
  8. class GrammarError(Exception):
  9. pass
  10. class ParseError(Exception):
  11. pass
  12. class UnexpectedToken(ParseError):
  13. def __init__(self, token, expected, seq, index, considered_rules=None):
  14. self.token = token
  15. self.expected = expected
  16. self.line = getattr(token, 'line', '?')
  17. self.column = getattr(token, 'column', '?')
  18. self.considered_rules = considered_rules
  19. try:
  20. context = ' '.join(['%r(%s)' % (t.value, t.type) for t in seq[index:index+5]])
  21. except AttributeError:
  22. context = seq[index:index+5]
  23. except TypeError:
  24. context = "<no context>"
  25. message = ("Unexpected token %r at line %s, column %s.\n"
  26. "Expected: %s\n"
  27. "Context: %s" % (token, self.line, self.column, expected, context))
  28. super(UnexpectedToken, self).__init__(message)
  29. ###}
  30. class LexerConf:
  31. def __init__(self, tokens, ignore=(), postlex=None, callbacks=None):
  32. self.tokens = tokens
  33. self.ignore = ignore
  34. self.postlex = postlex
  35. self.callbacks = callbacks or {}
  36. class ParserConf:
  37. def __init__(self, rules, callback, start):
  38. self.rules = rules
  39. self.callback = callback
  40. self.start = start
  41. class Pattern(object):
  42. def __init__(self, value, flags=()):
  43. self.value = value
  44. self.flags = frozenset(flags)
  45. def __repr__(self):
  46. return repr(self.to_regexp())
  47. # Pattern Hashing assumes all subclasses have a different priority!
  48. def __hash__(self):
  49. return hash((type(self), self.value, self.flags))
  50. def __eq__(self, other):
  51. return type(self) == type(other) and self.value == other.value and self.flags == other.flags
  52. if Py36:
  53. # Python 3.6 changed syntax for flags in regular expression
  54. def _get_flags(self, value):
  55. for f in self.flags:
  56. value = ('(?%s:%s)' % (f, value))
  57. return value
  58. else:
  59. def _get_flags(self, value):
  60. for f in self.flags:
  61. value = ('(?%s)' % f) + value
  62. return value
  63. class PatternStr(Pattern):
  64. def to_regexp(self):
  65. return self._get_flags(re.escape(self.value))
  66. @property
  67. def min_width(self):
  68. return len(self.value)
  69. max_width = min_width
  70. class PatternRE(Pattern):
  71. def to_regexp(self):
  72. return self._get_flags(self.value)
  73. @property
  74. def min_width(self):
  75. return get_regexp_width(self.to_regexp())[0]
  76. @property
  77. def max_width(self):
  78. return get_regexp_width(self.to_regexp())[1]
  79. class TokenDef(object):
  80. def __init__(self, name, pattern, priority=1):
  81. assert isinstance(pattern, Pattern), pattern
  82. self.name = name
  83. self.pattern = pattern
  84. self.priority = priority
  85. def __repr__(self):
  86. return '%s(%r, %r)' % (type(self).__name__, self.name, self.pattern)