4 * Created on: Aug 26, 2012
14 bool Tokenizer::HasMore() {
15 if (isPutback) return true;
17 if (!in) return false;
19 putback = ReadToken();
21 if (!skipComments || putback.type != Token::COMMENT) return true;
23 while (in && putback.type == Token::COMMENT) {
24 putback = ReadToken();
27 return putback.type != Token::COMMENT;
30 void Tokenizer::ScanSpace() {
31 std::istream::char_type c;
33 while (in && std::isspace(c)) {
44 void Tokenizer::Putback(const Token &t) {
46 throw LexerError(line, "Tokenizer: double putback not supported");
53 const Tokenizer::Token &Tokenizer::Peek() {
61 Tokenizer::Token Tokenizer::GetNext() {
63 throw LexerError(line, "read beyond last token");
73 Tokenizer::Token Tokenizer::ReadToken() {
75 std::istream::char_type c;
78 case Token::ANGLE_BRACKET_OPEN:
79 case Token::ANGLE_BRACKET_CLOSE:
82 case Token::BRACKET_OPEN:
83 case Token::BRACKET_CLOSE:
84 case Token::PARENTHESIS_OPEN:
85 case Token::PARENTHESIS_CLOSE:
88 return Token ((Token::Type) c);
90 std::istream::char_type c2;
93 return Token(Token::SCRIPT_BEGIN);
96 return Token(Token::CHEVRON_OPEN);
100 std::istream::char_type c2;
103 return Token(Token::SCRIPT_END);
106 return Token(Token::CHEVRON_CLOSE);
110 case '0': case '1': case '2': case '3': case '4':
111 case '5': case '6': case '7': case '8': case '9':
119 std::istream::char_type c2;
122 return ReadComment();
123 } else if (c2 == '*') {
124 return ReadMultilineComment();
126 throw LexerError(line, std::string("Tokenizer: cannot parse token: ") + c + c2 + ": expected / or *");
133 Token t(ReadIdentifier());
134 if (std::isupper(c)) {
135 t.type = Token::TYPE_NAME;
136 } else if (std::islower(c)) {
139 throw LexerError(line, std::string("Tokenizer: cannot parse token: ") + c);
146 Tokenizer::Token Tokenizer::ReadNumber() {
147 Token t(Token::NUMBER);
148 bool isNegative(false);
150 std::istream::char_type c;
154 } else if (c != '+') {
159 if (!std::isdigit(c)) {
167 if (isNegative) t.number *= -1;
172 Tokenizer::Token Tokenizer::ReadString() {
173 Token t(Token::STRING);
176 std::istream::char_type c;
179 throw LexerError(line, "Tokenizer: strings must begin with '\"'");
187 t.str.push_back('\n');
190 t.str.push_back('\r');
193 t.str.push_back('\t');
199 } else if (c == '"') {
201 } else if (c == '\\') {
211 Tokenizer::Token Tokenizer::ReadIdentifier() {
212 Token t(Token::IDENTIFIER);
214 std::istream::char_type c;
216 if (std::isalnum(c) || c == '_') {
227 Tokenizer::Token Tokenizer::ReadComment() {
228 std::istream::char_type c;
229 while (in.get(c) && c != '\n');
231 return Token(Token::COMMENT);
234 Tokenizer::Token Tokenizer::ReadMultilineComment() {
235 std::istream::char_type c;
238 std::istream::char_type c2;
239 if (in.get(c2) && c2 == '/') {
242 } else if (c == '\n') {
246 return Token(Token::COMMENT);
249 bool Tokenizer::CheckKeyword(Token &t) {
250 if (t.str == "export") {
251 t.type = Token::KEYWORD_EXPORT;
253 } else if (t.str == "false") {
254 t.type = Token::KEYWORD_FALSE;
256 } else if (t.str == "include") {
257 t.type = Token::KEYWORD_INCLUDE;
259 } else if (t.str == "true") {
260 t.type = Token::KEYWORD_TRUE;