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.

139 lines
4.8 KiB

4 years ago
  1. __all__ = ['Composer', 'ComposerError']
  2. from .error import MarkedYAMLError
  3. from .events import *
  4. from .nodes import *
  5. class ComposerError(MarkedYAMLError):
  6. pass
  7. class Composer:
  8. def __init__(self):
  9. self.anchors = {}
  10. def check_node(self):
  11. # Drop the STREAM-START event.
  12. if self.check_event(StreamStartEvent):
  13. self.get_event()
  14. # If there are more documents available?
  15. return not self.check_event(StreamEndEvent)
  16. def get_node(self):
  17. # Get the root node of the next document.
  18. if not self.check_event(StreamEndEvent):
  19. return self.compose_document()
  20. def get_single_node(self):
  21. # Drop the STREAM-START event.
  22. self.get_event()
  23. # Compose a document if the stream is not empty.
  24. document = None
  25. if not self.check_event(StreamEndEvent):
  26. document = self.compose_document()
  27. # Ensure that the stream contains no more documents.
  28. if not self.check_event(StreamEndEvent):
  29. event = self.get_event()
  30. raise ComposerError("expected a single document in the stream",
  31. document.start_mark, "but found another document",
  32. event.start_mark)
  33. # Drop the STREAM-END event.
  34. self.get_event()
  35. return document
  36. def compose_document(self):
  37. # Drop the DOCUMENT-START event.
  38. self.get_event()
  39. # Compose the root node.
  40. node = self.compose_node(None, None)
  41. # Drop the DOCUMENT-END event.
  42. self.get_event()
  43. self.anchors = {}
  44. return node
  45. def compose_node(self, parent, index):
  46. if self.check_event(AliasEvent):
  47. event = self.get_event()
  48. anchor = event.anchor
  49. if anchor not in self.anchors:
  50. raise ComposerError(None, None, "found undefined alias %r"
  51. % anchor, event.start_mark)
  52. return self.anchors[anchor]
  53. event = self.peek_event()
  54. anchor = event.anchor
  55. if anchor is not None:
  56. if anchor in self.anchors:
  57. raise ComposerError("found duplicate anchor %r; first occurrence"
  58. % anchor, self.anchors[anchor].start_mark,
  59. "second occurrence", event.start_mark)
  60. self.descend_resolver(parent, index)
  61. if self.check_event(ScalarEvent):
  62. node = self.compose_scalar_node(anchor)
  63. elif self.check_event(SequenceStartEvent):
  64. node = self.compose_sequence_node(anchor)
  65. elif self.check_event(MappingStartEvent):
  66. node = self.compose_mapping_node(anchor)
  67. self.ascend_resolver()
  68. return node
  69. def compose_scalar_node(self, anchor):
  70. event = self.get_event()
  71. tag = event.tag
  72. if tag is None or tag == '!':
  73. tag = self.resolve(ScalarNode, event.value, event.implicit)
  74. node = ScalarNode(tag, event.value,
  75. event.start_mark, event.end_mark, style=event.style)
  76. if anchor is not None:
  77. self.anchors[anchor] = node
  78. return node
  79. def compose_sequence_node(self, anchor):
  80. start_event = self.get_event()
  81. tag = start_event.tag
  82. if tag is None or tag == '!':
  83. tag = self.resolve(SequenceNode, None, start_event.implicit)
  84. node = SequenceNode(tag, [],
  85. start_event.start_mark, None,
  86. flow_style=start_event.flow_style)
  87. if anchor is not None:
  88. self.anchors[anchor] = node
  89. index = 0
  90. while not self.check_event(SequenceEndEvent):
  91. node.value.append(self.compose_node(node, index))
  92. index += 1
  93. end_event = self.get_event()
  94. node.end_mark = end_event.end_mark
  95. return node
  96. def compose_mapping_node(self, anchor):
  97. start_event = self.get_event()
  98. tag = start_event.tag
  99. if tag is None or tag == '!':
  100. tag = self.resolve(MappingNode, None, start_event.implicit)
  101. node = MappingNode(tag, [],
  102. start_event.start_mark, None,
  103. flow_style=start_event.flow_style)
  104. if anchor is not None:
  105. self.anchors[anchor] = node
  106. while not self.check_event(MappingEndEvent):
  107. #key_event = self.peek_event()
  108. item_key = self.compose_node(node, None)
  109. #if item_key in node.value:
  110. # raise ComposerError("while composing a mapping", start_event.start_mark,
  111. # "found duplicate key", key_event.start_mark)
  112. item_value = self.compose_node(node, item_key)
  113. #node.value[item_key] = item_value
  114. node.value.append((item_key, item_value))
  115. end_event = self.get_event()
  116. node.end_mark = end_event.end_mark
  117. return node