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

Revision 122, 6.0 KB checked in by xi, 9 years ago (diff)

Add a skeleton of the emitter.

Line 
1
2# Events should obey the following grammar:
3# stream ::= STREAM-START document* STREAM-END
4# document ::= DOCUMENT-START node DOCUMENT-END
5# node ::= SCALAR | sequence | mapping
6# sequence ::= SEQUENCE-START node* SEQUENCE-END
7# mapping ::= MAPPING-START (node node)* MAPPING-END
8
9__all__ = ['Emitter', 'EmitterError']
10
11from error import YAMLError
12from events import *
13
14class EmitterError(YAMLError):
15    pass
16
17class Emitter:
18
19    def __init__(self, writer):
20        self.writer = writer
21        self.states = []
22        self.state = self.expect_stream_start
23        self.levels = []
24        self.level = 0
25        self.soft_space = False
26
27    def emit(self, event):
28        self.state(event)
29
30    def expect_stream_start(self, event):
31        if isinstance(event, StreamStartEvent):
32            self.state = self.expect_document_start
33        else:
34            raise EmitterError("expected StreamStartEvent, but got %s" % event.__class__.__name__)
35
36    def expect_document_start(self, event):
37        if isinstance(event, DocumentStartEvent):
38            self.write_document_start()
39            self.states.append(self.expect_document_end)
40            self.state = self.expect_root_node
41        elif isinstance(event, StreamEndEvent):
42            self.writer.flush()
43            self.state = self.expect_nothing
44        else:
45            raise EmitterError("expected DocumentStartEvent, but got %s" % event.__class__.__name__)
46
47    def expect_document_end(self, event):
48        if isinstance(event, DocumentEndEvent):
49            self.write_document_end()
50            self.state = self.expect_document_start
51        else:
52            raiseEmitterError("expected DocumentEndEvent, but got %s" % event.__class__.__name__)
53
54    def expect_root_node(self, event):
55        self.expect_node(event)
56
57    def expect_node(self, event):
58        if isinstance(event, AliasEvent):
59            self.write_anchor("*", event.anchor)
60            self.state = self.states.pop()
61        elif isinstance(event, NodeEvent):
62            if event.anchor:
63                self.write_anchor("&", event.anchor)
64            if event.tag:
65                self.write_tag(event.tag)
66            if isinstance(event, ScalarEvent):
67                self.write_scalar(event.value)
68                self.state = self.states.pop()
69            elif isinstance(event, SequenceEvent):
70                self.write_collection_start("[")
71                self.level += 1
72                self.state = self.expect_first_sequence_item
73            elif isinstance(event, MappingEvent):
74                self.write_collection_start("{")
75                self.level += 1
76                self.state = self.expect_first_mapping_key
77        else:
78            raise EmitterError("Expected NodeEvent, but got %s" % event.__class__.__name__)
79
80    def expect_first_sequence_item(self, event):
81        if isinstance(event, CollectionEndEvent):
82            self.write_collection_end("]")
83            self.state = self.states.pop()
84        else:
85            self.write_indent()
86            self.states.append(self.expect_sequence_item)
87            self.expect_node(event)
88
89    def expect_sequence_item(self, event):
90        if isinstance(event, CollectionEndEvent):
91            self.level -= 1
92            self.write_indent()
93            self.write_collection_end("]")
94            self.state = self.states.pop()
95        else:
96            self.write_indicator(",")
97            self.write_indent()
98            self.states.append(self.expect_sequence_item)
99            self.expect_node(event)
100       
101    def expect_first_mapping_key(self, event):
102        if isinstance(event, CollectionEndEvent):
103            self.write_collection_end("}")
104            self.state = self.states.pop()
105        else:
106            self.write_indent()
107            self.write_indicator("?")
108            self.states.append(self.expect_mapping_value)
109            self.expect_node(event)
110
111    def expect_mapping_key(self, event):
112        if isinstance(event, CollectionEndEvent):
113            self.level -= 1
114            self.write_indent()
115            self.write_collection_end("}")
116            self.state = self.states.pop()
117        else:
118            self.write_indicator(",")
119            self.write_indent()
120            self.write_indicator("?")
121            self.states.append(self.expect_mapping_value)
122            self.expect_node(event)
123
124    def expect_mapping_value(self, event):
125        self.write_indent()
126        self.write_indicator(":")
127        self.states.append(self.expect_mapping_key)
128        self.expect_node(event)
129
130    def expect_nothing(self, event):
131        raise EmitterError("expected nothing, but got %s" % event.__class__.__name__)
132
133    def write_document_start(self):
134        self.writer.write("%YAML 1.1\n")
135        self.writer.write("---")
136        self.soft_space = True
137
138    def write_document_end(self):
139        self.writer.write("\n...\n")
140        self.soft_space = False
141
142    def write_collection_start(self, indicator):
143        if self.soft_space:
144            self.writer.write(" ")
145        self.writer.write(indicator)
146        self.soft_space = False
147
148    def write_collection_end(self, indicator):
149        self.writer.write(indicator)
150        self.soft_space = True
151
152    def write_anchor(self, indicator, name):
153        if self.soft_space:
154            self.writer.write(" ")
155        self.writer.write("%s%s" % (indicator, name))
156        self.soft_space = True
157
158    def write_tag(self, tag):
159        if self.soft_space:
160            self.writer.write(" ")
161        if tag.startswith("tag:yaml.org,2002:"):
162            self.writer.write("!!%s" % tag[len("tag.yaml.org,2002:"):])
163        else:
164            self.writer.write("!<%s>" % tag)
165        self.soft_space = True
166
167    def write_scalar(self, value):
168        if self.soft_space:
169            self.writer.write(" ")
170        self.writer.write("\"%s\"" % value.encode('utf-8'))
171        self.soft_space = True
172
173    def write_indicator(self, indicator):
174        self.writer.write(indicator)
175        self.soft_space = True
176
177    def write_indent(self):
178        self.writer.write("\n"+" "*(self.level*4))
179        self.soft_space = False
180
Note: See TracBrowser for help on using the repository browser.