1 #include "singledocparser.h"
2 #include "collectionstack.h"
3 #include "directives.h"
4 #include "yaml-cpp/eventhandler.h"
5 #include "yaml-cpp/exceptions.h"
15 SingleDocParser::SingleDocParser(Scanner
& scanner
, const Directives
& directives
): m_scanner(scanner
), m_directives(directives
), m_pCollectionStack(new CollectionStack
), m_curAnchor(0)
19 SingleDocParser::~SingleDocParser()
24 // . Handles the next document
25 // . Throws a ParserException on error.
26 void SingleDocParser::HandleDocument(EventHandler
& eventHandler
)
28 assert(!m_scanner
.empty()); // guaranteed that there are tokens
31 eventHandler
.OnDocumentStart(m_scanner
.peek().mark
);
34 if(m_scanner
.peek().type
== Token::DOC_START
)
38 HandleNode(eventHandler
);
40 eventHandler
.OnDocumentEnd();
42 // and finally eat any doc ends we see
43 while(!m_scanner
.empty() && m_scanner
.peek().type
== Token::DOC_END
)
47 void SingleDocParser::HandleNode(EventHandler
& eventHandler
)
49 // an empty node *is* a possibility
50 if(m_scanner
.empty()) {
51 eventHandler
.OnNull(Mark::null(), NullAnchor
);
56 Mark mark
= m_scanner
.peek().mark
;
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();
66 // special case: an alias node
67 if(m_scanner
.peek().type
== Token::ALIAS
) {
68 eventHandler
.OnAlias(mark
, LookupAnchor(mark
, m_scanner
.peek().value
));
75 ParseProperties(tag
, anchor
);
77 const Token
& token
= m_scanner
.peek();
79 // add non-specific tags
81 tag
= (token
.type
== Token::NON_PLAIN_SCALAR
? "!" : "?");
83 // now split based on what kind of node we should be
85 case Token::PLAIN_SCALAR
:
86 case Token::NON_PLAIN_SCALAR
:
87 eventHandler
.OnScalar(mark
, tag
, anchor
, token
.value
);
90 case Token::FLOW_SEQ_START
:
91 case Token::BLOCK_SEQ_START
:
92 eventHandler
.OnSequenceStart(mark
, tag
, anchor
);
93 HandleSequence(eventHandler
);
94 eventHandler
.OnSequenceEnd();
96 case Token::FLOW_MAP_START
:
97 case Token::BLOCK_MAP_START
:
98 eventHandler
.OnMapStart(mark
, tag
, anchor
);
99 HandleMap(eventHandler
);
100 eventHandler
.OnMapEnd();
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();
116 eventHandler
.OnNull(mark
, anchor
);
118 eventHandler
.OnScalar(mark
, tag
, anchor
, "");
121 void SingleDocParser::HandleSequence(EventHandler
& eventHandler
)
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;
131 void SingleDocParser::HandleBlockSequence(EventHandler
& eventHandler
)
135 m_pCollectionStack
->PushCollectionType(CollectionType::BlockSeq
);
138 if(m_scanner
.empty())
139 throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ
);
141 Token token
= m_scanner
.peek();
142 if(token
.type
!= Token::BLOCK_ENTRY
&& token
.type
!= Token::BLOCK_SEQ_END
)
143 throw ParserException(token
.mark
, ErrorMsg::END_OF_SEQ
);
146 if(token
.type
== Token::BLOCK_SEQ_END
)
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
);
158 HandleNode(eventHandler
);
161 m_pCollectionStack
->PopCollectionType(CollectionType::BlockSeq
);
164 void SingleDocParser::HandleFlowSequence(EventHandler
& eventHandler
)
168 m_pCollectionStack
->PushCollectionType(CollectionType::FlowSeq
);
171 if(m_scanner
.empty())
172 throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW
);
174 // first check for end
175 if(m_scanner
.peek().type
== Token::FLOW_SEQ_END
) {
180 // then read the node
181 HandleNode(eventHandler
);
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
)
187 else if(token
.type
!= Token::FLOW_SEQ_END
)
188 throw ParserException(token
.mark
, ErrorMsg::END_OF_SEQ_FLOW
);
191 m_pCollectionStack
->PopCollectionType(CollectionType::FlowSeq
);
194 void SingleDocParser::HandleMap(EventHandler
& eventHandler
)
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;
206 void SingleDocParser::HandleBlockMap(EventHandler
& eventHandler
)
210 m_pCollectionStack
->PushCollectionType(CollectionType::BlockMap
);
213 if(m_scanner
.empty())
214 throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP
);
216 Token token
= m_scanner
.peek();
217 if(token
.type
!= Token::KEY
&& token
.type
!= Token::VALUE
&& token
.type
!= Token::BLOCK_MAP_END
)
218 throw ParserException(token
.mark
, ErrorMsg::END_OF_MAP
);
220 if(token
.type
== Token::BLOCK_MAP_END
) {
225 // grab key (if non-null)
226 if(token
.type
== Token::KEY
) {
228 HandleNode(eventHandler
);
230 eventHandler
.OnNull(token
.mark
, NullAnchor
);
233 // now grab value (optional)
234 if(!m_scanner
.empty() && m_scanner
.peek().type
== Token::VALUE
) {
236 HandleNode(eventHandler
);
238 eventHandler
.OnNull(token
.mark
, NullAnchor
);
242 m_pCollectionStack
->PopCollectionType(CollectionType::BlockMap
);
245 void SingleDocParser::HandleFlowMap(EventHandler
& eventHandler
)
249 m_pCollectionStack
->PushCollectionType(CollectionType::FlowMap
);
252 if(m_scanner
.empty())
253 throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW
);
255 Token
& token
= m_scanner
.peek();
256 // first check for end
257 if(token
.type
== Token::FLOW_MAP_END
) {
262 // grab key (if non-null)
263 if(token
.type
== Token::KEY
) {
265 HandleNode(eventHandler
);
267 eventHandler
.OnNull(token
.mark
, NullAnchor
);
270 // now grab value (optional)
271 if(!m_scanner
.empty() && m_scanner
.peek().type
== Token::VALUE
) {
273 HandleNode(eventHandler
);
275 eventHandler
.OnNull(token
.mark
, NullAnchor
);
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
)
282 else if(nextToken
.type
!= Token::FLOW_MAP_END
)
283 throw ParserException(nextToken
.mark
, ErrorMsg::END_OF_MAP_FLOW
);
286 m_pCollectionStack
->PopCollectionType(CollectionType::FlowMap
);
289 // . Single "key: value" pair in a flow sequence
290 void SingleDocParser::HandleCompactMap(EventHandler
& eventHandler
)
292 m_pCollectionStack
->PushCollectionType(CollectionType::CompactMap
);
295 Mark mark
= m_scanner
.peek().mark
;
297 HandleNode(eventHandler
);
299 // now grab value (optional)
300 if(!m_scanner
.empty() && m_scanner
.peek().type
== Token::VALUE
) {
302 HandleNode(eventHandler
);
304 eventHandler
.OnNull(mark
, NullAnchor
);
307 m_pCollectionStack
->PopCollectionType(CollectionType::CompactMap
);
310 // . Single ": value" pair in a flow sequence
311 void SingleDocParser::HandleCompactMapWithNoKey(EventHandler
& eventHandler
)
313 m_pCollectionStack
->PushCollectionType(CollectionType::CompactMap
);
316 eventHandler
.OnNull(m_scanner
.peek().mark
, NullAnchor
);
320 HandleNode(eventHandler
);
322 m_pCollectionStack
->PopCollectionType(CollectionType::CompactMap
);
326 // . Grabs any tag or anchor tokens and deals with them.
327 void SingleDocParser::ParseProperties(std::string
& tag
, anchor_t
& anchor
)
333 if(m_scanner
.empty())
336 switch(m_scanner
.peek().type
) {
337 case Token::TAG
: ParseTag(tag
); break;
338 case Token::ANCHOR
: ParseAnchor(anchor
); break;
344 void SingleDocParser::ParseTag(std::string
& tag
)
346 Token
& token
= m_scanner
.peek();
348 throw ParserException(token
.mark
, ErrorMsg::MULTIPLE_TAGS
);
351 tag
= tagInfo
.Translate(m_directives
);
355 void SingleDocParser::ParseAnchor(anchor_t
& anchor
)
357 Token
& token
= m_scanner
.peek();
359 throw ParserException(token
.mark
, ErrorMsg::MULTIPLE_ANCHORS
);
361 anchor
= RegisterAnchor(token
.value
);
365 anchor_t
SingleDocParser::RegisterAnchor(const std::string
& name
)
370 return m_anchors
[name
] = ++m_curAnchor
;
373 anchor_t
SingleDocParser::LookupAnchor(const Mark
& mark
, const std::string
& name
) const
375 Anchors::const_iterator it
= m_anchors
.find(name
);
376 if(it
== m_anchors
.end())
377 throw ParserException(mark
, ErrorMsg::UNKNOWN_ANCHOR
);