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

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

Refactor resolver.

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