Refactor resolver.
[pyyaml/python3.git] / lib / yaml / composer.py
blob00e6db69aeaa836143dd9070d617da4229c46803
2 __all__ = ['Composer', 'ComposerError']
4 from error import MarkedYAMLError
5 from events import *
6 from nodes import *
8 class ComposerError(MarkedYAMLError):
9 pass
11 class Composer:
13 def __init__(self):
14 self.all_anchors = {}
15 self.complete_anchors = {}
17 def check_node(self):
18 # If there are more documents available?
19 return not self.check_event(StreamEndEvent)
21 def get_node(self):
22 # Get the root node of the next document.
23 if not self.check_event(StreamEndEvent):
24 return self.compose_document()
26 def __iter__(self):
27 # Iterator protocol.
28 while not self.check_event(StreamEndEvent):
29 yield self.compose_document()
31 def compose_document(self):
33 # Drop the STREAM-START event.
34 if self.check_event(StreamStartEvent):
35 self.get_event()
37 # Drop the DOCUMENT-START event.
38 self.get_event()
40 # Compose the root node.
41 node = self.compose_node(None, None)
43 # Drop the DOCUMENT-END event.
44 self.get_event()
46 self.all_anchors = {}
47 self.complete_anchors = {}
48 return node
50 def compose_node(self, parent, index):
51 if self.check_event(AliasEvent):
52 event = self.get_event()
53 anchor = event.anchor
54 if anchor not in self.all_anchors:
55 raise ComposerError(None, None, "found undefined alias %r"
56 % anchor.encode('utf-8'), event.start_mark)
57 if anchor not in self.complete_anchors:
58 collection_event = self.all_anchors[anchor]
59 raise ComposerError("while composing a collection",
60 collection_event.start_mark,
61 "found recursive anchor %r" % anchor.encode('utf-8'),
62 event.start_mark)
63 return self.complete_anchors[anchor]
64 event = self.peek_event()
65 anchor = event.anchor
66 if anchor is not None:
67 if anchor in self.all_anchors:
68 raise ComposerError("found duplicate anchor %r; first occurence"
69 % anchor.encode('utf-8'), self.all_anchors[anchor].start_mark,
70 "second occurence", event.start_mark)
71 self.all_anchors[anchor] = event
72 self.descend_resolver(parent, index)
73 if self.check_event(ScalarEvent):
74 node = self.compose_scalar_node()
75 elif self.check_event(SequenceStartEvent):
76 node = self.compose_sequence_node()
77 elif self.check_event(MappingStartEvent):
78 node = self.compose_mapping_node()
79 if anchor is not None:
80 self.complete_anchors[anchor] = node
81 self.ascend_resolver()
82 return node
84 def compose_scalar_node(self):
85 event = self.get_event()
86 tag = event.tag
87 if tag is None or tag == u'!':
88 tag = self.resolve(ScalarNode, event.value, event.implicit)
89 return ScalarNode(tag, event.value,
90 event.start_mark, event.end_mark, style=event.style)
92 def compose_sequence_node(self):
93 start_event = self.get_event()
94 tag = start_event.tag
95 if tag is None or tag == u'!':
96 tag = self.resolve(SequenceNode, None, start_event.implicit)
97 node = SequenceNode(tag, [],
98 start_event.start_mark, None,
99 flow_style=start_event.flow_style)
100 index = 0
101 while not self.check_event(SequenceEndEvent):
102 node.value.append(self.compose_node(node, index))
103 index += 1
104 end_event = self.get_event()
105 node.end_mark = end_event.end_mark
106 return node
108 def compose_mapping_node(self):
109 start_event = self.get_event()
110 tag = start_event.tag
111 if tag is None or tag == u'!':
112 tag = self.resolve(MappingNode, None, start_event.implicit)
113 node = MappingNode(tag, {},
114 start_event.start_mark, None,
115 flow_style=start_event.flow_style)
116 while not self.check_event(MappingEndEvent):
117 key_event = self.peek_event()
118 item_key = self.compose_node(node, None)
119 if item_key in node.value:
120 raise ComposerError("while composing a mapping", start_event.start_mark,
121 "found duplicate key", key_event.start_mark)
122 item_value = self.compose_node(node, item_key)
123 node.value[item_key] = item_value
124 end_event = self.get_event()
125 node.end_mark = end_event.end_mark
126 return node