This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

137 satır
3.6 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[0] == '$'
  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=None):
  40. self.value = value
  41. self.flags = 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))
  47. def __eq__(self, other):
  48. return type(self) == type(other) and self.value == other.value
  49. if Py36:
  50. # Python 3.6 changed syntax for flags in regular expression
  51. def _get_flags(self, value):
  52. if self.flags:
  53. assert len(self.flags) == 1
  54. return ('(?%s:%s)' % (self.flags[0], value))
  55. return value
  56. else:
  57. def _get_flags(self, value):
  58. if self.flags:
  59. assert len(self.flags) == 1
  60. return ('(?%s)' % self.flags) + value
  61. return value
  62. class PatternStr(Pattern):
  63. def to_regexp(self):
  64. return self._get_flags(re.escape(self.value))
  65. @property
  66. def min_width(self):
  67. return len(self.value)
  68. max_width = min_width
  69. class PatternRE(Pattern):
  70. def to_regexp(self):
  71. return self._get_flags(self.value)
  72. @property
  73. def min_width(self):
  74. return sre_parse.parse(self.to_regexp()).getwidth()[0]
  75. @property
  76. def max_width(self):
  77. return sre_parse.parse(self.to_regexp()).getwidth()[1]
  78. class TokenDef(object):
  79. def __init__(self, name, pattern, priority=1):
  80. assert isinstance(pattern, Pattern), pattern
  81. self.name = name
  82. self.pattern = pattern
  83. self.priority = priority
  84. def __repr__(self):
  85. return '%s(%r, %r)' % (type(self).__name__, self.name, self.pattern)
  86. class Terminal:
  87. def __init__(self, data):
  88. self.data = data
  89. def __repr__(self):
  90. return '%r' % self.data
  91. def __eq__(self, other):
  92. return isinstance(other, type(self)) and self.data == other.data
  93. def __hash__(self):
  94. return hash(self.data)
  95. class Terminal_Regexp(Terminal):
  96. def __init__(self, name, regexp):
  97. Terminal.__init__(self, regexp)
  98. self.name = name
  99. self.match = re.compile(regexp).match
  100. class Terminal_Token(Terminal):
  101. def match(self, other):
  102. return self.data == other.type