Back to work :). Rename markers to marks.
[pyyaml/python3.git] / lib / yaml / composer.py
blobb6cbb94d36dbcce89e0bf9bb1097d45521426ed5
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, parser):
14 self.parser = parser
15 self.all_anchors = {}
16 self.complete_anchors = {}
18 def check(self):
19 # If there are more documents available?
20 return not self.parser.check(StreamEndEvent)
22 def get(self):
23 # Get the root node of the next document.
24 if not self.parser.check(StreamEndEvent):
25 return self.compose_document()
27 def __iter__(self):
28 # Iterator protocol.
29 while not self.parser.check(StreamEndEvent):
30 yield self.compose_document()
32 def compose_document(self):
33 node = self.compose_node()
34 self.all_anchors = {}
35 self.complete_anchors = {}
36 return node
38 def compose_node(self):
39 if self.parser.check(AliasEvent):
40 event = self.parser.get()
41 anchor = event.anchor
42 if anchor not in self.all_anchors:
43 raise ComposerError(None, None, "found undefined alias %r"
44 % anchor.encode('utf-8'), event.start_mark)
45 if anchor not in self.complete_anchors:
46 collection_event = self.all_anchors[anchor]
47 raise ComposerError("while composing a collection",
48 collection_event.start_mark,
49 "found recursive anchor %r" % anchor.encode('utf-8'),
50 event.start_mark)
51 return self.complete_anchors[anchor]
52 event = self.parser.peek()
53 anchor = event.anchor
54 if anchor is not None:
55 if anchor in self.all_anchors:
56 raise ComposerError("found duplicate anchor %r; first occurence"
57 % anchor.encode('utf-8'), self.all_anchors[anchor].start_mark,
58 "second occurence", event.start_mark)
59 self.all_anchors[anchor] = event
60 if self.parser.check(ScalarEvent):
61 node = self.compose_scalar_node()
62 elif self.parser.check(SequenceEvent):
63 node = self.compose_sequence_node()
64 elif self.parser.check(MappingEvent):
65 node = self.compose_mapping_node()
66 if anchor is not None:
67 self.complete_anchors[anchor] = node
68 return node
70 def compose_scalar_node(self):
71 event = self.parser.get()
72 return ScalarNode(event.tag, event.value,
73 event.start_mark, event.end_mark)
75 def compose_sequence_node(self):
76 start_event = self.parser.get()
77 value = []
78 while not self.parser.check(CollectionEndEvent):
79 value.append(self.compose_node())
80 end_event = self.parser.get()
81 return SequenceNode(start_event.tag, value,
82 start_event.start_mark, end_event.end_mark)
84 def compose_mapping_node(self):
85 start_event = self.parser.get()
86 value = {}
87 while not self.parser.check(CollectionEndEvent):
88 key_event = self.parser.peek()
89 item_key = self.compose_node()
90 item_value = self.compose_node()
91 if item_key in value:
92 raise ComposerError("while composing a mapping", start_event.start_mark,
93 "found duplicate key", key_event.start_mark)
94 value[item_key] = item_value
95 end_event = self.parser.get()
96 return MappingNode(start_event.tag, value,
97 start_event.start_mark, end_event.end_mark)