7 bool Tokenizer::HasMore() {
8 if (isPutback) return true;
10 if (!in) return false;
12 putback = ReadToken();
14 if (!skipComments || putback.type != Token::COMMENT) return true;
16 while (in && putback.type == Token::COMMENT) {
17 putback = ReadToken();
20 return putback.type != Token::COMMENT;
23 void Tokenizer::ScanSpace() {
24 std::istream::char_type c;
26 while (in && std::isspace(c)) {
37 void Tokenizer::Putback(const Token &t) {
39 throw LexerError(line, "Tokenizer: double putback not supported");
46 const Tokenizer::Token &Tokenizer::Peek() {
54 Tokenizer::Token Tokenizer::GetNext() {
56 throw LexerError(line, "read beyond last token");
66 Tokenizer::Token Tokenizer::ReadToken() {
68 std::istream::char_type c;
71 case Token::ANGLE_BRACKET_OPEN:
72 case Token::ANGLE_BRACKET_CLOSE:
75 case Token::BRACKET_OPEN:
76 case Token::BRACKET_CLOSE:
77 case Token::PARENTHESIS_OPEN:
78 case Token::PARENTHESIS_CLOSE:
81 return Token ((Token::Type) c);
83 std::istream::char_type c2;
86 return Token(Token::SCRIPT_BEGIN);
89 return Token(Token::CHEVRON_OPEN);
93 std::istream::char_type c2;
96 return Token(Token::SCRIPT_END);
99 return Token(Token::CHEVRON_CLOSE);
103 case '0': case '1': case '2': case '3': case '4':
104 case '5': case '6': case '7': case '8': case '9':
112 std::istream::char_type c2;
115 return ReadComment();
116 } else if (c2 == '*') {
117 return ReadMultilineComment();
119 throw LexerError(line, std::string("Tokenizer: cannot parse token: ") + c + c2 + ": expected / or *");
126 Token t(ReadIdentifier());
127 if (std::isupper(c)) {
128 t.type = Token::TYPE_NAME;
129 } else if (std::islower(c)) {
132 throw LexerError(line, std::string("Tokenizer: cannot parse token: ") + c);
139 Tokenizer::Token Tokenizer::ReadNumber() {
140 Token t(Token::NUMBER);
141 bool isNegative(false);
143 std::istream::char_type c;
147 } else if (c != '+') {
152 if (!std::isdigit(c)) {
160 if (isNegative) t.number *= -1;
165 Tokenizer::Token Tokenizer::ReadString() {
166 Token t(Token::STRING);
169 std::istream::char_type c;
172 throw LexerError(line, "Tokenizer: strings must begin with '\"'");
180 t.str.push_back('\n');
183 t.str.push_back('\r');
186 t.str.push_back('\t');
192 } else if (c == '"') {
194 } else if (c == '\\') {
204 Tokenizer::Token Tokenizer::ReadIdentifier() {
205 Token t(Token::IDENTIFIER);
207 std::istream::char_type c;
209 if (std::isalnum(c) || c == '_') {
220 Tokenizer::Token Tokenizer::ReadComment() {
221 std::istream::char_type c;
222 while (in.get(c) && c != '\n');
224 return Token(Token::COMMENT);
227 Tokenizer::Token Tokenizer::ReadMultilineComment() {
228 std::istream::char_type c;
231 std::istream::char_type c2;
232 if (in.get(c2) && c2 == '/') {
235 } else if (c == '\n') {
239 return Token(Token::COMMENT);
242 bool Tokenizer::CheckKeyword(Token &t) {
243 if (t.str == "export") {
244 t.type = Token::KEYWORD_EXPORT;
246 } else if (t.str == "false") {
247 t.type = Token::KEYWORD_FALSE;
249 } else if (t.str == "include") {
250 t.type = Token::KEYWORD_INCLUDE;
252 } else if (t.str == "true") {
253 t.type = Token::KEYWORD_TRUE;