OSDN Git Service

First version
[st-ro/stro.git] / 3rdparty / yaml-cpp / src / singledocparser.cpp
1 #include <algorithm>
2 #include <cstdio>
3 #include <sstream>
4
5 #include "collectionstack.h"  // IWYU pragma: keep
6 #include "scanner.h"
7 #include "singledocparser.h"
8 #include "tag.h"
9 #include "token.h"
10 #include "yaml-cpp/emitterstyle.h"
11 #include "yaml-cpp/eventhandler.h"
12 #include "yaml-cpp/exceptions.h"  // IWYU pragma: keep
13 #include "yaml-cpp/mark.h"
14 #include "yaml-cpp/null.h"
15
16 namespace YAML {
17 SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
18     : m_scanner(scanner),
19       m_directives(directives),
20       m_pCollectionStack(new CollectionStack),
21       m_curAnchor(0) {}
22
23 SingleDocParser::~SingleDocParser() {}
24
25 // HandleDocument
26 // . Handles the next document
27 // . Throws a ParserException on error.
28 void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
29   assert(!m_scanner.empty());  // guaranteed that there are tokens
30   assert(!m_curAnchor);
31
32   eventHandler.OnDocumentStart(m_scanner.peek().mark);
33
34   // eat doc start
35   if (m_scanner.peek().type == Token::DOC_START)
36     m_scanner.pop();
37
38   // recurse!
39   HandleNode(eventHandler);
40
41   eventHandler.OnDocumentEnd();
42
43   // and finally eat any doc ends we see
44   while (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
45     m_scanner.pop();
46 }
47
48 void SingleDocParser::HandleNode(EventHandler& eventHandler) {
49   // an empty node *is* a possibility
50   if (m_scanner.empty()) {
51     eventHandler.OnNull(m_scanner.mark(), NullAnchor);
52     return;
53   }
54
55   // save location
56   Mark mark = m_scanner.peek().mark;
57
58   // special case: a value node by itself must be a map, with no header
59   if (m_scanner.peek().type == Token::VALUE) {
60     eventHandler.OnMapStart(mark, "?", NullAnchor, EmitterStyle::Default);
61     HandleMap(eventHandler);
62     eventHandler.OnMapEnd();
63     return;
64   }
65
66   // special case: an alias node
67   if (m_scanner.peek().type == Token::ALIAS) {
68     eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
69     m_scanner.pop();
70     return;
71   }
72
73   std::string tag;
74   anchor_t anchor;
75   ParseProperties(tag, anchor);
76
77   const Token& token = m_scanner.peek();
78
79   if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
80     eventHandler.OnNull(mark, anchor);
81     m_scanner.pop();
82     return;
83   }
84
85   // add non-specific tags
86   if (tag.empty())
87     tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
88
89   // now split based on what kind of node we should be
90   switch (token.type) {
91     case Token::PLAIN_SCALAR:
92     case Token::NON_PLAIN_SCALAR:
93       eventHandler.OnScalar(mark, tag, anchor, token.value);
94       m_scanner.pop();
95       return;
96     case Token::FLOW_SEQ_START:
97       eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Flow);
98       HandleSequence(eventHandler);
99       eventHandler.OnSequenceEnd();
100       return;
101     case Token::BLOCK_SEQ_START:
102       eventHandler.OnSequenceStart(mark, tag, anchor, EmitterStyle::Block);
103       HandleSequence(eventHandler);
104       eventHandler.OnSequenceEnd();
105       return;
106     case Token::FLOW_MAP_START:
107       eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
108       HandleMap(eventHandler);
109       eventHandler.OnMapEnd();
110       return;
111     case Token::BLOCK_MAP_START:
112       eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Block);
113       HandleMap(eventHandler);
114       eventHandler.OnMapEnd();
115       return;
116     case Token::KEY:
117       // compact maps can only go in a flow sequence
118       if (m_pCollectionStack->GetCurCollectionType() ==
119           CollectionType::FlowSeq) {
120         eventHandler.OnMapStart(mark, tag, anchor, EmitterStyle::Flow);
121         HandleMap(eventHandler);
122         eventHandler.OnMapEnd();
123         return;
124       }
125       break;
126     default:
127       break;
128   }
129
130   if (tag == "?")
131     eventHandler.OnNull(mark, anchor);
132   else
133     eventHandler.OnScalar(mark, tag, anchor, "");
134 }
135
136 void SingleDocParser::HandleSequence(EventHandler& eventHandler) {
137   // split based on start token
138   switch (m_scanner.peek().type) {
139     case Token::BLOCK_SEQ_START:
140       HandleBlockSequence(eventHandler);
141       break;
142     case Token::FLOW_SEQ_START:
143       HandleFlowSequence(eventHandler);
144       break;
145     default:
146       break;
147   }
148 }
149
150 void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
151   // eat start token
152   m_scanner.pop();
153   m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
154
155   while (1) {
156     if (m_scanner.empty())
157       throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
158
159     Token token = m_scanner.peek();
160     if (token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
161       throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
162
163     m_scanner.pop();
164     if (token.type == Token::BLOCK_SEQ_END)
165       break;
166
167     // check for null
168     if (!m_scanner.empty()) {
169       const Token& token_ = m_scanner.peek();
170       if (token_.type == Token::BLOCK_ENTRY ||
171           token_.type == Token::BLOCK_SEQ_END) {
172         eventHandler.OnNull(token_.mark, NullAnchor);
173         continue;
174       }
175     }
176
177     HandleNode(eventHandler);
178   }
179
180   m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
181 }
182
183 void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
184   // eat start token
185   m_scanner.pop();
186   m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
187
188   while (1) {
189     if (m_scanner.empty())
190       throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
191
192     // first check for end
193     if (m_scanner.peek().type == Token::FLOW_SEQ_END) {
194       m_scanner.pop();
195       break;
196     }
197
198     // then read the node
199     HandleNode(eventHandler);
200
201     if (m_scanner.empty())
202       throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
203
204     // now eat the separator (or could be a sequence end, which we ignore - but
205     // if it's neither, then it's a bad node)
206     Token& token = m_scanner.peek();
207     if (token.type == Token::FLOW_ENTRY)
208       m_scanner.pop();
209     else if (token.type != Token::FLOW_SEQ_END)
210       throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
211   }
212
213   m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
214 }
215
216 void SingleDocParser::HandleMap(EventHandler& eventHandler) {
217   // split based on start token
218   switch (m_scanner.peek().type) {
219     case Token::BLOCK_MAP_START:
220       HandleBlockMap(eventHandler);
221       break;
222     case Token::FLOW_MAP_START:
223       HandleFlowMap(eventHandler);
224       break;
225     case Token::KEY:
226       HandleCompactMap(eventHandler);
227       break;
228     case Token::VALUE:
229       HandleCompactMapWithNoKey(eventHandler);
230       break;
231     default:
232       break;
233   }
234 }
235
236 void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
237   // eat start token
238   m_scanner.pop();
239   m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
240
241   while (1) {
242     if (m_scanner.empty())
243       throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
244
245     Token token = m_scanner.peek();
246     if (token.type != Token::KEY && token.type != Token::VALUE &&
247         token.type != Token::BLOCK_MAP_END)
248       throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
249
250     if (token.type == Token::BLOCK_MAP_END) {
251       m_scanner.pop();
252       break;
253     }
254
255     // grab key (if non-null)
256     if (token.type == Token::KEY) {
257       m_scanner.pop();
258       HandleNode(eventHandler);
259     } else {
260       eventHandler.OnNull(token.mark, NullAnchor);
261     }
262
263     // now grab value (optional)
264     if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
265       m_scanner.pop();
266       HandleNode(eventHandler);
267     } else {
268       eventHandler.OnNull(token.mark, NullAnchor);
269     }
270   }
271
272   m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
273 }
274
275 void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
276   // eat start token
277   m_scanner.pop();
278   m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
279
280   while (1) {
281     if (m_scanner.empty())
282       throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
283
284     Token& token = m_scanner.peek();
285     const Mark mark = token.mark;
286     // first check for end
287     if (token.type == Token::FLOW_MAP_END) {
288       m_scanner.pop();
289       break;
290     }
291
292     // grab key (if non-null)
293     if (token.type == Token::KEY) {
294       m_scanner.pop();
295       HandleNode(eventHandler);
296     } else {
297       eventHandler.OnNull(mark, NullAnchor);
298     }
299
300     // now grab value (optional)
301     if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
302       m_scanner.pop();
303       HandleNode(eventHandler);
304     } else {
305       eventHandler.OnNull(mark, NullAnchor);
306     }
307
308     if (m_scanner.empty())
309       throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
310
311     // now eat the separator (or could be a map end, which we ignore - but if
312     // it's neither, then it's a bad node)
313     Token& nextToken = m_scanner.peek();
314     if (nextToken.type == Token::FLOW_ENTRY)
315       m_scanner.pop();
316     else if (nextToken.type != Token::FLOW_MAP_END)
317       throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
318   }
319
320   m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
321 }
322
323 // . Single "key: value" pair in a flow sequence
324 void SingleDocParser::HandleCompactMap(EventHandler& eventHandler) {
325   m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
326
327   // grab key
328   Mark mark = m_scanner.peek().mark;
329   m_scanner.pop();
330   HandleNode(eventHandler);
331
332   // now grab value (optional)
333   if (!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
334     m_scanner.pop();
335     HandleNode(eventHandler);
336   } else {
337     eventHandler.OnNull(mark, NullAnchor);
338   }
339
340   m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
341 }
342
343 // . Single ": value" pair in a flow sequence
344 void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler) {
345   m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
346
347   // null key
348   eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
349
350   // grab value
351   m_scanner.pop();
352   HandleNode(eventHandler);
353
354   m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
355 }
356
357 // ParseProperties
358 // . Grabs any tag or anchor tokens and deals with them.
359 void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor) {
360   tag.clear();
361   anchor = NullAnchor;
362
363   while (1) {
364     if (m_scanner.empty())
365       return;
366
367     switch (m_scanner.peek().type) {
368       case Token::TAG:
369         ParseTag(tag);
370         break;
371       case Token::ANCHOR:
372         ParseAnchor(anchor);
373         break;
374       default:
375         return;
376     }
377   }
378 }
379
380 void SingleDocParser::ParseTag(std::string& tag) {
381   Token& token = m_scanner.peek();
382   if (!tag.empty())
383     throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
384
385   Tag tagInfo(token);
386   tag = tagInfo.Translate(m_directives);
387   m_scanner.pop();
388 }
389
390 void SingleDocParser::ParseAnchor(anchor_t& anchor) {
391   Token& token = m_scanner.peek();
392   if (anchor)
393     throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
394
395   anchor = RegisterAnchor(token.value);
396   m_scanner.pop();
397 }
398
399 anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
400   if (name.empty())
401     return NullAnchor;
402
403   return m_anchors[name] = ++m_curAnchor;
404 }
405
406 anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
407                                        const std::string& name) const {
408   Anchors::const_iterator it = m_anchors.find(name);
409   if (it == m_anchors.end())
410     throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
411
412   return it->second;
413 }
414 }