parse_comment.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. from typing import TYPE_CHECKING
  2. from .utils.constants import JSONReturnType
  3. from .utils.json_context import ContextValues
  4. if TYPE_CHECKING:
  5. from .json_parser import JSONParser
  6. def parse_comment(self: "JSONParser") -> JSONReturnType:
  7. """
  8. Parse code-like comments:
  9. - "# comment": A line comment that continues until a newline.
  10. - "// comment": A line comment that continues until a newline.
  11. - "/* comment */": A block comment that continues until the closing delimiter "*/".
  12. The comment is skipped over and an empty string is returned so that comments do not interfere
  13. with the actual JSON elements.
  14. """
  15. char = self.get_char_at()
  16. termination_characters = ["\n", "\r"]
  17. if ContextValues.ARRAY in self.context.context:
  18. termination_characters.append("]")
  19. if ContextValues.OBJECT_VALUE in self.context.context:
  20. termination_characters.append("}")
  21. if ContextValues.OBJECT_KEY in self.context.context:
  22. termination_characters.append(":")
  23. # Line comment starting with #
  24. if char == "#":
  25. comment = ""
  26. while char and char not in termination_characters:
  27. comment += char
  28. self.index += 1
  29. char = self.get_char_at()
  30. self.log(f"Found line comment: {comment}, ignoring")
  31. # Comments starting with '/'
  32. elif char == "/":
  33. next_char = self.get_char_at(1)
  34. # Handle line comment starting with //
  35. if next_char == "/":
  36. comment = "//"
  37. self.index += 2 # Skip both slashes.
  38. char = self.get_char_at()
  39. while char and char not in termination_characters:
  40. comment += char
  41. self.index += 1
  42. char = self.get_char_at()
  43. self.log(f"Found line comment: {comment}, ignoring")
  44. # Handle block comment starting with /*
  45. elif next_char == "*":
  46. comment = "/*"
  47. self.index += 2 # Skip '/*'
  48. while True:
  49. char = self.get_char_at()
  50. if not char:
  51. self.log("Reached end-of-string while parsing block comment; unclosed block comment.")
  52. break
  53. comment += char
  54. self.index += 1
  55. if comment.endswith("*/"):
  56. break
  57. self.log(f"Found block comment: {comment}, ignoring")
  58. else:
  59. # Skip standalone '/' characters that are not part of a comment
  60. # to avoid getting stuck in an infinite loop
  61. self.index += 1
  62. if self.context.empty:
  63. return self.parse_json()
  64. return ""