This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

116 行
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)