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.

97 lines
3.1 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 UnexpectedInput(LarkError):
  12. pos_in_stream = None
  13. def get_context(self, text, span=40):
  14. pos = self.pos_in_stream
  15. start = max(pos - span, 0)
  16. end = pos + span
  17. before = text[start:pos].rsplit('\n', 1)[-1]
  18. after = text[pos:end].split('\n', 1)[0]
  19. return before + after + '\n' + ' ' * len(before) + '^\n'
  20. def match_examples(self, parse_fn, examples):
  21. """ Given a parser instance and a dictionary mapping some label with
  22. some malformed syntax examples, it'll return the label for the
  23. example that bests matches the current error.
  24. """
  25. assert self.state is not None, "Not supported for this exception"
  26. candidate = None
  27. for label, example in examples.items():
  28. assert not isinstance(example, STRING_TYPE)
  29. for malformed in example:
  30. try:
  31. parse_fn(malformed)
  32. except UnexpectedInput as ut:
  33. if ut.state == self.state:
  34. try:
  35. if ut.token == self.token: # Try exact match first
  36. return label
  37. except AttributeError:
  38. pass
  39. if not candidate:
  40. candidate = label
  41. return candidate
  42. class UnexpectedCharacters(LexError, UnexpectedInput):
  43. def __init__(self, seq, lex_pos, line, column, allowed=None, considered_tokens=None, state=None):
  44. message = "No terminal defined for '%s' at line %d col %d" % (seq[lex_pos], line, column)
  45. self.line = line
  46. self.column = column
  47. self.allowed = allowed
  48. self.considered_tokens = considered_tokens
  49. self.pos_in_stream = lex_pos
  50. self.state = state
  51. message += '\n\n' + self.get_context(seq)
  52. if allowed:
  53. message += '\nExpecting: %s\n' % allowed
  54. super(UnexpectedCharacters, self).__init__(message)
  55. class UnexpectedToken(ParseError, UnexpectedInput):
  56. def __init__(self, token, expected, considered_rules=None, state=None):
  57. self.token = token
  58. self.expected = expected # XXX str shouldn't necessary
  59. self.line = getattr(token, 'line', '?')
  60. self.column = getattr(token, 'column', '?')
  61. self.considered_rules = considered_rules
  62. self.state = state
  63. self.pos_in_stream = getattr(token, 'pos_in_stream', None)
  64. message = ("Unexpected token %r at line %s, column %s.\n"
  65. "Expected one of: \n\t* %s\n"
  66. % (token, self.line, self.column, '\n\t* '.join(self.expected)))
  67. super(UnexpectedToken, self).__init__(message)
  68. class VisitError(LarkError):
  69. def __init__(self, tree, orig_exc):
  70. self.tree = tree
  71. self.orig_exc = orig_exc
  72. message = 'Error trying to process rule "%s":\n\n%s' % (tree.data, orig_exc)
  73. super(VisitError, self).__init__(message)
  74. ###}