singledocparser.cpp
Go to the documentation of this file.
00001 #include "singledocparser.h"
00002 #include "collectionstack.h"
00003 #include "directives.h"
00004 #include "yaml-cpp-pm/eventhandler.h"
00005 #include "yaml-cpp-pm/exceptions.h"
00006 #include "scanner.h"
00007 #include "tag.h"
00008 #include "token.h"
00009 #include <sstream>
00010 #include <cstdio>
00011 #include <algorithm>
00012 
00013 namespace YAML_PM
00014 {
00015         SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives): m_scanner(scanner), m_directives(directives), m_pCollectionStack(new CollectionStack), m_curAnchor(0)
00016         {
00017         }
00018 
00019         SingleDocParser::~SingleDocParser()
00020         {
00021         }
00022 
00023         // HandleDocument
00024         // . Handles the next document
00025         // . Throws a ParserException on error.
00026         void SingleDocParser::HandleDocument(EventHandler& eventHandler)
00027         {
00028                 assert(!m_scanner.empty()); // guaranteed that there are tokens
00029                 assert(!m_curAnchor);
00030 
00031                 eventHandler.OnDocumentStart(m_scanner.peek().mark);
00032                 
00033                 // eat doc start
00034                 if(m_scanner.peek().type == Token::DOC_START)
00035                         m_scanner.pop();
00036                 
00037                 // recurse!
00038                 HandleNode(eventHandler);
00039                 
00040                 eventHandler.OnDocumentEnd();
00041                 
00042                 // and finally eat any doc ends we see
00043                 while(!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
00044                         m_scanner.pop();
00045         }
00046         
00047         void SingleDocParser::HandleNode(EventHandler& eventHandler)
00048         {
00049                 // an empty node *is* a possibility
00050                 if(m_scanner.empty()) {
00051                         eventHandler.OnNull(Mark::null(), NullAnchor);
00052                         return;
00053                 }
00054                 
00055                 // save location
00056                 Mark mark = m_scanner.peek().mark;
00057                 
00058                 // special case: a value node by itself must be a map, with no header
00059                 if(m_scanner.peek().type == Token::VALUE) {
00060                         eventHandler.OnMapStart(mark, "", NullAnchor);
00061                         HandleMap(eventHandler);
00062                         eventHandler.OnMapEnd();
00063                         return;
00064                 }
00065                 
00066                 // special case: an alias node
00067                 if(m_scanner.peek().type == Token::ALIAS) {
00068                         eventHandler.OnAlias(mark, LookupAnchor(mark, m_scanner.peek().value));
00069                         m_scanner.pop();
00070                         return;
00071                 }
00072                 
00073                 std::string tag;
00074                 anchor_t anchor;
00075                 ParseProperties(tag, anchor);
00076                 
00077                 const Token& token = m_scanner.peek();
00078                 
00079                 // add non-specific tags
00080                 if(tag.empty())
00081                         tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
00082                 
00083                 // now split based on what kind of node we should be
00084                 switch(token.type) {
00085                         case Token::PLAIN_SCALAR:
00086                         case Token::NON_PLAIN_SCALAR:
00087                                 eventHandler.OnScalar(mark, tag, anchor, token.value);
00088                                 m_scanner.pop();
00089                                 return;
00090                         case Token::FLOW_SEQ_START:
00091                         case Token::BLOCK_SEQ_START:
00092                                 eventHandler.OnSequenceStart(mark, tag, anchor);
00093                                 HandleSequence(eventHandler);
00094                                 eventHandler.OnSequenceEnd();
00095                                 return;
00096                         case Token::FLOW_MAP_START:
00097                         case Token::BLOCK_MAP_START:
00098                                 eventHandler.OnMapStart(mark, tag, anchor);
00099                                 HandleMap(eventHandler);
00100                                 eventHandler.OnMapEnd();
00101                                 return;
00102                         case Token::KEY:
00103                                 // compact maps can only go in a flow sequence
00104                                 if(m_pCollectionStack->GetCurCollectionType() == CollectionType::FlowSeq) {
00105                                         eventHandler.OnMapStart(mark, tag, anchor);
00106                                         HandleMap(eventHandler);
00107                                         eventHandler.OnMapEnd();
00108                                         return;
00109                                 }
00110                                 break;
00111                         default:
00112                                 break;
00113                 }
00114                 
00115                 if(tag == "?")
00116                         eventHandler.OnNull(mark, anchor);
00117                 else
00118                         eventHandler.OnScalar(mark, tag, anchor, "");
00119         }
00120         
00121         void SingleDocParser::HandleSequence(EventHandler& eventHandler)
00122         {
00123                 // split based on start token
00124                 switch(m_scanner.peek().type) {
00125                         case Token::BLOCK_SEQ_START: HandleBlockSequence(eventHandler); break;
00126                         case Token::FLOW_SEQ_START: HandleFlowSequence(eventHandler); break;
00127                         default: break;
00128                 }
00129         }
00130         
00131         void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler)
00132         {
00133                 // eat start token
00134                 m_scanner.pop();
00135                 m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
00136                 
00137                 while(1) {
00138                         if(m_scanner.empty())
00139                                 throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ);
00140                         
00141                         Token token = m_scanner.peek();
00142                         if(token.type != Token::BLOCK_ENTRY && token.type != Token::BLOCK_SEQ_END)
00143                                 throw ParserException(token.mark, ErrorMsg::END_OF_SEQ);
00144                         
00145                         m_scanner.pop();
00146                         if(token.type == Token::BLOCK_SEQ_END)
00147                                 break;
00148                         
00149                         // check for null
00150                         if(!m_scanner.empty()) {
00151                                 const Token& token = m_scanner.peek();
00152                                 if(token.type == Token::BLOCK_ENTRY || token.type == Token::BLOCK_SEQ_END) {
00153                                         eventHandler.OnNull(token.mark, NullAnchor);
00154                                         continue;
00155                                 }
00156                         }
00157                         
00158                         HandleNode(eventHandler);
00159                 }
00160                 
00161                 m_pCollectionStack->PopCollectionType(CollectionType::BlockSeq);
00162         }
00163         
00164         void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler)
00165         {
00166                 // eat start token
00167                 m_scanner.pop();
00168                 m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
00169                 
00170                 while(1) {
00171                         if(m_scanner.empty())
00172                                 throw ParserException(Mark::null(), ErrorMsg::END_OF_SEQ_FLOW);
00173                         
00174                         // first check for end
00175                         if(m_scanner.peek().type == Token::FLOW_SEQ_END) {
00176                                 m_scanner.pop();
00177                                 break;
00178                         }
00179                         
00180                         // then read the node
00181                         HandleNode(eventHandler);
00182                         
00183                         // now eat the separator (or could be a sequence end, which we ignore - but if it's neither, then it's a bad node)
00184                         Token& token = m_scanner.peek();
00185                         if(token.type == Token::FLOW_ENTRY)
00186                                 m_scanner.pop();
00187                         else if(token.type != Token::FLOW_SEQ_END)
00188                                 throw ParserException(token.mark, ErrorMsg::END_OF_SEQ_FLOW);
00189                 }
00190                 
00191                 m_pCollectionStack->PopCollectionType(CollectionType::FlowSeq);
00192         }
00193         
00194         void SingleDocParser::HandleMap(EventHandler& eventHandler)
00195         {
00196                 // split based on start token
00197                 switch(m_scanner.peek().type) {
00198                         case Token::BLOCK_MAP_START: HandleBlockMap(eventHandler); break;
00199                         case Token::FLOW_MAP_START: HandleFlowMap(eventHandler); break;
00200                         case Token::KEY: HandleCompactMap(eventHandler); break;
00201                         case Token::VALUE: HandleCompactMapWithNoKey(eventHandler); break;
00202                         default: break;
00203                 }
00204         }
00205         
00206         void SingleDocParser::HandleBlockMap(EventHandler& eventHandler)
00207         {
00208                 // eat start token
00209                 m_scanner.pop();
00210                 m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
00211                 
00212                 while(1) {
00213                         if(m_scanner.empty())
00214                                 throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP);
00215                         
00216                         Token token = m_scanner.peek();
00217                         if(token.type != Token::KEY && token.type != Token::VALUE && token.type != Token::BLOCK_MAP_END)
00218                                 throw ParserException(token.mark, ErrorMsg::END_OF_MAP);
00219                         
00220                         if(token.type == Token::BLOCK_MAP_END) {
00221                                 m_scanner.pop();
00222                                 break;
00223                         }
00224                         
00225                         // grab key (if non-null)
00226                         if(token.type == Token::KEY) {
00227                                 m_scanner.pop();
00228                                 HandleNode(eventHandler);
00229                         } else {
00230                                 eventHandler.OnNull(token.mark, NullAnchor);
00231                         }
00232                         
00233                         // now grab value (optional)
00234                         if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
00235                                 m_scanner.pop();
00236                                 HandleNode(eventHandler);
00237                         } else {
00238                                 eventHandler.OnNull(token.mark, NullAnchor);
00239                         }
00240                 }
00241                 
00242                 m_pCollectionStack->PopCollectionType(CollectionType::BlockMap);
00243         }
00244         
00245         void SingleDocParser::HandleFlowMap(EventHandler& eventHandler)
00246         {
00247                 // eat start token
00248                 m_scanner.pop();
00249                 m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
00250                 
00251                 while(1) {
00252                         if(m_scanner.empty())
00253                                 throw ParserException(Mark::null(), ErrorMsg::END_OF_MAP_FLOW);
00254                         
00255                         Token& token = m_scanner.peek();
00256                         // first check for end
00257                         if(token.type == Token::FLOW_MAP_END) {
00258                                 m_scanner.pop();
00259                                 break;
00260                         }
00261                         
00262                         // grab key (if non-null)
00263                         if(token.type == Token::KEY) {
00264                                 m_scanner.pop();
00265                                 HandleNode(eventHandler);
00266                         } else {
00267                                 eventHandler.OnNull(token.mark, NullAnchor);
00268                         }
00269                         
00270                         // now grab value (optional)
00271                         if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
00272                                 m_scanner.pop();
00273                                 HandleNode(eventHandler);
00274                         } else {
00275                                 eventHandler.OnNull(token.mark, NullAnchor);
00276                         }
00277                         
00278                         // now eat the separator (or could be a map end, which we ignore - but if it's neither, then it's a bad node)
00279                         Token& nextToken = m_scanner.peek();
00280                         if(nextToken.type == Token::FLOW_ENTRY)
00281                                 m_scanner.pop();
00282                         else if(nextToken.type != Token::FLOW_MAP_END)
00283                                 throw ParserException(nextToken.mark, ErrorMsg::END_OF_MAP_FLOW);
00284                 }
00285                 
00286                 m_pCollectionStack->PopCollectionType(CollectionType::FlowMap);
00287         }
00288         
00289         // . Single "key: value" pair in a flow sequence
00290         void SingleDocParser::HandleCompactMap(EventHandler& eventHandler)
00291         {
00292                 m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
00293                 
00294                 // grab key
00295                 Mark mark = m_scanner.peek().mark;
00296                 m_scanner.pop();
00297                 HandleNode(eventHandler);
00298                 
00299                 // now grab value (optional)
00300                 if(!m_scanner.empty() && m_scanner.peek().type == Token::VALUE) {
00301                         m_scanner.pop();
00302                         HandleNode(eventHandler);
00303                 } else {
00304                         eventHandler.OnNull(mark, NullAnchor);
00305                 }
00306                 
00307                 m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
00308         }
00309         
00310         // . Single ": value" pair in a flow sequence
00311         void SingleDocParser::HandleCompactMapWithNoKey(EventHandler& eventHandler)
00312         {
00313                 m_pCollectionStack->PushCollectionType(CollectionType::CompactMap);
00314                 
00315                 // null key
00316                 eventHandler.OnNull(m_scanner.peek().mark, NullAnchor);
00317                 
00318                 // grab value
00319                 m_scanner.pop();
00320                 HandleNode(eventHandler);
00321                 
00322                 m_pCollectionStack->PopCollectionType(CollectionType::CompactMap);
00323         }
00324         
00325         // ParseProperties
00326         // . Grabs any tag or anchor tokens and deals with them.
00327         void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor)
00328         {
00329                 tag.clear();
00330                 anchor = NullAnchor;
00331                 
00332                 while(1) {
00333                         if(m_scanner.empty())
00334                                 return;
00335                         
00336                         switch(m_scanner.peek().type) {
00337                                 case Token::TAG: ParseTag(tag); break;
00338                                 case Token::ANCHOR: ParseAnchor(anchor); break;
00339                                 default: return;
00340                         }
00341                 }
00342         }
00343         
00344         void SingleDocParser::ParseTag(std::string& tag)
00345         {
00346                 Token& token = m_scanner.peek();
00347                 if(!tag.empty())
00348                         throw ParserException(token.mark, ErrorMsg::MULTIPLE_TAGS);
00349                 
00350                 Tag tagInfo(token);
00351                 tag = tagInfo.Translate(m_directives);
00352                 m_scanner.pop();
00353         }
00354         
00355         void SingleDocParser::ParseAnchor(anchor_t& anchor)
00356         {
00357                 Token& token = m_scanner.peek();
00358                 if(anchor)
00359                         throw ParserException(token.mark, ErrorMsg::MULTIPLE_ANCHORS);
00360                 
00361                 anchor = RegisterAnchor(token.value);
00362                 m_scanner.pop();
00363         }
00364         
00365         anchor_t SingleDocParser::RegisterAnchor(const std::string& name)
00366         {
00367                 if(name.empty())
00368                         return NullAnchor;
00369                 
00370                 return m_anchors[name] = ++m_curAnchor;
00371         }
00372         
00373         anchor_t SingleDocParser::LookupAnchor(const Mark& mark, const std::string& name) const
00374         {
00375                 Anchors::const_iterator it = m_anchors.find(name);
00376                 if(it == m_anchors.end())
00377                         throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
00378                 
00379                 return it->second;
00380         }
00381 }


libpointmatcher
Author(s):
autogenerated on Thu Jun 20 2019 19:51:32