1 #include "Tokenizer.hpp"
2 #include "TokenStreamReader.hpp"
7 #include <glm/gtc/quaternion.hpp>
14 Tokenizer::Tokenizer(istream &in)
21 bool Tokenizer::HasMore() {
22 return bool(istream::sentry(in));
25 const Token &Tokenizer::Next() {
30 void Tokenizer::ReadToken() {
31 current.type = Token::UNKNOWN;
32 current.value.clear();
34 istream::sentry s(in);
36 throw runtime_error("read past the end of stream");
49 current.type = Token::Type(c);
51 case '+': case '-': case '.':
52 case '0': case '1': case '2': case '3': case '4':
53 case '5': case '6': case '7': case '8': case '9':
74 bool is_num_char(istream::char_type c) {
84 void Tokenizer::ReadNumber() {
85 current.type = Token::NUMBER;
97 void Tokenizer::ReadString() {
98 current.type = Token::STRING;
101 istream::char_type c;
107 current.value += '\n';
110 current.value += '\t';
113 current.value += '\t';
119 } else if (c == '"') {
121 } else if (c == '\\') {
129 void Tokenizer::ReadComment() {
130 current.type = Token::COMMENT;
131 istream::char_type c;
135 while (in.get(c) && c != '\n') {
141 // c is guaranteed to be '/' now
143 throw runtime_error("unexpected end of stream");
146 while (in.get(c) && c != '\n') {
150 } else if (c != '*') {
151 throw runtime_error("invalid character after /");
156 istream::char_type c2;
158 throw runtime_error("unexpected end of stream");
172 void Tokenizer::ReadIdentifier() {
173 current.type = Token::IDENTIFIER;
175 istream::char_type c;
177 if (isalnum(c) || c == '_') {
187 TokenStreamReader::TokenStreamReader(istream &in)
194 bool TokenStreamReader::HasMore() {
198 while (in.HasMore()) {
199 if (in.Next().type != Token::COMMENT) {
207 const Token &TokenStreamReader::Next() {
216 const Token &TokenStreamReader::Peek() {
225 void TokenStreamReader::Assert(Token::Type t) {
226 if (GetType() != t) {
227 throw runtime_error("unexpected token in input stream");
231 Token::Type TokenStreamReader::GetType() const noexcept {
232 return in.Current().type;
235 const std::string &TokenStreamReader::GetValue() const noexcept {
236 return in.Current().value;
239 void TokenStreamReader::Skip(Token::Type t) {
245 void TokenStreamReader::ReadBoolean(bool &b) {
249 void TokenStreamReader::ReadIdentifier(string &out) {
251 Assert(Token::IDENTIFIER);
255 void TokenStreamReader::ReadNumber(float &n) {
259 void TokenStreamReader::ReadNumber(int &n) {
263 void TokenStreamReader::ReadNumber(unsigned long &n) {
267 void TokenStreamReader::ReadString(string &out) {
269 Assert(Token::STRING);
274 void TokenStreamReader::ReadVec(glm::vec2 &v) {
275 Skip(Token::BRACKET_OPEN);
279 Skip(Token::BRACKET_CLOSE);
282 void TokenStreamReader::ReadVec(glm::vec3 &v) {
283 Skip(Token::BRACKET_OPEN);
289 Skip(Token::BRACKET_CLOSE);
292 void TokenStreamReader::ReadVec(glm::vec4 &v) {
293 Skip(Token::BRACKET_OPEN);
301 Skip(Token::BRACKET_CLOSE);
304 void TokenStreamReader::ReadVec(glm::ivec2 &v) {
305 Skip(Token::BRACKET_OPEN);
309 Skip(Token::BRACKET_CLOSE);
312 void TokenStreamReader::ReadVec(glm::ivec3 &v) {
313 Skip(Token::BRACKET_OPEN);
319 Skip(Token::BRACKET_CLOSE);
322 void TokenStreamReader::ReadVec(glm::ivec4 &v) {
323 Skip(Token::BRACKET_OPEN);
331 Skip(Token::BRACKET_CLOSE);
334 void TokenStreamReader::ReadQuat(glm::quat &q) {
335 Skip(Token::BRACKET_OPEN);
343 Skip(Token::BRACKET_CLOSE);
347 bool TokenStreamReader::GetBool() {
351 return GetInt() != 0;
352 case Token::IDENTIFIER:
354 if (GetValue() == "true" || GetValue() == "yes" || GetValue() == "on") {
356 } else if (GetValue() == "false" || GetValue() == "no" || GetValue() == "off") {
359 throw runtime_error("unexpected value in input stream");
362 throw runtime_error("unexpected token in input stream");
366 float TokenStreamReader::GetFloat() {
368 Assert(Token::NUMBER);
369 return stof(GetValue());
372 int TokenStreamReader::GetInt() {
374 Assert(Token::NUMBER);
375 return stoi(GetValue());
378 unsigned long TokenStreamReader::GetULong() {
380 Assert(Token::NUMBER);
381 return stoul(GetValue());