This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

115 linhas
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):
  14. self.token = token
  15. self.expected = expected
  16. self.line = getattr(token, 'line', '?')
  17. self.column = getattr(token, 'column', '?')
  18. try:
  19. context = ' '.join(['%r(%s)' % (t.value, t.type) for t in seq[index:index+5]])
  20. except AttributeError:
  21. context = seq[index:index+5]
  22. except TypeError:
  23. context = "<no context>"
  24. message = ("Unexpected token %r at line %s, column %s.\n"
  25. "Expected: %s\n"
  26. "Context: %s" % (token, self.line, self.column, expected, context))
  27. super(UnexpectedToken, self).__init__(message)
  28. ###}
  29. class LexerConf:
  30. def __init__(self, tokens, ignore=(), postlex=None, callbacks=None):
  31. self.tokens = tokens
  32. self.ignore = ignore
  33. self.postlex = postlex
  34. self.callbacks = callbacks or {}
  35. class ParserConf:
  36. def __init__(self, rules, callback, start):
  37. self.rules = rules
  38. self.callback = callback
  39. self.start = start
  40. class Pattern(object):
  41. def __init__(self, value, flags=()):
  42. self.value = value
  43. self.flags = frozenset(flags)
  44. def __repr__(self):
  45. return repr(self.to_regexp())
  46. # Pattern Hashing assumes all subclasses have a different priority!
  47. def __hash__(self):
  48. return hash((type(self), self.value, self.flags))
  49. def __eq__(self, other):
  50. return type(self) == type(other) and self.value == other.value and self.flags == other.flags
  51. if Py36:
  52. # Python 3.6 changed syntax for flags in regular expression
  53. def _get_flags(self, value):
  54. for f in self.flags:
  55. value = ('(?%s:%s)' % (f, value))
  56. return value
  57. else:
  58. def _get_flags(self, value):
  59. for f in self.flags:
  60. value = ('(?%s)' % f) + 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 get_regexp_width(self.to_regexp())[0]
  75. @property
  76. def max_width(self):
  77. return get_regexp_width(self.to_regexp())[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)