Fix allow_unicode (ticket:3).
[pyyaml/python3.git] / lib / yaml / composer.py
blobbb26f3661d04be6f99188c59eb240f44a5a22ebe
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 # Drop the STREAM-START event.
19 self.parser.get()
21 def check(self):
22 # If there are more documents available?
23 return not self.parser.check(StreamEndEvent)
25 def get(self):
26 # Get the root node of the next document.
27 if not self.parser.check(StreamEndEvent):
28 return self.compose_document()
30 def __iter__(self):
31 # Iterator protocol.
32 while not self.parser.check(StreamEndEvent):
33 yield self.compose_document()
35 def compose_document(self):
37 # Drop the DOCUMENT-START event.
38 self.parser.get()
40 # Compose the root node.
41 node = self.compose_node()
43 # Drop the DOCUMENT-END event.
44 self.parser.get()
46 self.all_anchors = {}
47 self.complete_anchors = {}
48 return node
50 def compose_node(self):
51 if self.parser.check(AliasEvent):
52 event = self.parser.get()
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.parser.peek()
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 if self.parser.check(ScalarEvent):
73 node = self.compose_scalar_node()
74 elif self.parser.check(SequenceStartEvent):
75 node = self.compose_sequence_node()
76 elif self.parser.check(MappingStartEvent):
77 node = self.compose_mapping_node()
78 if anchor is not None:
79 self.complete_anchors[anchor] = node
80 return node
82 def compose_scalar_node(self):
83 event = self.parser.get()
84 return ScalarNode(event.tag, event.value, event.implicit,
85 event.start_mark, event.end_mark, style=event.style)
87 def compose_sequence_node(self):
88 start_event = self.parser.get()
89 value = []
90 while not self.parser.check(SequenceEndEvent):
91 value.append(self.compose_node())
92 end_event = self.parser.get()
93 return SequenceNode(start_event.tag, value,
94 start_event.start_mark, end_event.end_mark,
95 flow_style=start_event.flow_style)
97 def compose_mapping_node(self):
98 start_event = self.parser.get()
99 value = {}
100 while not self.parser.check(MappingEndEvent):
101 key_event = self.parser.peek()
102 item_key = self.compose_node()
103 item_value = self.compose_node()
104 if item_key in value:
105 raise ComposerError("while composing a mapping", start_event.start_mark,
106 "found duplicate key", key_event.start_mark)
107 value[item_key] = item_value
108 end_event = self.parser.get()
109 return MappingNode(start_event.tag, value,
110 start_event.start_mark, end_event.end_mark,
111 flow_style=start_event.flow_style)