singledocparser.cpp
Go to the documentation of this file.
1 #include "singledocparser.h"
2 #include "collectionstack.h"
3 #include "directives.h"
6 #include "scanner.h"
7 #include "tag.h"
8 #include "token.h"
9 #include <sstream>
10 #include <cstdio>
11 #include <algorithm>
12 
13 namespace YAML_PM
14 {
15  SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives): m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), m_curAnchor(0)
16  {
17  }
18 
20  {
21  }
22 
23  // HandleDocument
24  // . Handles the next document
25  // . Throws a ParserException on error.
27  {
28  assert(!m_scanner.empty()); // guaranteed that there are tokens
29  assert(!m_curAnchor);
30 
31  eventHandler.OnDocumentStart(m_scanner.peek().mark);
32 
33  // eat doc start
35  m_scanner.pop();
36 
37  // recurse!
38  HandleNode(eventHandler);
39 
40  eventHandler.OnDocumentEnd();
41 
42  // and finally eat any doc ends we see
44  m_scanner.pop();
45  }
46 
48  {
49  // an empty node *is* a possibility
50  if(m_scanner.empty()) {
51  eventHandler.OnNull(Mark::null(), 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);
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  // add non-specific tags
80  if(tag.empty())
81  tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
82 
83  // now split based on what kind of node we should be
84  switch(token.type) {
87  eventHandler.OnScalar(mark, tag, anchor, token.value);
88  m_scanner.pop();
89  return;
92  eventHandler.OnSequenceStart(mark, tag, anchor);
93  HandleSequence(eventHandler);
94  eventHandler.OnSequenceEnd();
95  return;
98  eventHandler.OnMapStart(mark, tag, anchor);
99  HandleMap(eventHandler);
100  eventHandler.OnMapEnd();
101  return;
102  case Token::KEY:
103  // compact maps can only go in a flow sequence
104  if(m_pCollectionStack->GetCurCollectionType() == CollectionType::FlowSeq) {
105  eventHandler.OnMapStart(mark, tag, anchor);
106  HandleMap(eventHandler);
107  eventHandler.OnMapEnd();
108  return;
109  }
110  break;
111  default:
112  break;
113  }
114 
115  if(tag == "?")
116  eventHandler.OnNull(mark, anchor);
117  else
118  eventHandler.OnScalar(mark, tag, anchor, "");
119  }
120 
122  {
123  // split based on start token
124  switch(m_scanner.peek().type) {
125  case Token::BLOCK_SEQ_START: HandleBlockSequence(eventHandler); break;
126  case Token::FLOW_SEQ_START: HandleFlowSequence(eventHandler); break;
127  default: break;
128  }
129  }
130 
132  {
133  // eat start token
134  m_scanner.pop();
135  m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
136 
137  while(1) {
138  if(m_scanner.empty())
140 
141  Token token = m_scanner.peek();
142  if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
144 
145  m_scanner.pop();
146  if(token.type == Token::BLOCK_SEQ_END)
147  break;
148 
149  // check for null
150  if(!m_scanner.empty()) {
151  const Token& token = m_scanner.peek();
152  if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) {
153  eventHandler.OnNull(token.mark, NullAnchor);
154  continue;
155  }
156  }
157 
158  HandleNode(eventHandler);
159  }
160 
161  m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
162  }
163 
165  {
166  // eat start token
167  m_scanner.pop();
168  m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
169 
170  while(1) {
171  if(m_scanner.empty())
173 
174  // first check for end
176  m_scanner.pop();
177  break;
178  }
179 
180  // then read the node
181  HandleNode(eventHandler);
182 
183  // now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
184  Token& token = m_scanner.peek();
185  if(token.type == Token::FLOW_ENTRY)
186  m_scanner.pop();
187  else if(token.type != Token::FLOW_SEQ_END)
189  }
190 
191  m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
192  }
193 
195  {
196  // split based on start token
197  switch(m_scanner.peek().type) {
198  case Token::BLOCK_MAP_START: HandleBlockMap(eventHandler); break;
199  case Token::FLOW_MAP_START: HandleFlowMap(eventHandler); break;
200  case Token::KEY: HandleCompactMap(eventHandler); break;
201  case Token::VALUE: HandleCompactMapWithNoKey(eventHandler); break;
202  default: break;
203  }
204  }
205 
207  {
208  // eat start token
209  m_scanner.pop();
210  m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
211 
212  while(1) {
213  if(m_scanner.empty())
215 
216  Token token = m_scanner.peek();
217  if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
219 
220  if(token.type == Token::BLOCK_MAP_END) {
221  m_scanner.pop();
222  break;
223  }
224 
225  // grab key (if non-null)
226  if(token.type == Token::KEY) {
227  m_scanner.pop();
228  HandleNode(eventHandler);
229  } else {
230  eventHandler.OnNull(token.mark, NullAnchor);
231  }
232 
233  // now grab value (optional)
234  if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
235  m_scanner.pop();
236  HandleNode(eventHandler);
237  } else {
238  eventHandler.OnNull(token.mark, NullAnchor);
239  }
240  }
241 
242  m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
243  }
244 
246  {
247  // eat start token
248  m_scanner.pop();
249  m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
250 
251  while(1) {
252  if(m_scanner.empty())
254 
255  Token& token = m_scanner.peek();
256  // first check for end
257  if(token.type == Token::FLOW_MAP_END) {
258  m_scanner.pop();
259  break;
260  }
261 
262  // grab key (if non-null)
263  if(token.type == Token::KEY) {
264  m_scanner.pop();
265  HandleNode(eventHandler);
266  } else {
267  eventHandler.OnNull(token.mark, NullAnchor);
268  }
269 
270  // now grab value (optional)
271  if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
272  m_scanner.pop();
273  HandleNode(eventHandler);
274  } else {
275  eventHandler.OnNull(token.mark, NullAnchor);
276  }
277 
278  // now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
279  Token& nextToken = m_scanner.peek();
280  if(nextToken.type == Token::FLOW_ENTRY)
281  m_scanner.pop();
282  else if(nextToken.type != Token::FLOW_MAP_END)
284  }
285 
286  m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
287  }
288 
289  // . Single "key: value" pair in a flow sequence
291  {
292  m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
293 
294  // grab key
295  Mark mark = m_scanner.peek().mark;
296  m_scanner.pop();
297  HandleNode(eventHandler);
298 
299  // now grab value (optional)
300  if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
301  m_scanner.pop();
302  HandleNode(eventHandler);
303  } else {
304  eventHandler.OnNull(mark, NullAnchor);
305  }
306 
308  }
309 
310  // . Single ": value" pair in a flow sequence
312  {
313  m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
314 
315  // null key
316  eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
317 
318  // grab value
319  m_scanner.pop();
320  HandleNode(eventHandler);
321 
323  }
324 
325  // ParseProperties
326  // . Grabs any tag or anchor tokens and deals with them.
328  {
329  tag.clear();
330  anchor = NullAnchor;
331 
332  while(1) {
333  if(m_scanner.empty())
334  return;
335 
336  switch(m_scanner.peek().type) {
337  case Token::TAG: ParseTag(tag); break;
338  case Token::ANCHOR: ParseAnchor(anchor); break;
339  default: return;
340  }
341  }
342  }
343 
345  {
346  Token& token = m_scanner.peek();
347  if(!tag.empty())
349 
350  Tag tagInfo(token);
351  tag = tagInfo.Translate(m_directives);
352  m_scanner.pop();
353  }
354 
356  {
357  Token& token = m_scanner.peek();
358  if(anchor)
360 
361  anchor = RegisterAnchor(token.value);
362  m_scanner.pop();
363  }
364 
366  {
367  if(name.empty())
368  return NullAnchor;
369 
370  return m_anchors[name] = ++m_curAnchor;
371  }
372 
374  {
375  Anchors::const_iterator it = m_anchors.find(name);
376  if(it == m_anchors.end())
378 
379  return it->second;
380  }
381 }
void HandleFlowSequence(EventHandler &eventHandler)
static const Mark null()
Definition: mark.h:16
const char *const UNKNOWN_ANCHOR
Definition: exceptions.h:56
const char *const END_OF_SEQ_FLOW
Definition: exceptions.h:32
void ParseTag(std::string &tag)
std::size_t anchor_t
Definition: anchor.h:12
SingleDocParser(Scanner &scanner, const Directives &directives)
std::auto_ptr< CollectionStack > m_pCollectionStack
::std::string string
Definition: gtest.h:1979
void HandleSequence(EventHandler &eventHandler)
virtual void OnSequenceEnd()=0
void HandleDocument(EventHandler &eventHandler)
virtual void OnSequenceStart(const Mark &mark, const std::string &tag, anchor_t anchor)=0
void ParseProperties(std::string &tag, anchor_t &anchor)
virtual void OnDocumentEnd()=0
anchor_t LookupAnchor(const Mark &mark, const std::string &name) const
virtual void OnNull(const Mark &mark, anchor_t anchor)=0
void HandleBlockMap(EventHandler &eventHandler)
void HandleFlowMap(EventHandler &eventHandler)
virtual void OnMapEnd()=0
const char *const MULTIPLE_ANCHORS
Definition: exceptions.h:34
void HandleNode(EventHandler &eventHandler)
void ParseAnchor(anchor_t &anchor)
Mark mark
Definition: token.h:78
virtual void OnMapStart(const Mark &mark, const std::string &tag, anchor_t anchor)=0
virtual void OnDocumentStart(const Mark &mark)=0
virtual void OnAlias(const Mark &mark, anchor_t anchor)=0
const anchor_t NullAnchor
Definition: anchor.h:13
const char *const END_OF_SEQ
Definition: exceptions.h:31
void HandleMap(EventHandler &eventHandler)
const Directives & m_directives
Token & peek()
Definition: scanner.cpp:38
const char *const END_OF_MAP_FLOW
Definition: exceptions.h:30
const char *const END_OF_MAP
Definition: exceptions.h:29
const char *const MULTIPLE_TAGS
Definition: exceptions.h:33
const std::string Translate(const Directives &directives)
Definition: tag.cpp:32
std::string value
Definition: token.h:79
void HandleCompactMap(EventHandler &eventHandler)
TYPE type
Definition: token.h:77
void HandleCompactMapWithNoKey(EventHandler &eventHandler)
void HandleBlockSequence(EventHandler &eventHandler)
virtual void OnScalar(const Mark &mark, const std::string &tag, anchor_t anchor, const std::string &value)=0
anchor_t RegisterAnchor(const std::string &name)


libpointmatcher
Author(s):
autogenerated on Sat May 27 2023 02:38:03