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.

107 lines
3.5 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):
  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
  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. except AttributeError:
  43. pass
  44. if not candidate:
  45. candidate = label
  46. return candidate
  47. class UnexpectedCharacters(LexError, UnexpectedInput):
  48. def __init__(self, seq, lex_pos, line, column, allowed=None, considered_tokens=None, state=None, token_history=None):
  49. message = "No terminal defined for '%s' at line %d col %d" % (seq[lex_pos], line, column)
  50. self.line = line
  51. self.column = column
  52. self.allowed = allowed
  53. self.considered_tokens = considered_tokens
  54. self.pos_in_stream = lex_pos
  55. self.state = state
  56. message += '\n\n' + self.get_context(seq)
  57. if allowed:
  58. message += '\nExpecting: %s\n' % allowed
  59. if token_history:
  60. message += '\nPrevious tokens: %s\n' % ', '.join(repr(t) for t in token_history)
  61. super(UnexpectedCharacters, self).__init__(message)
  62. class UnexpectedToken(ParseError, UnexpectedInput):
  63. def __init__(self, token, expected, considered_rules=None, state=None):
  64. self.token = token
  65. self.expected = expected # XXX str shouldn't necessary
  66. self.line = getattr(token, 'line', '?')
  67. self.column = getattr(token, 'column', '?')
  68. self.considered_rules = considered_rules
  69. self.state = state
  70. self.pos_in_stream = getattr(token, 'pos_in_stream', None)
  71. message = ("Unexpected token %r at line %s, column %s.\n"
  72. "Expected one of: \n\t* %s\n"
  73. % (token, self.line, self.column, '\n\t* '.join(self.expected)))
  74. super(UnexpectedToken, self).__init__(message)
  75. class VisitError(LarkError):
  76. def __init__(self, rule, obj, orig_exc):
  77. self.obj = obj
  78. self.orig_exc = orig_exc
  79. message = 'Error trying to process rule "%s":\n\n%s' % (rule, orig_exc)
  80. super(VisitError, self).__init__(message)
  81. ###}