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);
35 throw runtime_error("read past the end of stream");
48 current.type = Token::Type(c);
50 case '+': case '-': case '.':
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() {
197 while (in.HasMore()) {
198 if (in.Next().type != Token::COMMENT) {
206 const Token &TokenStreamReader::Next() {
215 const Token &TokenStreamReader::Peek() {
224 void TokenStreamReader::Assert(Token::Type t) {
225 if (GetType() != t) {
226 throw runtime_error("unexpected token in input stream");
230 Token::Type TokenStreamReader::GetType() const noexcept {
231 return in.Current().type;
234 const std::string &TokenStreamReader::GetValue() const noexcept {
235 return in.Current().value;
238 void TokenStreamReader::Skip(Token::Type t) {
244 void TokenStreamReader::ReadBoolean(bool &b) {
248 void TokenStreamReader::ReadIdentifier(string &out) {
250 Assert(Token::IDENTIFIER);
254 void TokenStreamReader::ReadNumber(float &n) {
258 void TokenStreamReader::ReadNumber(int &n) {
262 void TokenStreamReader::ReadNumber(unsigned long &n) {
266 void TokenStreamReader::ReadString(string &out) {
268 Assert(Token::STRING);
273 void TokenStreamReader::ReadVec(glm::vec2 &v) {
274 Skip(Token::BRACKET_OPEN);
278 Skip(Token::BRACKET_CLOSE);
281 void TokenStreamReader::ReadVec(glm::vec3 &v) {
282 Skip(Token::BRACKET_OPEN);
288 Skip(Token::BRACKET_CLOSE);
291 void TokenStreamReader::ReadVec(glm::vec4 &v) {
292 Skip(Token::BRACKET_OPEN);
300 Skip(Token::BRACKET_CLOSE);
303 void TokenStreamReader::ReadVec(glm::ivec2 &v) {
304 Skip(Token::BRACKET_OPEN);
308 Skip(Token::BRACKET_CLOSE);
311 void TokenStreamReader::ReadVec(glm::ivec3 &v) {
312 Skip(Token::BRACKET_OPEN);
318 Skip(Token::BRACKET_CLOSE);
321 void TokenStreamReader::ReadVec(glm::ivec4 &v) {
322 Skip(Token::BRACKET_OPEN);
330 Skip(Token::BRACKET_CLOSE);
334 bool TokenStreamReader::GetBool() {
338 return GetInt() != 0;
339 case Token::IDENTIFIER:
341 if (GetValue() == "true" || GetValue() == "yes" || GetValue() == "on") {
343 } else if (GetValue() == "false" || GetValue() == "no" || GetValue() == "off") {
346 throw runtime_error("unexpected value in input stream");
349 throw runtime_error("unexpected token in input stream");
353 float TokenStreamReader::GetFloat() {
355 Assert(Token::NUMBER);
356 return stof(GetValue());
359 int TokenStreamReader::GetInt() {
361 Assert(Token::NUMBER);
362 return stoi(GetValue());
365 unsigned long TokenStreamReader::GetULong() {
367 Assert(Token::NUMBER);
368 return stoul(GetValue());