2 #include "Tokenizer.hpp"
3 #include "TokenStreamReader.hpp"
10 #include <glm/gtc/quaternion.hpp>
18 ostream &operator <<(ostream &out, Token::Type t) {
20 case Token::ANGLE_BRACKET_OPEN:
21 return out << "ANGLE_BRACKET_OPEN";
22 case Token::ANGLE_BRACKET_CLOSE:
23 return out << "ANGLE_BRACKET_CLOSE";
24 case Token::CHEVRON_OPEN:
25 return out << "CHEVRON_OPEN";
26 case Token::CHEVRON_CLOSE:
27 return out << "CHEVRON_CLOSE";
28 case Token::BRACKET_OPEN:
29 return out << "BRACKET_OPEN";
30 case Token::BRACKET_CLOSE:
31 return out << "BRACKET_CLOSE";
32 case Token::PARENTHESIS_OPEN:
33 return out << "PARENTHESIS_OPEN";
34 case Token::PARENTHESIS_CLOSE:
35 return out << "PARENTHESIS_CLOSE";
37 return out << "COLON";
38 case Token::SEMICOLON:
39 return out << "SEMICOLON";
41 return out << "COMMA";
43 return out << "EQUALS";
45 return out << "NUMBER";
47 return out << "STRING";
48 case Token::IDENTIFIER:
49 return out << "IDENTIFIER";
51 return out << "COMMENT";
53 return out << "UNKNOWN";
57 ostream &operator <<(ostream &out, const Token &t) {
63 case Token::IDENTIFIER:
65 return out << '(' << t.value << ')';
71 Tokenizer::Tokenizer(istream &in)
78 bool Tokenizer::HasMore() {
79 return bool(istream::sentry(in));
82 const Token &Tokenizer::Next() {
87 void Tokenizer::ReadToken() {
88 current.type = Token::UNKNOWN;
89 current.value.clear();
91 istream::sentry s(in);
93 throw runtime_error("read past the end of stream");
106 current.type = Token::Type(c);
108 case '+': case '-': case '.':
109 case '0': case '1': case '2': case '3': case '4':
110 case '5': case '6': case '7': case '8': case '9':
131 bool is_num_char(istream::char_type c) {
141 void Tokenizer::ReadNumber() {
142 current.type = Token::NUMBER;
143 istream::char_type c;
145 if (is_num_char(c)) {
154 void Tokenizer::ReadString() {
155 current.type = Token::STRING;
158 istream::char_type c;
164 current.value += '\n';
167 current.value += '\r';
170 current.value += '\t';
176 } else if (c == '"') {
178 } else if (c == '\\') {
186 void Tokenizer::ReadComment() {
187 current.type = Token::COMMENT;
188 istream::char_type c;
192 while (in.get(c) && c != '\n') {
198 // c is guaranteed to be '/' now
200 throw runtime_error("unexpected end of stream");
203 while (in.get(c) && c != '\n') {
207 } else if (c != '*') {
208 throw runtime_error("invalid character after /");
213 istream::char_type c2;
215 throw runtime_error("unexpected end of stream");
229 void Tokenizer::ReadIdentifier() {
230 current.type = Token::IDENTIFIER;
232 istream::char_type c;
234 if (isalnum(c) || c == '_' || c == '.') {
244 TokenStreamReader::TokenStreamReader(istream &in)
251 bool TokenStreamReader::HasMore() {
259 const Token &TokenStreamReader::Next() {
265 void TokenStreamReader::SkipComments() {
267 if (in.Current().type == Token::COMMENT) {
273 while (in.HasMore()) {
274 if (in.Next().type != Token::COMMENT) {
281 const Token &TokenStreamReader::Peek() {
290 void TokenStreamReader::Assert(Token::Type t) const {
291 if (GetType() != t) {
293 s << "unexpected token in input stream: expected " << t << ", but got " << in.Current();
294 throw runtime_error(s.str());
298 Token::Type TokenStreamReader::GetType() const noexcept {
299 return in.Current().type;
302 const std::string &TokenStreamReader::GetValue() const noexcept {
303 return in.Current().value;
306 void TokenStreamReader::Skip(Token::Type t) {
312 void TokenStreamReader::ReadBoolean(bool &b) {
316 void TokenStreamReader::ReadIdentifier(string &out) {
318 Assert(Token::IDENTIFIER);
322 void TokenStreamReader::ReadNumber(double &n) {
326 void TokenStreamReader::ReadNumber(float &n) {
330 void TokenStreamReader::ReadNumber(int &n) {
334 void TokenStreamReader::ReadNumber(unsigned long &n) {
338 void TokenStreamReader::ReadString(string &out) {
340 Assert(Token::STRING);
345 void TokenStreamReader::ReadVec(glm::vec2 &v) {
346 Skip(Token::BRACKET_OPEN);
350 Skip(Token::BRACKET_CLOSE);
353 void TokenStreamReader::ReadVec(glm::vec3 &v) {
354 Skip(Token::BRACKET_OPEN);
360 Skip(Token::BRACKET_CLOSE);
363 void TokenStreamReader::ReadVec(glm::vec4 &v) {
364 Skip(Token::BRACKET_OPEN);
372 Skip(Token::BRACKET_CLOSE);
375 void TokenStreamReader::ReadVec(glm::dvec2 &v) {
376 Skip(Token::BRACKET_OPEN);
380 Skip(Token::BRACKET_CLOSE);
383 void TokenStreamReader::ReadVec(glm::dvec3 &v) {
384 Skip(Token::BRACKET_OPEN);
390 Skip(Token::BRACKET_CLOSE);
393 void TokenStreamReader::ReadVec(glm::dvec4 &v) {
394 Skip(Token::BRACKET_OPEN);
402 Skip(Token::BRACKET_CLOSE);
405 void TokenStreamReader::ReadVec(glm::ivec2 &v) {
406 Skip(Token::BRACKET_OPEN);
410 Skip(Token::BRACKET_CLOSE);
413 void TokenStreamReader::ReadVec(glm::ivec3 &v) {
414 Skip(Token::BRACKET_OPEN);
420 Skip(Token::BRACKET_CLOSE);
423 void TokenStreamReader::ReadVec(glm::ivec4 &v) {
424 Skip(Token::BRACKET_OPEN);
432 Skip(Token::BRACKET_CLOSE);
435 void TokenStreamReader::ReadQuat(glm::quat &q) {
436 Skip(Token::BRACKET_OPEN);
444 Skip(Token::BRACKET_CLOSE);
447 void TokenStreamReader::ReadQuat(glm::dquat &q) {
448 Skip(Token::BRACKET_OPEN);
456 Skip(Token::BRACKET_CLOSE);
460 bool TokenStreamReader::GetBool() {
465 bool TokenStreamReader::AsBool() const {
469 case Token::IDENTIFIER:
471 if (GetValue() == "true" || GetValue() == "yes" || GetValue() == "on") {
473 } else if (GetValue() == "false" || GetValue() == "no" || GetValue() == "off") {
476 throw runtime_error("unexpected value in input stream: cannot cast " + GetValue() + " to bool");
481 s << "unexpected token in input stream: cannot cast " << in.Current() << " to bool";
482 throw runtime_error(s.str());
487 float TokenStreamReader::GetDouble() {
492 float TokenStreamReader::AsDouble() const {
493 Assert(Token::NUMBER);
494 return stod(GetValue());
497 float TokenStreamReader::GetFloat() {
502 float TokenStreamReader::AsFloat() const {
503 Assert(Token::NUMBER);
504 return stof(GetValue());
507 int TokenStreamReader::GetInt() {
512 int TokenStreamReader::AsInt() const {
513 Assert(Token::NUMBER);
514 return stoi(GetValue());
517 unsigned long TokenStreamReader::GetULong() {
522 unsigned long TokenStreamReader::AsULong() const {
523 Assert(Token::NUMBER);
524 return stoul(GetValue());