source: pyyaml/trunk/lib/yaml/composer.py @ 233

Revision 233, 4.1 KB checked in by xi, 8 years ago (diff)

Fix loading an empty YAML stream.

Line 
1
2__all__ = ['Composer', 'ComposerError']
3
4from error import MarkedYAMLError
5from events import *
6from nodes import *
7
8class ComposerError(MarkedYAMLError):
9    pass
10
11class Composer(object):
12
13    def __init__(self):
14        self.anchors = {}
15
16    def check_node(self):
17        # Drop the STREAM-START event.
18        if self.check_event(StreamStartEvent):
19            self.get_event()
20
21        # If there are more documents available?
22        return not self.check_event(StreamEndEvent)
23
24    def get_node(self):
25        # Get the root node of the next document.
26        if not self.check_event(StreamEndEvent):
27            return self.compose_document()
28
29    def compose_document(self):
30        # Drop the DOCUMENT-START event.
31        self.get_event()
32
33        # Compose the root node.
34        node = self.compose_node(None, None)
35
36        # Drop the DOCUMENT-END event.
37        self.get_event()
38
39        self.anchors = {}
40        return node
41
42    def compose_node(self, parent, index):
43        if self.check_event(AliasEvent):
44            event = self.get_event()
45            anchor = event.anchor
46            if anchor not in self.anchors:
47                raise ComposerError(None, None, "found undefined alias %r"
48                        % anchor.encode('utf-8'), event.start_mark)
49            return self.anchors[anchor]
50        event = self.peek_event()
51        anchor = event.anchor
52        if anchor is not None:
53            if anchor in self.anchors:
54                raise ComposerError("found duplicate anchor %r; first occurence"
55                        % anchor.encode('utf-8'), self.anchors[anchor].start_mark,
56                        "second occurence", event.start_mark)
57        self.descend_resolver(parent, index)
58        if self.check_event(ScalarEvent):
59            node = self.compose_scalar_node(anchor)
60        elif self.check_event(SequenceStartEvent):
61            node = self.compose_sequence_node(anchor)
62        elif self.check_event(MappingStartEvent):
63            node = self.compose_mapping_node(anchor)
64        self.ascend_resolver()
65        return node
66
67    def compose_scalar_node(self, anchor):
68        event = self.get_event()
69        tag = event.tag
70        if tag is None or tag == u'!':
71            tag = self.resolve(ScalarNode, event.value, event.implicit)
72        node = ScalarNode(tag, event.value,
73                event.start_mark, event.end_mark, style=event.style)
74        if anchor is not None:
75            self.anchors[anchor] = node
76        return node
77
78    def compose_sequence_node(self, anchor):
79        start_event = self.get_event()
80        tag = start_event.tag
81        if tag is None or tag == u'!':
82            tag = self.resolve(SequenceNode, None, start_event.implicit)
83        node = SequenceNode(tag, [],
84                start_event.start_mark, None,
85                flow_style=start_event.flow_style)
86        if anchor is not None:
87            self.anchors[anchor] = node
88        index = 0
89        while not self.check_event(SequenceEndEvent):
90            node.value.append(self.compose_node(node, index))
91            index += 1
92        end_event = self.get_event()
93        node.end_mark = end_event.end_mark
94        return node
95
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 == u'!':
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
118
Note: See TracBrowser for help on using the repository browser.