1 #include "Tokenizer.hpp"
2 #include "TokenStreamReader.hpp"
13 Tokenizer::Tokenizer(istream &in)
20 bool Tokenizer::HasMore() {
21 return bool(istream::sentry(in));
24 const Token &Tokenizer::Next() {
29 void Tokenizer::ReadToken() {
30 current.type = Token::UNKNOWN;
31 current.value.clear();
33 istream::sentry s(in);
48 current.type = Token::Type(c);
51 case '0': case '1': case '2': case '3': case '4':
52 case '5': case '6': case '7': case '8': case '9':
73 bool is_num_char(istream::char_type c) {
83 void Tokenizer::ReadNumber() {
84 current.type = Token::NUMBER;
96 void Tokenizer::ReadString() {
97 current.type = Token::STRING;
100 istream::char_type c;
106 current.value += '\n';
109 current.value += '\t';
112 current.value += '\t';
118 } else if (c == '"') {
120 } else if (c == '\\') {
128 void Tokenizer::ReadComment() {
129 current.type = Token::COMMENT;
130 istream::char_type c;
134 while (in.get(c) && c != '\n') {
140 // c is guaranteed to be '/' now
142 throw runtime_error("unexpected end of stream");
145 while (in.get(c) && c != '\n') {
149 } else if (c != '*') {
150 throw runtime_error("invalid character after /");
155 istream::char_type c2;
157 throw runtime_error("unexpected end of stream");
171 void Tokenizer::ReadIdentifier() {
172 current.type = Token::IDENTIFIER;
174 istream::char_type c;
176 if (isalnum(c) || c == '_') {
186 TokenStreamReader::TokenStreamReader(istream &in)
193 bool TokenStreamReader::HasMore() {
194 while (in.HasMore()) {
195 if (in.Next().type != Token::COMMENT) {
203 const Token &TokenStreamReader::Next() {
212 const Token &TokenStreamReader::Peek() {
221 void TokenStreamReader::Assert(Token::Type t) {
222 if (GetType() != t) {
223 throw runtime_error("unexpected token in input stream");
227 Token::Type TokenStreamReader::GetType() const noexcept {
228 return in.Current().type;
231 const std::string &TokenStreamReader::GetValue() const noexcept {
232 return in.Current().value;
235 void TokenStreamReader::Skip(Token::Type t) {
241 void TokenStreamReader::ReadBoolean(bool &b) {
245 void TokenStreamReader::ReadIdentifier(string &out) {
247 Assert(Token::IDENTIFIER);
251 void TokenStreamReader::ReadNumber(float &n) {
255 void TokenStreamReader::ReadNumber(int &n) {
259 void TokenStreamReader::ReadNumber(unsigned long &n) {
263 void TokenStreamReader::ReadString(string &out) {
265 Assert(Token::STRING);
270 void TokenStreamReader::ReadVec(glm::vec2 &v) {
271 Skip(Token::BRACKET_OPEN);
275 Skip(Token::BRACKET_CLOSE);
278 void TokenStreamReader::ReadVec(glm::vec3 &v) {
279 Skip(Token::BRACKET_OPEN);
285 Skip(Token::BRACKET_CLOSE);
288 void TokenStreamReader::ReadVec(glm::vec4 &v) {
289 Skip(Token::BRACKET_OPEN);
297 Skip(Token::BRACKET_CLOSE);
300 void TokenStreamReader::ReadVec(glm::ivec2 &v) {
301 Skip(Token::BRACKET_OPEN);
305 Skip(Token::BRACKET_CLOSE);
308 void TokenStreamReader::ReadVec(glm::ivec3 &v) {
309 Skip(Token::BRACKET_OPEN);
315 Skip(Token::BRACKET_CLOSE);
318 void TokenStreamReader::ReadVec(glm::ivec4 &v) {
319 Skip(Token::BRACKET_OPEN);
327 Skip(Token::BRACKET_CLOSE);
331 bool TokenStreamReader::GetBool() {
335 return GetInt() != 0;
336 case Token::IDENTIFIER:
338 if (GetValue() == "true" || GetValue() == "yes" || GetValue() == "on") {
340 } else if (GetValue() == "false" || GetValue() == "no" || GetValue() == "off") {
343 throw runtime_error("unexpected value in input stream");
346 throw runtime_error("unexpected token in input stream");
350 float TokenStreamReader::GetFloat() {
352 Assert(Token::NUMBER);
353 return stof(GetValue());
356 int TokenStreamReader::GetInt() {
358 Assert(Token::NUMBER);
359 return stoi(GetValue());
362 unsigned long TokenStreamReader::GetULong() {
364 Assert(Token::NUMBER);
365 return stoul(GetValue());