Mercurial > code
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 |
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 | 29 namespace { |
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 | 140 case TokenType::Include: |
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 | 170 case TokenType::Include: |
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 | 373 } else if (it->type() != TokenType::NewLine && it->type() != TokenType::Comment) { |
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 | 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 | 409 } // !namespace |
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 } |