Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / external_libraries / yaml-cpp-0.3.0 / src / parser.cpp
blobb836823f9a89759176996e744a1649486a193a16
1 #include "yaml-cpp/parser.h"
2 #include "yaml-cpp/eventhandler.h"
3 #include "yaml-cpp/exceptions.h"
4 #include "yaml-cpp/node.h"
5 #include "directives.h"
6 #include "nodebuilder.h"
7 #include "scanner.h"
8 #include "singledocparser.h"
9 #include "tag.h"
10 #include "token.h"
11 #include <sstream>
12 #include <cstdio>
14 namespace YAML
16 Parser::Parser()
20 Parser::Parser(std::istream& in)
22 Load(in);
25 Parser::~Parser()
29 Parser::operator bool() const
31 return m_pScanner.get() && !m_pScanner->empty();
34 void Parser::Load(std::istream& in)
36 m_pScanner.reset(new Scanner(in));
37 m_pDirectives.reset(new Directives);
40 // HandleNextDocument
41 // . Handles the next document
42 // . Throws a ParserException on error.
43 // . Returns false if there are no more documents
44 bool Parser::HandleNextDocument(EventHandler& eventHandler)
46 if(!m_pScanner.get())
47 return false;
49 ParseDirectives();
50 if(m_pScanner->empty())
51 return false;
53 SingleDocParser sdp(*m_pScanner, *m_pDirectives);
54 sdp.HandleDocument(eventHandler);
55 return true;
58 // GetNextDocument
59 // . Reads the next document in the queue (of tokens).
60 // . Throws a ParserException on error.
61 bool Parser::GetNextDocument(Node& document)
63 NodeBuilder builder(document);
64 return HandleNextDocument(builder);
67 // ParseDirectives
68 // . Reads any directives that are next in the queue.
69 void Parser::ParseDirectives()
71 bool readDirective = false;
73 while(1) {
74 if(m_pScanner->empty())
75 break;
77 Token& token = m_pScanner->peek();
78 if(token.type != Token::DIRECTIVE)
79 break;
81 // we keep the directives from the last document if none are specified;
82 // but if any directives are specific, then we reset them
83 if(!readDirective)
84 m_pDirectives.reset(new Directives);
86 readDirective = true;
87 HandleDirective(token);
88 m_pScanner->pop();
92 void Parser::HandleDirective(const Token& token)
94 if(token.value == "YAML")
95 HandleYamlDirective(token);
96 else if(token.value == "TAG")
97 HandleTagDirective(token);
100 // HandleYamlDirective
101 // . Should be of the form 'major.minor' (like a version number)
102 void Parser::HandleYamlDirective(const Token& token)
104 if(token.params.size() != 1)
105 throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
107 if(!m_pDirectives->version.isDefault)
108 throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
110 std::stringstream str(token.params[0]);
111 str >> m_pDirectives->version.major;
112 str.get();
113 str >> m_pDirectives->version.minor;
114 if(!str || str.peek() != EOF)
115 throw ParserException(token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
117 if(m_pDirectives->version.major > 1)
118 throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
120 m_pDirectives->version.isDefault = false;
121 // TODO: warning on major == 1, minor > 2?
124 // HandleTagDirective
125 // . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
126 void Parser::HandleTagDirective(const Token& token)
128 if(token.params.size() != 2)
129 throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
131 const std::string& handle = token.params[0];
132 const std::string& prefix = token.params[1];
133 if(m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
134 throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
136 m_pDirectives->tags[handle] = prefix;
139 void Parser::PrintTokens(std::ostream& out)
141 if(!m_pScanner.get())
142 return;
144 while(1) {
145 if(m_pScanner->empty())
146 break;
148 out << m_pScanner->peek() << "\n";
149 m_pScanner->pop();