annotate C++/Ini.cpp @ 326:fb6c42173634

Ini: - Add support for empty values - Add tests about multi definition
author David Demelier <markand@malikania.fr>
date Tue, 03 Mar 2015 19:43:23 +0100
parents d52a69f9f029
children 78e8f9a3b233
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
325
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * Ini.cpp -- .ini file parsing
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
4 * Copyright (c) 2013, 2014 David Demelier <markand@malikania.fr>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 *
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * Permission to use, copy, modify, and/or distribute this software for any
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 *
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 */
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
18
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 #include <cctype>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
20 #include <iostream>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 #include <iterator>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 #include <memory>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 #include <ostream>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 #include <sstream>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
25 #include <vector>
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
26
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 #include "Ini.h"
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
28
326
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
29 namespace {
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
30
325
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
31 /* --------------------------------------------------------
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 * Tokens
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 * -------------------------------------------------------- */
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
34
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 enum class TokenType {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
36 Comment = '#',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 SectionBegin = '[',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 SectionEnd = ']',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 Escape = '\\',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
40 QuoteSimple = '\'',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 QuoteDouble = '"',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
42 NewLine = '\n',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 Assign = '=',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
44 Include = '@',
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 Word,
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
46 Space
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
47 };
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
48
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 std::ostream &operator<<(std::ostream &out, const TokenType &type)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
50 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 switch (type) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 case TokenType::Comment:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
53 out << "Comment";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
54 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 case TokenType::SectionBegin:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
56 out << "SectionBegin";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
57 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 case TokenType::SectionEnd:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
59 out << "SectionEnd";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 case TokenType::Escape:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 out << "Escape";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 case TokenType::QuoteSimple:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 out << "QuoteSimple";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 case TokenType::QuoteDouble:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 out << "QuoteDouble";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 case TokenType::NewLine:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
71 out << "NewLine";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 case TokenType::Assign:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
74 out << "Assign";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
76 case TokenType::Include:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 out << "Include";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
78 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 case TokenType::Word:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 out << "Word";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 case TokenType::Space:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 out << "Space";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 default:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
88
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
89 return out;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
91
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 class Token {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 private:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 TokenType m_type;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 int m_line;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 int m_position;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 std::string m_value;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
98
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
99 public:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 inline Token(TokenType type, int line, int position, std::string value = "")
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 : m_type(type)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 , m_line(line)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
103 , m_position(position)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 , m_value(std::move(value))
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
107
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 inline TokenType type() const noexcept
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
109 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 return m_type;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
112
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 inline int line() const noexcept
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
114 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 return m_line;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
117
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
118 inline int position() const noexcept
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
120 return m_position;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
121 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
122
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 inline std::string value() const
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
124 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
125 switch (m_type) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 case TokenType::Comment:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
127 return "#";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 case TokenType::SectionBegin:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 return "[";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 case TokenType::SectionEnd:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 return "]";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
132 case TokenType::QuoteSimple:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
133 return "'";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 case TokenType::QuoteDouble:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
135 return "\"";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
136 case TokenType::NewLine:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 return "\n";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
138 case TokenType::Assign:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 return "=";
326
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
140 case TokenType::Include:
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
141 return "@";
325
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 case TokenType::Space:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
143 return m_value;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
144 case TokenType::Word:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
145 return m_value;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 default:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
148 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
149
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 return "";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
151 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
152
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
153 inline std::string toString() const
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
154 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
155 switch (m_type) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 case TokenType::Comment:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 return "'#'";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 case TokenType::SectionBegin:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
159 return "'['";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 case TokenType::SectionEnd:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 return "']'";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
162 case TokenType::QuoteSimple:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 return "'";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
164 case TokenType::QuoteDouble:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
165 return "\"";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 case TokenType::NewLine:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 return "<newline>";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
168 case TokenType::Assign:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
169 return "=";
326
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
170 case TokenType::Include:
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
171 return "@";
325
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
172 case TokenType::Space:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 return "<blank>";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
174 case TokenType::Word:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
175 return "`" + m_value + "'";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 default:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
177 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
178 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
179
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
180 return "";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
181 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
182 };
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
183
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
184 std::ostream &operator<<(std::ostream &out, const Token &token)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
185 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
186 out << token.type();
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
187
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
188 if (token.type() == TokenType::Space)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
189 out << ": size = " << token.value().size();
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
190 else if (token.type() == TokenType::Word)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
191 out << ": value = [" << token.value() << "]";
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
192
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
193 return out;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
194 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
195
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
196 using TokenStack = std::vector<Token>;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
197
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
198 /* --------------------------------------------------------
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
199 * IniBuilder
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
200 * -------------------------------------------------------- */
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
201
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
202 class Error : public std::exception {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
203 private:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
204 int m_line;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
205 int m_offset;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
206 std::string m_error;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
207
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
208 public:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
209 inline Error(const Token &token, std::string error)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
210 : m_line(token.line())
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
211 , m_offset(token.position())
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
212 , m_error(error)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
213 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
215
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
216 int line() const noexcept
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
217 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
218 return m_line;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
219 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
220
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
221 int offset() const noexcept
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
222 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
223 return m_offset;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
224 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
225
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
226 const char *what() const noexcept
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
228 return m_error.c_str();
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
229 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
230 };
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
231
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 class IniBuilder {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
233 private:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
234 inline bool isReserved(char c) const noexcept
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
235 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
236 return c == '\n' || c == '#' || c == '"' || c == '\'' || c == '=' || c == '[' || c == ']' || c == '@';
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
237 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
238
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
239 std::vector<Token> analyze(std::istream &stream) const
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
240 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
241 std::istreambuf_iterator<char> it(stream);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 std::istreambuf_iterator<char> end;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
243 std::vector<Token> tokens;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
244
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
245 int lineno{1};
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
246 int position{0};
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
247
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
248 while (it != end) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
249 std::string value;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
250
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
251 if (isReserved(*it)) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
252 while (it != end && isReserved(*it)) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
253 // Single character tokens
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
254 switch (*it) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
255 case '\n':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
256 ++lineno;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
257 position = 0;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
258 case '#':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
259 case '[':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
260 case ']':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
261 case '\'':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
262 case '"':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
263 case '=':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
264 case '@':
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
265 tokens.push_back({ static_cast<TokenType>(*it), lineno, position });
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
266 ++it;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
267 ++position;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
268 default:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
269 break;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
270 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
271 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
272 } else if (std::isspace(*it)) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
273 while (it != end && std::isspace(*it) && *it != '\n')
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
274 value.push_back(*it++);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
275
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
276 tokens.push_back({ TokenType::Space, lineno, position, std::move(value) });
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
277 } else {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
278 while (it != end && !std::isspace(*it) && !isReserved(*it))
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
279 value.push_back(*it++);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
280
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
281 tokens.push_back({ TokenType::Word, lineno, position, std::move(value) });
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
282 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
283 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
284
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
285 return tokens;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
286 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
287
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
288 void readComment(TokenStack::iterator &it, TokenStack::iterator end)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
289 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
290 while (it != end && it->type() != TokenType::NewLine)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
291 ++ it;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
292
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
293 // remove new line
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
294 ++ it;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
295 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
296
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
297 void readSpace(TokenStack::iterator &it, TokenStack::iterator end)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
298 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
299 while (it != end && it->type() == TokenType::Space)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
300 ++ it;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
301 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
302
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
303 void readNewLine(TokenStack::iterator &it, TokenStack::iterator end)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
304 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
305 while (it != end && it->type() == TokenType::NewLine)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
306 ++ it;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
307 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
308
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
309 IniSection readSection(TokenStack::iterator &it, TokenStack::iterator end)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
310 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
311 if (++it == end || it->type() != TokenType::Word)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
312 throw Error(*it, "word expected after [, got " + it->toString());
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
313
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
314 IniSection section(it->value());
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
315
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
316 if (++it == end || it->type() != TokenType::SectionEnd)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
317 throw Error(*it, "] expected, got " + it->toString());
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
318
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
319 // Remove ]
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
320 ++ it;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
321
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
322 if (it == end)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
323 return section;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
324
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
325 while (it != end && it->type() != TokenType::SectionBegin) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
326 if (it->type() == TokenType::Space)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
327 readSpace(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
328 else if (it->type() == TokenType::NewLine)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
329 readNewLine(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
330 else if (it->type() == TokenType::Comment)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
331 readComment(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
332 else if (it->type() == TokenType::Word)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
333 section.push_back(readOption(it, end));
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
334 else {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
335 throw Error(*it, "unexpected token " + it->toString());
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
336 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
337 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
338
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
339 return section;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
340 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
341
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
342 IniOption readOption(TokenStack::iterator &it, TokenStack::iterator end)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
343 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
344 std::string key = it->value();
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
345
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
346 if (++it == end) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
347 throw Error(*it, "expected '=' after option declaration, got <EOF>");
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
348 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
349
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
350 readSpace(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
351
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
352 if (it == end || it++->type() != TokenType::Assign) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
353 throw Error(*it, "expected '=' after option declaration, got " + it->toString());
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
354 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
355
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
356 readSpace(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
357
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
358 std::ostringstream oss;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
359
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
360 if (it->type() == TokenType::QuoteSimple || it->type() == TokenType::QuoteDouble) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
361 TokenStack::iterator save = it++;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
362
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
363 while (it != end && it->type() != save->type()) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
364 oss << it++->value();
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
365 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
366
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
367 if (it == end)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
368 throw Error(*save, "undisclosed quote: " + save->toString() + " expected");
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
369
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
370 ++ it;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
371 } else if (it->type() == TokenType::Word) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
372 oss << it++->value();
326
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
373 } else if (it->type() != TokenType::NewLine && it->type() != TokenType::Comment) {
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
374 // No value requested, must be NewLine or comment
325
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
375 throw Error(*it, "expected option value after '=', got " + it->toString());
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
376 }
326
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
377
325
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
378
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
379 return IniOption(std::move(key), oss.str());
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
380 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
381
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
382 public:
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
383 IniBuilder(Ini &ini, std::istream &stream)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
384 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
385 std::vector<Token> ts = analyze(stream);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
386
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
387 auto it = ts.begin();
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
388 auto end = ts.end();
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
389
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
390 try {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
391 while (it != end) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
392 if (it->type() == TokenType::Space)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
393 readSpace(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
394 else if (it->type() == TokenType::NewLine)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
395 readNewLine(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
396 else if (it->type() == TokenType::Comment)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
397 readComment(it, end);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
398 else if (it->type() == TokenType::SectionBegin)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
399 ini.push_back(readSection(it, end));
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
400 else
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
401 throw Error(*it, "unexpected " + it->toString() + " on root document");
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
402 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
403 } catch (const Error &ex) {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
404 std::cerr << ex.line() << ":" << ex.offset() << ":" << ex.what() << std::endl;
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
405 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
406 }
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
407 };
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
408
326
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
409 } // !namespace
David Demelier <markand@malikania.fr>
parents: 325
diff changeset
410
325
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
411 /* --------------------------------------------------------
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
412 * Ini
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
413 * -------------------------------------------------------- */
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
414
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
415 Ini::Ini(std::istream &stream)
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
416 {
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
417 IniBuilder builder(*this, stream);
d52a69f9f029 Add Ini, brand new replacement for Parser
David Demelier <markand@malikania.fr>
parents:
diff changeset
418 }