parser.cpp 2.18 KB
Newer Older
1
#include "parser.h"
2
#include "scanner.h"
3
#include "token.h"
Jesse Beder's avatar
Jesse Beder committed
4
#include "exceptions.h"
5
#include <sstream>
6
7
8

namespace YAML
{
9
	Parser::Parser(std::istream& in): m_pScanner(0)
10
	{
11
		m_pScanner = new Scanner(in);
12
		m_state.Reset();
13
14
15
16
	}

	Parser::~Parser()
	{
17
		delete m_pScanner;
18
19
	}

20
21
22
23
24
	Parser::operator bool() const
	{
		return m_pScanner->PeekNextToken() != 0;
	}

Jesse Beder's avatar
Jesse Beder committed
25
	void Parser::GetNextDocument(Document& document)
26
	{
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
		// first read directives
		ParseDirectives();

		// then parse the document
		document.Parse(m_pScanner, m_state);
	}

	void Parser::ParseDirectives()
	{
		bool readDirective = false;

		while(1) {
			Token *pToken = m_pScanner->PeekNextToken();
			if(!pToken || pToken->type != TT_DIRECTIVE)
				break;

			// we keep the directives from the last document if none are specified;
			// but if any directives are specific, then we reset them
			if(!readDirective)
				m_state.Reset();

			readDirective = true;
			HandleDirective(pToken->value, pToken->params);
			m_pScanner->PopNextToken();
		}
	}

	void Parser::HandleDirective(const std::string& name, const std::vector <std::string>& params)
	{
		if(name == "YAML")
			HandleYamlDirective(params);
		else if(name == "TAG")
			HandleTagDirective(params);
	}

	// HandleYamlDirective
	// . Should be of the form 'major.minor' (like a version number)
	void Parser::HandleYamlDirective(const std::vector <std::string>& params)
	{
Jesse Beder's avatar
Jesse Beder committed
66
67
		if(params.size() != 1)
			throw BadYAMLDirective();
68
69
70
71
72
73

		std::stringstream str(params[0]);
		str >> m_state.version.major;
		str.get();
		str >> m_state.version.minor;
		if(!str)
Jesse Beder's avatar
Jesse Beder committed
74
			throw BadYAMLDirective();  // TODO: or throw if there are any more characters in the stream?
75

Jesse Beder's avatar
Jesse Beder committed
76
		// TODO: throw on major > 1? warning on major == 1, minor > 2?
77
78
79
80
81
	}

	void Parser::HandleTagDirective(const std::vector <std::string>& params)
	{
		if(params.size() != 2)
Jesse Beder's avatar
Jesse Beder committed
82
			throw BadTAGDirective();
83
84
85

		std::string handle = params[0], prefix = params[1];
		m_state.tags[handle] = prefix;
86
	}
87

88
	void Parser::PrintTokens(std::ostream& out)
89
90
91
92
93
94
	{
		while(1) {
			Token *pToken = m_pScanner->GetNextToken();
			if(!pToken)
				break;

95
			out << *pToken << std::endl;
96
97
		}
	}
98
}