This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

137 righe
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