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.

87 lines
2.8 KiB

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