This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

120 lines
4.2 KiB

  1. from .utils import STRING_TYPE
  2. ###{standalone
  3. class LarkError(Exception):
  4. pass
  5. class GrammarError(LarkError):
  6. pass
  7. class ParseError(LarkError):
  8. pass
  9. class LexError(LarkError):
  10. pass
  11. class UnexpectedEOF(ParseError):
  12. def __init__(self, expected):
  13. self.expected = expected
  14. message = ("Unexpected end-of-input. Expected one of: \n\t* %s\n" % '\n\t* '.join(x.name for x in self.expected))
  15. super(UnexpectedEOF, self).__init__(message)
  16. class UnexpectedInput(LarkError):
  17. pos_in_stream = None
  18. def get_context(self, text, span=40):
  19. pos = self.pos_in_stream
  20. start = max(pos - span, 0)
  21. end = pos + span
  22. before = text[start:pos].rsplit('\n', 1)[-1]
  23. after = text[pos:end].split('\n', 1)[0]
  24. return before + after + '\n' + ' ' * len(before) + '^\n'
  25. def match_examples(self, parse_fn, examples, token_type_match_fallback=False):
  26. """ Given a parser instance and a dictionary mapping some label with
  27. some malformed syntax examples, it'll return the label for the
  28. example that bests matches the current error.
  29. """
  30. assert self.state is not None, "Not supported for this exception"
  31. candidate = (None, False)
  32. for label, example in examples.items():
  33. assert not isinstance(example, STRING_TYPE)
  34. for malformed in example:
  35. try:
  36. parse_fn(malformed)
  37. except UnexpectedInput as ut:
  38. if ut.state == self.state:
  39. try:
  40. if ut.token == self.token: # Try exact match first
  41. return label
  42. if token_type_match_fallback:
  43. # Fallback to token types match
  44. if (ut.token.type == self.token.type) and not candidate[-1]:
  45. candidate = label, True
  46. except AttributeError:
  47. pass
  48. if not candidate[0]:
  49. candidate = label, False
  50. return candidate[0]
  51. class UnexpectedCharacters(LexError, UnexpectedInput):
  52. def __init__(self, seq, lex_pos, line, column, allowed=None, considered_tokens=None, state=None, token_history=None):
  53. message = "No terminal defined for '%s' at line %d col %d" % (seq[lex_pos], line, column)
  54. self.line = line
  55. self.column = column
  56. self.allowed = allowed
  57. self.considered_tokens = considered_tokens
  58. self.pos_in_stream = lex_pos
  59. self.state = state
  60. message += '\n\n' + self.get_context(seq)
  61. if allowed:
  62. message += '\nExpecting: %s\n' % allowed
  63. if token_history:
  64. message += '\nPrevious tokens: %s\n' % ', '.join(repr(t) for t in token_history)
  65. super(UnexpectedCharacters, self).__init__(message)
  66. class UnexpectedToken(ParseError, UnexpectedInput):
  67. def __init__(self, token, expected, considered_rules=None, state=None, puppet=None):
  68. self.token = token
  69. self.expected = expected # XXX str shouldn't necessary
  70. self.line = getattr(token, 'line', '?')
  71. self.column = getattr(token, 'column', '?')
  72. self.considered_rules = considered_rules
  73. self.state = state
  74. self.pos_in_stream = getattr(token, 'pos_in_stream', None)
  75. self.puppet = puppet
  76. message = ("Unexpected token %r at line %s, column %s.\n"
  77. "Expected one of: \n\t* %s\n"
  78. % (token, self.line, self.column, '\n\t* '.join(self.expected)))
  79. super(UnexpectedToken, self).__init__(message)
  80. class VisitError(LarkError):
  81. """VisitError is raised when visitors are interrupted by an exception
  82. It provides the following attributes for inspection:
  83. - obj: the tree node or token it was processing when the exception was raised
  84. - orig_exc: the exception that cause it to fail
  85. """
  86. def __init__(self, rule, obj, orig_exc):
  87. self.obj = obj
  88. self.orig_exc = orig_exc
  89. message = 'Error trying to process rule "%s":\n\n%s' % (rule, orig_exc)
  90. super(VisitError, self).__init__(message)
  91. ###}