6#define UNDO(CHR) { in.putback(c_); c_ = CHR; pos_.column--; }
15#define M_KEYWORD(tok, text) keywords_.emplace(pool(#text), TK_##tok);
16#include <mutable/tables/Keywords.tbl>
26 case ' ':
case '\t':
case '\v':
case '\f':
case '\n':
case '\r':
step();
continue;
50 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
68#define LEX(chr, text, tt, SUB) case chr: step(); switch (c_) { SUB } return Token(start_, pool(text), tt);
69#define GUESS(first, SUB) case first: step(); switch (c_) { SUB } UNDO(first); break;
70 LEX(
'(',
"(", TK_LPAR, );
71 LEX(
')',
")", TK_RPAR, );
72 LEX(
'~',
"~", TK_TILDE, );
73 LEX(
'+',
"+", TK_PLUS, );
74 LEX(
'-',
"-", TK_MINUS, );
75 LEX(
'*',
"*", TK_ASTERISK, );
76 LEX(
'/',
"/", TK_SLASH, );
77 LEX(
'%',
"%", TK_PERCENT, );
78 LEX(
'=',
"=", TK_EQUAL, );
80 LEX(
'=',
"!=", TK_BANG_EQUAL, ) );
81 LEX(
'<',
"<", TK_LESS,
82 LEX(
'=',
"<=", TK_LESS_EQUAL, ) );
83 LEX(
'>',
">", TK_GREATER,
84 LEX(
'=',
">=", TK_GREATER_EQUAL, ) );
85 LEX(
',',
",", TK_COMMA, );
86 LEX(
';',
";", TK_SEMICOL, );
88 LEX(
'.',
"..", TK_DOTDOT, )
89 case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
105 diag.
e(
start_) <<
"illegal character '" << str <<
"'\n";
123 else return Token(
start_, std::move(str), it->second);
128 bool is_float =
false;
130 enum { Oct, Dec, Hex } is, has;
134 if (
'0' ==
c_) { is = Oct; empty =
false;
push(); }
135 if (
'x' ==
c_ ||
'X' ==
c_) { is = Hex; empty =
true;
push(); }
141 else if (is == Oct &&
is_dec(
c_)) has = Dec;
153 if (is == Oct) is = Dec;
154 if (has == Oct) has = Dec;
162 if ((is == Oct && (
'e' ==
c_ ||
'E' ==
c_)) ||
163 (is == Dec && (
'e' ==
c_ ||
'E' ==
c_)) ||
164 (is == Hex && (
'p' ==
c_ ||
'P' ==
c_))) {
167 if (is == Oct) is = Dec;
168 if (has == Oct) has = Dec;
174 if (empty or is != has) {
176 diag.
e(
start_) <<
"invalid number '" << str <<
"'\n";
181 case Oct: tt = TK_OCT_INT;
break;
182 case Dec: tt = is_float ? TK_DEC_FLOAT : TK_DEC_INT;
break;
183 case Hex: tt = is_float ? TK_HEX_FLOAT : TK_HEX_INT;
break;
191 bool invalid =
false;
192 while (EOF !=
c_ and '"' !=
c_) {
214 diag.
e(
start_) <<
"unterminated string literal '" << str <<
"'\n";
222 diag.
e(
start_) <<
"invalid escape sequence in string literal '" << str <<
"'\n";
226 return Token(
start_, std::move(str), TK_STRING_LITERAL);
232 bool invalid =
false;
233 bool datetime =
false;
235#define DIGITS(num) for (auto i = 0; i < num; ++i) if (is_dec(c_)) push(); else invalid = true;
255 diag.
e(
start_) <<
"unterminated " << (datetime ?
"datetime" :
"date") <<
" '" << str <<
"'\n";
263 diag.
e(
start_) <<
"invalid symbol in " << (datetime ?
"datetime" :
"date") <<
" '" << str <<
"'\n";
267 return Token(
start_, std::move(str), datetime ? TK_DATE_TIME : TK_DATE);
273 while (
';' !=
c_ and EOF !=
c_)
#define GUESS(first, SUB)
#define LEX(chr, text, tt, SUB)
std::ostream & e(const Position pos)
Token read_string_literal()
Token next()
Obtains the next token from the input stream.
Token read_keyword_or_identifier()
void initialize_keywords()
Initializes the set of all keywords.
ThreadSafePooledString internalize()
int step()
Reads the next character from in to c_, and updates pos_ accordingly.
ThreadSafeStringPool & pool
Token read_date_or_datetime()