]> git.localhorst.tv Git - blank.git/blobdiff - src/io/token.cpp
fix number as bool in TokenStreamReader
[blank.git] / src / io / token.cpp
index cf3ac3b97ec87e7af45f94252807fc2bfb8237cd..a2ad44c918f0a834a409aa94fc36f4c3877eaabe 100644 (file)
@@ -1,8 +1,11 @@
+#include "Token.hpp"
 #include "Tokenizer.hpp"
 #include "TokenStreamReader.hpp"
 
 #include <cctype>
 #include <istream>
+#include <ostream>
+#include <sstream>
 #include <stdexcept>
 #include <glm/gtc/quaternion.hpp>
 
@@ -11,6 +14,59 @@ using namespace std;
 
 namespace blank {
 
+ostream &operator <<(ostream &out, Token::Type t) {
+       switch (t) {
+               case Token::ANGLE_BRACKET_OPEN:
+                       return out << "ANGLE_BRACKET_OPEN";
+               case Token::ANGLE_BRACKET_CLOSE:
+                       return out << "ANGLE_BRACKET_CLOSE";
+               case Token::CHEVRON_OPEN:
+                       return out << "CHEVRON_OPEN";
+               case Token::CHEVRON_CLOSE:
+                       return out << "CHEVRON_CLOSE";
+               case Token::BRACKET_OPEN:
+                       return out << "BRACKET_OPEN";
+               case Token::BRACKET_CLOSE:
+                       return out << "BRACKET_CLOSE";
+               case Token::PARENTHESIS_OPEN:
+                       return out << "PARENTHESIS_OPEN";
+               case Token::PARENTHESIS_CLOSE:
+                       return out << "PARENTHESIS_CLOSE";
+               case Token::COLON:
+                       return out << "COLON";
+               case Token::SEMICOLON:
+                       return out << "SEMICOLON";
+               case Token::COMMA:
+                       return out << "COMMA";
+               case Token::EQUALS:
+                       return out << "EQUALS";
+               case Token::NUMBER:
+                       return out << "NUMBER";
+               case Token::STRING:
+                       return out << "STRING";
+               case Token::IDENTIFIER:
+                       return out << "IDENTIFIER";
+               case Token::COMMENT:
+                       return out << "COMMENT";
+               default:
+                       return out << "UNKNOWN";
+       }
+}
+
+ostream &operator <<(ostream &out, const Token &t) {
+       out << t.type;
+       switch (t.type) {
+               case Token::UNKNOWN:
+               case Token::NUMBER:
+               case Token::STRING:
+               case Token::IDENTIFIER:
+               case Token::COMMENT:
+                       return out << '(' << t.value << ')';
+               default:
+                       return out;
+       }
+}
+
 Tokenizer::Tokenizer(istream &in)
 : in(in)
 , current() {
@@ -107,7 +163,7 @@ void Tokenizer::ReadString() {
                                        current.value += '\n';
                                        break;
                                case 'r':
-                                       current.value += '\t';
+                                       current.value += '\r';
                                        break;
                                case 't':
                                        current.value += '\t';
@@ -174,7 +230,7 @@ void Tokenizer::ReadIdentifier() {
 
        istream::char_type c;
        while (in.get(c)) {
-               if (isalnum(c) || c == '_') {
+               if (isalnum(c) || c == '_' || c == '.') {
                        current.value += c;
                } else {
                        in.putback(c);
@@ -195,36 +251,46 @@ bool TokenStreamReader::HasMore() {
        if (cached) {
                return true;
        }
-       while (in.HasMore()) {
-               if (in.Next().type != Token::COMMENT) {
-                       cached = true;
-                       return true;
-               }
-       }
-       return false;
+       SkipComments();
+       return cached;
 }
 
 const Token &TokenStreamReader::Next() {
+       SkipComments();
+       cached = false;
+       return in.Current();
+}
+
+void TokenStreamReader::SkipComments() {
        if (cached) {
-               cached = false;
-               return in.Current();
-       } else {
-               return in.Next();
+               if (in.Current().type == Token::COMMENT) {
+                       cached = false;
+               } else {
+                       return;
+               }
+       }
+       while (in.HasMore()) {
+               if (in.Next().type != Token::COMMENT) {
+                       cached = true;
+                       return;
+               }
        }
 }
 
 const Token &TokenStreamReader::Peek() {
        if (!cached) {
-               in.Next();
+               Next();
                cached = true;
        }
        return in.Current();
 }
 
 
-void TokenStreamReader::Assert(Token::Type t) {
+void TokenStreamReader::Assert(Token::Type t) const {
        if (GetType() != t) {
-               throw runtime_error("unexpected token in input stream");
+               stringstream s;
+               s << "unexpected token in input stream: expected " << t << ", but got " << in.Current();
+               throw runtime_error(s.str());
        }
 }
 
@@ -346,9 +412,13 @@ void TokenStreamReader::ReadQuat(glm::quat &q) {
 
 bool TokenStreamReader::GetBool() {
        Next();
+       return AsBool();
+}
+
+bool TokenStreamReader::AsBool() const {
        switch (GetType()) {
                case Token::NUMBER:
-                       return GetInt() != 0;
+                       return AsInt() != 0;
                case Token::IDENTIFIER:
                case Token::STRING:
                        if (GetValue() == "true" || GetValue() == "yes" || GetValue() == "on") {
@@ -356,27 +426,43 @@ bool TokenStreamReader::GetBool() {
                        } else if (GetValue() == "false" || GetValue() == "no" || GetValue() == "off") {
                                return false;
                        } else {
-                               throw runtime_error("unexpected value in input stream");
+                               throw runtime_error("unexpected value in input stream: cannot cast " + GetValue() + " to bool");
                        }
                default:
-                       throw runtime_error("unexpected token in input stream");
+                       {
+                               stringstream s;
+                               s << "unexpected token in input stream: cannot cast " << in.Current() << " to bool";
+                               throw runtime_error(s.str());
+                       }
        }
 }
 
 float TokenStreamReader::GetFloat() {
        Next();
+       return AsFloat();
+}
+
+float TokenStreamReader::AsFloat() const {
        Assert(Token::NUMBER);
        return stof(GetValue());
 }
 
 int TokenStreamReader::GetInt() {
        Next();
+       return AsInt();
+}
+
+int TokenStreamReader::AsInt() const {
        Assert(Token::NUMBER);
        return stoi(GetValue());
 }
 
 unsigned long TokenStreamReader::GetULong() {
        Next();
+       return AsULong();
+}
+
+unsigned long TokenStreamReader::AsULong() const {
        Assert(Token::NUMBER);
        return stoul(GetValue());
 }