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

Revision 137, 4.5 KB checked in by xi, 8 years ago (diff)

Refactor resolver.

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.all_anchors = {}
15        self.complete_anchors = {}
16
17    def check_node(self):
18        # If there are more documents available?
19        return not self.check_event(StreamEndEvent)
20
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()
25
26    def __iter__(self):
27        # Iterator protocol.
28        while not self.check_event(StreamEndEvent):
29            yield self.compose_document()
30
31    def compose_document(self):
32
33        # Drop the STREAM-START event.
34        if self.check_event(StreamStartEvent):
35            self.get_event()
36
37        # Drop the DOCUMENT-START event.
38        self.get_event()
39
40        # Compose the root node.
41        node = self.compose_node(None, None)
42
43        # Drop the DOCUMENT-END event.
44        self.get_event()
45
46        self.all_anchors = {}
47        self.complete_anchors = {}
48        return node
49
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
83
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)
91
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
107
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
127
Note: See TracBrowser for help on using the repository browser.