source: pyyaml/branches/working-on-emitter/lib/yaml/composer.py @ 121

Revision 121, 3.8 KB checked in by xi, 8 years ago (diff)

Add a branch for working on Emitter.

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, parser):
14        self.parser = parser
15        self.all_anchors = {}
16        self.complete_anchors = {}
17
18        # Drop the STREAM-START event.
19        self.parser.get()
20
21    def check(self):
22        # If there are more documents available?
23        return not self.parser.check(StreamEndEvent)
24
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()
29
30    def __iter__(self):
31        # Iterator protocol.
32        while not self.parser.check(StreamEndEvent):
33            yield self.compose_document()
34
35    def compose_document(self):
36
37        # Drop the DOCUMENT-START event.
38        self.parser.get()
39
40        # Compose the root node.
41        node = self.compose_node()
42
43        # Drop the DOCUMENT-END event.
44        self.parser.get()
45
46        self.all_anchors = {}
47        self.complete_anchors = {}
48        return node
49
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(SequenceEvent):
75            node = self.compose_sequence_node()
76        elif self.parser.check(MappingEvent):
77            node = self.compose_mapping_node()
78        if anchor is not None:
79            self.complete_anchors[anchor] = node
80        return node
81
82    def compose_scalar_node(self):
83        event = self.parser.get()
84        return ScalarNode(event.tag, event.value,
85                event.start_mark, event.end_mark)
86
87    def compose_sequence_node(self):
88        start_event = self.parser.get()
89        value = []
90        while not self.parser.check(CollectionEndEvent):
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
96    def compose_mapping_node(self):
97        start_event = self.parser.get()
98        value = {}
99        while not self.parser.check(CollectionEndEvent):
100            key_event = self.parser.peek()
101            item_key = self.compose_node()
102            item_value = self.compose_node()
103            if item_key in value:
104                raise ComposerError("while composing a mapping", start_event.start_mark,
105                        "found duplicate key", key_event.start_mark)
106            value[item_key] = item_value
107        end_event = self.parser.get()
108        return MappingNode(start_event.tag, value,
109                start_event.start_mark, end_event.end_mark)
110
Note: See TracBrowser for help on using the repository browser.