1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
#ifndef TOKENIZER_H
#define TOKENIZER_H
#include <fstream>
#include <stdexcept>
namespace wsclean {
class Tokenizer {
public:
std::string getString() {
std::string token;
getToken(token);
if (token.size() < 2 || token[0] != '\"' || token[token.size() - 1] != '\"')
throw std::runtime_error("Expecting string");
return token.substr(1, token.size() - 2);
}
double getTokenAsDouble() {
std::string token;
getToken(token);
return atof(token.c_str());
}
bool getTokenAsBool() {
std::string token;
getToken(token);
if (token == "1" || token == "true" || token == "True")
return true;
else if (token == "0" || token == "false" || token == "False")
return false;
else
throw std::runtime_error("Expecting boolean");
}
bool getToken(std::string &token) {
if (!_stream->good()) return false;
std::stringstream s;
bool finished = false;
enum {
StateStart,
StateInToken,
StateInString,
StateEscaped,
StateInLineComment
} state = StateStart;
do {
char c;
_stream->get(c);
if (!_stream->fail()) {
switch (state) {
case StateStart:
if (!(c == ' ' || c == '\t' || c == '\n')) {
if (c == '/')
state = StateEscaped;
else {
s << c;
if (c == '\"')
state = StateInString;
else
state = StateInToken;
}
}
break;
case StateInString:
s << c;
if (c == '\"') finished = true;
break;
case StateInToken:
if (c == ' ' || c == '\t' || c == '\n' || c == ';')
finished = true;
else
s << c;
break;
case StateEscaped:
if (c == '/')
state = StateInLineComment;
else
throw std::runtime_error("Incorrect /");
break;
case StateInLineComment:
if (c == '\n') state = StateStart;
break;
}
} else {
token = s.str();
return !token.empty();
}
} while (!finished);
token = s.str();
return true;
}
void SetStream(std::ifstream &stream) { _stream = &stream; }
std::ifstream &Stream() { return *_stream; }
const std::ifstream &Stream() const { return *_stream; }
std::ifstream *_stream;
};
} // namespace wsclean
#endif
|