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"
8 #include "singledocparser.h"
20 Parser::Parser(std::istream
& in
)
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
);
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
)
50 if(m_pScanner
->empty())
53 SingleDocParser
sdp(*m_pScanner
, *m_pDirectives
);
54 sdp
.HandleDocument(eventHandler
);
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
);
68 // . Reads any directives that are next in the queue.
69 void Parser::ParseDirectives()
71 bool readDirective
= false;
74 if(m_pScanner
->empty())
77 Token
& token
= m_pScanner
->peek();
78 if(token
.type
!= Token::DIRECTIVE
)
81 // we keep the directives from the last document if none are specified;
82 // but if any directives are specific, then we reset them
84 m_pDirectives
.reset(new Directives
);
87 HandleDirective(token
);
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
;
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())
145 if(m_pScanner
->empty())
148 out
<< m_pScanner
->peek() << "\n";