X-Git-Url: http://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fio%2Ftoken.cpp;h=588c125674b870d126e29147e16402994757a611;hb=d507e4b06e32aff46caacf961b310ba1050b232f;hp=5e734ad573b634ed4fcf101c89735f7c64dda4b2;hpb=ede25c0a2f59e21521d1cd962e6ea9d78169ca12;p=blank.git diff --git a/src/io/token.cpp b/src/io/token.cpp index 5e734ad..588c125 100644 --- a/src/io/token.cpp +++ b/src/io/token.cpp @@ -1,15 +1,72 @@ +#include "Token.hpp" #include "Tokenizer.hpp" #include "TokenStreamReader.hpp" #include #include +#include +#include #include +#include 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() { @@ -32,7 +89,7 @@ void Tokenizer::ReadToken() { istream::sentry s(in); if (!s) { - // TODO: error? + throw runtime_error("read past the end of stream"); return; } @@ -47,7 +104,7 @@ void Tokenizer::ReadToken() { case ',': case '=': current.type = Token::Type(c); break; - case '+': case '-': + case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': in.putback(c); @@ -71,7 +128,7 @@ void Tokenizer::ReadToken() { namespace { bool is_num_char(istream::char_type c) { - return isdigit(c) + return isxdigit(c) || c == '.' || c == '-' || c == '+' @@ -106,7 +163,7 @@ void Tokenizer::ReadString() { current.value += '\n'; break; case 'r': - current.value += '\t'; + current.value += '\r'; break; case 't': current.value += '\t'; @@ -173,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); @@ -191,27 +248,38 @@ TokenStreamReader::TokenStreamReader(istream &in) bool TokenStreamReader::HasMore() { - while (in.HasMore()) { - if (in.Next().type != Token::COMMENT) { - cached = true; - return true; - } + if (cached) { + 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(); @@ -220,7 +288,9 @@ const Token &TokenStreamReader::Peek() { void TokenStreamReader::Assert(Token::Type t) { 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()); } } @@ -327,6 +397,18 @@ void TokenStreamReader::ReadVec(glm::ivec4 &v) { Skip(Token::BRACKET_CLOSE); } +void TokenStreamReader::ReadQuat(glm::quat &q) { + Skip(Token::BRACKET_OPEN); + ReadNumber(q.w); + Skip(Token::COMMA); + ReadNumber(q.x); + Skip(Token::COMMA); + ReadNumber(q.y); + Skip(Token::COMMA); + ReadNumber(q.z); + Skip(Token::BRACKET_CLOSE); +} + bool TokenStreamReader::GetBool() { Next(); @@ -340,10 +422,14 @@ 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()); + } } }