This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

135 rader
3.5 KiB

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