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

Revision 142, 4.2 KB checked in by xi, 9 years ago (diff)

Add support for recursive nodes to Composer. Constructor does not support recursive objects though.

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:
12
13    def __init__(self):
14        self.anchors = {}
15
16    def check_node(self):
17        # If there are more documents available?
18        return not self.check_event(StreamEndEvent)
19
20    def get_node(self):
21        # Get the root node of the next document.
22        if not self.check_event(StreamEndEvent):
23            return self.compose_document()
24
25    def __iter__(self):
26        # Iterator protocol.
27        while not self.check_event(StreamEndEvent):
28            yield self.compose_document()
29
30    def compose_document(self):
31
32        # Drop the STREAM-START event.
33        if self.check_event(StreamStartEvent):
34            self.get_event()
35
36        # Drop the DOCUMENT-START event.
37        self.get_event()
38
39        # Compose the root node.
40        node = self.compose_node(None, None)
41
42        # Drop the DOCUMENT-END event.
43        self.get_event()
44
45        self.complete_anchors = {}
46        return node
47
48    def compose_node(self, parent, index):
49        if self.check_event(AliasEvent):
50            event = self.get_event()
51            anchor = event.anchor
52            if anchor not in self.anchors:
53                raise ComposerError(None, None, "found undefined alias %r"
54                        % anchor.encode('utf-8'), event.start_mark)
55            return self.anchors[anchor]
56        event = self.peek_event()
57        anchor = event.anchor
58        if anchor is not None:
59            if anchor in self.anchors:
60                raise ComposerError("found duplicate anchor %r; first occurence"
61                        % anchor.encode('utf-8'), self.anchors[anchor].start_mark,
62                        "second occurence", event.start_mark)
63        self.descend_resolver(parent, index)
64        if self.check_event(ScalarEvent):
65            node = self.compose_scalar_node(anchor)
66        elif self.check_event(SequenceStartEvent):
67            node = self.compose_sequence_node(anchor)
68        elif self.check_event(MappingStartEvent):
69            node = self.compose_mapping_node(anchor)
70        self.ascend_resolver()
71        return node
72
73    def compose_scalar_node(self, anchor):
74        event = self.get_event()
75        tag = event.tag
76        if tag is None or tag == u'!':
77            tag = self.resolve(ScalarNode, event.value, event.implicit)
78        node = ScalarNode(tag, event.value,
79                event.start_mark, event.end_mark, style=event.style)
80        if anchor is not None:
81            self.anchors[anchor] = node
82        return node
83
84    def compose_sequence_node(self, anchor):
85        start_event = self.get_event()
86        tag = start_event.tag
87        if tag is None or tag == u'!':
88            tag = self.resolve(SequenceNode, None, start_event.implicit)
89        node = SequenceNode(tag, [],
90                start_event.start_mark, None,
91                flow_style=start_event.flow_style)
92        if anchor is not None:
93            self.anchors[anchor] = node
94        index = 0
95        while not self.check_event(SequenceEndEvent):
96            node.value.append(self.compose_node(node, index))
97            index += 1
98        end_event = self.get_event()
99        node.end_mark = end_event.end_mark
100        return node
101
102    def compose_mapping_node(self, anchor):
103        start_event = self.get_event()
104        tag = start_event.tag
105        if tag is None or tag == u'!':
106            tag = self.resolve(MappingNode, None, start_event.implicit)
107        node = MappingNode(tag, {},
108                start_event.start_mark, None,
109                flow_style=start_event.flow_style)
110        if anchor is not None:
111            self.anchors[anchor] = node
112        while not self.check_event(MappingEndEvent):
113            key_event = self.peek_event()
114            item_key = self.compose_node(node, None)
115            if item_key in node.value:
116                raise ComposerError("while composing a mapping", start_event.start_mark,
117                        "found duplicate key", key_event.start_mark)
118            item_value = self.compose_node(node, item_key)
119            node.value[item_key] = item_value
120        end_event = self.get_event()
121        node.end_mark = end_event.end_mark
122        return node
123
Note: See TracBrowser for help on using the repository browser.