iv-phonic 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Manifest.txt +2 -3
- data/Rakefile +1 -1
- data/ext/include/iv/alloc.h +11 -4
- data/ext/include/iv/ast-factory.h +15 -6
- data/ext/include/iv/ast-fwd.h +2 -0
- data/ext/include/iv/ast-info.h +21 -0
- data/ext/include/iv/ast-serializer.h +6 -0
- data/ext/include/iv/ast-visitor.h +1 -0
- data/ext/include/iv/ast.h +522 -105
- data/ext/include/iv/conversions.h +79 -11
- data/ext/include/iv/keyword.h +460 -0
- data/ext/include/iv/lexer.h +77 -464
- data/ext/include/iv/location.h +6 -0
- data/ext/include/iv/parser.h +100 -43
- data/ext/include/iv/token.h +2 -0
- data/ext/iv/phonic/ast-fwd.h +17 -1
- data/ext/iv/phonic/creator.h +8 -0
- data/ext/iv/phonic/factory.h +10 -1
- data/ext/iv/phonic/parser.h +2 -1
- data/ext/iv/phonic/rparser.h +3 -4
- data/ext/iv/phonic/source.h +4 -5
- metadata +5 -6
- data/ext/include/iv/source.h +0 -27
- data/ext/iv/phonic/ast.h +0 -10
- data/ext/iv/phonic/rnode.h +0 -15
@@ -21,6 +21,8 @@ class Conversions {
|
|
21
21
|
static const std::string kInfinity;
|
22
22
|
static const double DoubleToInt32_Two32;
|
23
23
|
static const double DoubleToInt32_Two31;
|
24
|
+
static const char* kHex;
|
25
|
+
static const int kMaxDoubleToStringWithRadixBufferSize = 2200;
|
24
26
|
};
|
25
27
|
template<typename T>
|
26
28
|
const double Conversions<T>::kNaN = std::numeric_limits<double>::quiet_NaN();
|
@@ -33,14 +35,19 @@ const double Conversions<T>::DoubleToInt32_Two32 = 4294967296.0;
|
|
33
35
|
|
34
36
|
template<typename T>
|
35
37
|
const double Conversions<T>::DoubleToInt32_Two31 = 2147483648.0;
|
38
|
+
|
39
|
+
template<typename T>
|
40
|
+
const char* Conversions<T>::kHex = "0123456789abcdefghijklmnopqrstuvwxyz";
|
41
|
+
|
36
42
|
} // namespace iv::core::detail
|
37
43
|
|
38
44
|
typedef detail::Conversions<None> Conversions;
|
39
45
|
|
40
46
|
template<typename Iter>
|
41
|
-
inline double StringToDouble(Iter it, Iter last) {
|
47
|
+
inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
42
48
|
bool is_decimal = true;
|
43
49
|
bool is_signed = false;
|
50
|
+
bool is_sign_found = false;
|
44
51
|
std::size_t pos = 0;
|
45
52
|
int significant_digits = 0;
|
46
53
|
int insignificant_digits = 0;
|
@@ -48,7 +55,7 @@ inline double StringToDouble(Iter it, Iter last) {
|
|
48
55
|
|
49
56
|
// empty string ""
|
50
57
|
if (it == last) {
|
51
|
-
return 0;
|
58
|
+
return (parse_float) ? Conversions::kNaN : 0;
|
52
59
|
}
|
53
60
|
|
54
61
|
while (it != last &&
|
@@ -58,15 +65,17 @@ inline double StringToDouble(Iter it, Iter last) {
|
|
58
65
|
|
59
66
|
// white space only " "
|
60
67
|
if (it == last) {
|
61
|
-
return 0;
|
68
|
+
return (parse_float) ? Conversions::kNaN : 0;
|
62
69
|
}
|
63
70
|
|
64
71
|
if (*it == '-') {
|
65
72
|
buffer[pos++] = '-';
|
66
73
|
++it;
|
67
74
|
is_signed = true;
|
75
|
+
is_sign_found = true;
|
68
76
|
} else if (*it == '+') {
|
69
77
|
++it;
|
78
|
+
is_sign_found = true;
|
70
79
|
}
|
71
80
|
|
72
81
|
if (it == last) {
|
@@ -79,7 +88,10 @@ inline double StringToDouble(Iter it, Iter last) {
|
|
79
88
|
if (it == last) {
|
80
89
|
return 0;
|
81
90
|
}
|
82
|
-
if (*it == 'x' || *it == 'X') {
|
91
|
+
if (!parse_float && (*it == 'x' || *it == 'X')) {
|
92
|
+
if (is_sign_found) {
|
93
|
+
return Conversions::kNaN;
|
94
|
+
}
|
83
95
|
is_decimal = false;
|
84
96
|
buffer[pos++] = '0';
|
85
97
|
buffer[pos++] = *it;
|
@@ -158,7 +170,7 @@ inline double StringToDouble(Iter it, Iter last) {
|
|
158
170
|
(Chars::IsWhiteSpace(*it) || Chars::IsLineTerminator(*it))) {
|
159
171
|
++it;
|
160
172
|
}
|
161
|
-
if (it == last) {
|
173
|
+
if (it == last || parse_float) {
|
162
174
|
if (is_signed) {
|
163
175
|
return -std::numeric_limits<double>::infinity();
|
164
176
|
} else {
|
@@ -213,10 +225,10 @@ inline double StringToDouble(Iter it, Iter last) {
|
|
213
225
|
++it;
|
214
226
|
}
|
215
227
|
|
216
|
-
if (it == last) {
|
228
|
+
if (it == last || parse_float) {
|
217
229
|
if (pos == 0) {
|
218
230
|
// empty
|
219
|
-
return 0;
|
231
|
+
return (parse_float) ? Conversions::kNaN : 0;
|
220
232
|
} else {
|
221
233
|
buffer[pos++] = '\0';
|
222
234
|
return std::strtod(buffer.data(), NULL);
|
@@ -226,12 +238,12 @@ inline double StringToDouble(Iter it, Iter last) {
|
|
226
238
|
}
|
227
239
|
}
|
228
240
|
|
229
|
-
inline double StringToDouble(const StringPiece& str) {
|
230
|
-
return StringToDouble(str.begin(), str.end());
|
241
|
+
inline double StringToDouble(const StringPiece& str, bool parse_float) {
|
242
|
+
return StringToDouble(str.begin(), str.end(), parse_float);
|
231
243
|
}
|
232
244
|
|
233
|
-
inline double StringToDouble(const UStringPiece& str) {
|
234
|
-
return StringToDouble(str.begin(), str.end());
|
245
|
+
inline double StringToDouble(const UStringPiece& str, bool parse_float) {
|
246
|
+
return StringToDouble(str.begin(), str.end(), parse_float);
|
235
247
|
}
|
236
248
|
|
237
249
|
inline std::size_t StringToHash(const UStringPiece& x) {
|
@@ -276,6 +288,16 @@ inline int32_t DoubleToUInt32(double d) {
|
|
276
288
|
return static_cast<uint32_t>(d);
|
277
289
|
}
|
278
290
|
|
291
|
+
inline double DoubleToInteger(double d) {
|
292
|
+
if (std::isnan(d)) {
|
293
|
+
return 0;
|
294
|
+
}
|
295
|
+
if (!std::isfinite(d) || d == 0) {
|
296
|
+
return d;
|
297
|
+
}
|
298
|
+
return std::floor(std::abs(d)) * (std::signbit(d) ? -1 : 1);
|
299
|
+
}
|
300
|
+
|
279
301
|
inline bool ConvertToUInt32(const UStringPiece& str, uint32_t* value) {
|
280
302
|
uint16_t ch;
|
281
303
|
*value = 0;
|
@@ -303,6 +325,52 @@ inline bool ConvertToUInt32(const UStringPiece& str, uint32_t* value) {
|
|
303
325
|
(ch < (std::numeric_limits<uint32_t>::max() % 10))));
|
304
326
|
}
|
305
327
|
|
328
|
+
template<typename T>
|
329
|
+
inline std::size_t DoubleToStringWithRadix(double v, int radix, T* buf) {
|
330
|
+
static const int kMaxBufSize = 1100;
|
331
|
+
std::tr1::array<
|
332
|
+
char,
|
333
|
+
Conversions::kMaxDoubleToStringWithRadixBufferSize> buffer;
|
334
|
+
const bool is_negative = v < 0.0;
|
335
|
+
if (is_negative) {
|
336
|
+
v = -v;
|
337
|
+
}
|
338
|
+
double integer = std::floor(v);
|
339
|
+
double decimal = v - integer;
|
340
|
+
|
341
|
+
// integer part
|
342
|
+
int integer_pos = kMaxBufSize - 1;
|
343
|
+
do {
|
344
|
+
buffer[integer_pos--] =
|
345
|
+
Conversions::kHex[static_cast<std::size_t>(std::fmod(integer, radix))];
|
346
|
+
integer /= radix;
|
347
|
+
} while (integer >= 1.0);
|
348
|
+
if (is_negative) {
|
349
|
+
buffer[integer_pos--] = '-';
|
350
|
+
}
|
351
|
+
assert(integer_pos >= 0);
|
352
|
+
|
353
|
+
// decimal part
|
354
|
+
int decimal_pos = kMaxBufSize;
|
355
|
+
if (decimal) {
|
356
|
+
buffer[decimal_pos++] = '.';
|
357
|
+
while ((decimal > 0.0) && (decimal_pos < (kMaxBufSize * 2))) {
|
358
|
+
decimal *= radix;
|
359
|
+
const std::size_t res = static_cast<std::size_t>(std::floor(decimal));
|
360
|
+
buffer[decimal_pos++] = Conversions::kHex[res];
|
361
|
+
decimal -= res;
|
362
|
+
}
|
363
|
+
}
|
364
|
+
buf->assign(buffer.data() + integer_pos + 1,
|
365
|
+
buffer.data() + decimal_pos);
|
366
|
+
return decimal_pos - integer_pos - 1; // size
|
367
|
+
}
|
368
|
+
|
369
|
+
inline std::string DoubleToStringWithRadix(double v, int radix) {
|
370
|
+
std::string str;
|
371
|
+
DoubleToStringWithRadix(v, radix, &str);
|
372
|
+
return str;
|
373
|
+
}
|
306
374
|
|
307
375
|
} } // namespace iv::core
|
308
376
|
#endif // IV_CONVERSIONS_H_
|
@@ -0,0 +1,460 @@
|
|
1
|
+
#ifndef _IV_KEYWORD_H_
|
2
|
+
#define _IV_KEYWORD_H_
|
3
|
+
#include <cstddef>
|
4
|
+
#include "token.h"
|
5
|
+
namespace iv {
|
6
|
+
namespace core {
|
7
|
+
|
8
|
+
// tags
|
9
|
+
class IdentifyReservedWords { };
|
10
|
+
class IgnoreReservedWords { };
|
11
|
+
class IgnoreReservedWordsAndIdentifyGetterOrSetter { };
|
12
|
+
|
13
|
+
namespace detail {
|
14
|
+
template<typename LexType>
|
15
|
+
class Keyword { };
|
16
|
+
|
17
|
+
// detect which Identifier is Keyword, FutureReservedWord or not
|
18
|
+
// Keyword and FutureReservedWord are defined in ECMA-262 5th.
|
19
|
+
//
|
20
|
+
// Some words such as :
|
21
|
+
// int, short, boolean, byte, long, char, float, double, abstract, volatile,
|
22
|
+
// transient, final, throws, goto, native, synchronized
|
23
|
+
// were defined as FutureReservedWord in ECMA-262 3rd, but not in 5th.
|
24
|
+
// So, Detect interprets them as Identifier.
|
25
|
+
template<>
|
26
|
+
class Keyword<IdentifyReservedWords> {
|
27
|
+
public:
|
28
|
+
template<typename Buffer>
|
29
|
+
static Token::Type Detect(const Buffer& buf, bool strict) {
|
30
|
+
const std::size_t len = buf.size();
|
31
|
+
Token::Type token = Token::IDENTIFIER;
|
32
|
+
switch (len) {
|
33
|
+
case 2:
|
34
|
+
// if in do
|
35
|
+
if (buf[0] == 'i') {
|
36
|
+
if (buf[1] == 'f') {
|
37
|
+
token = Token::IF;
|
38
|
+
} else if (buf[1] == 'n') {
|
39
|
+
token = Token::IN;
|
40
|
+
}
|
41
|
+
} else if (buf[0] == 'd' && buf[1] == 'o') {
|
42
|
+
// do
|
43
|
+
token = Token::DO;
|
44
|
+
}
|
45
|
+
break;
|
46
|
+
case 3:
|
47
|
+
// for var int new try let
|
48
|
+
switch (buf[2]) {
|
49
|
+
case 't':
|
50
|
+
if (buf[0] == 'l' && buf[1] == 'e' && strict) {
|
51
|
+
// let
|
52
|
+
token = Token::LET;
|
53
|
+
} else if (buf[0] == 'i' && buf[1] == 'n') {
|
54
|
+
// int (removed)
|
55
|
+
// token = Token::INT;
|
56
|
+
}
|
57
|
+
break;
|
58
|
+
case 'r':
|
59
|
+
// for var
|
60
|
+
if (buf[0] == 'f' && buf[1] == 'o') {
|
61
|
+
// for
|
62
|
+
token = Token::FOR;
|
63
|
+
} else if (buf[0] == 'v' && buf[1] == 'a') {
|
64
|
+
// var
|
65
|
+
token = Token::VAR;
|
66
|
+
}
|
67
|
+
break;
|
68
|
+
case 'y':
|
69
|
+
// try
|
70
|
+
if (buf[0] == 't' && buf[1] == 'r') {
|
71
|
+
token = Token::TRY;
|
72
|
+
}
|
73
|
+
break;
|
74
|
+
case 'w':
|
75
|
+
// new
|
76
|
+
if (buf[0] == 'n' && buf[1] == 'e') {
|
77
|
+
token = Token::NEW;
|
78
|
+
}
|
79
|
+
break;
|
80
|
+
}
|
81
|
+
break;
|
82
|
+
case 4:
|
83
|
+
// else case true byte null this
|
84
|
+
// void with long enum char goto
|
85
|
+
// number 3 character is most duplicated
|
86
|
+
switch (buf[3]) {
|
87
|
+
case 'e':
|
88
|
+
// else case true byte
|
89
|
+
if (buf[2] == 's') {
|
90
|
+
if (buf[0] == 'e' && buf[1] == 'l') {
|
91
|
+
// else
|
92
|
+
token = Token::ELSE;
|
93
|
+
} else if (buf[0] == 'c' && buf[1] == 'a') {
|
94
|
+
// case
|
95
|
+
token = Token::CASE;
|
96
|
+
}
|
97
|
+
} else if (buf[0] == 't' &&
|
98
|
+
buf[1] == 'r' && buf[2] == 'u') {
|
99
|
+
// true
|
100
|
+
token = Token::TRUE_LITERAL;
|
101
|
+
} else if (buf[0] == 'b' &&
|
102
|
+
buf[1] == 'y' && buf[2] == 't') {
|
103
|
+
// byte (removed)
|
104
|
+
// token = Token::BYTE;
|
105
|
+
}
|
106
|
+
break;
|
107
|
+
case 'l':
|
108
|
+
// null
|
109
|
+
if (buf[0] == 'n' &&
|
110
|
+
buf[1] == 'u' && buf[2] == 'l') {
|
111
|
+
token = Token::NULL_LITERAL;
|
112
|
+
}
|
113
|
+
break;
|
114
|
+
case 's':
|
115
|
+
// this
|
116
|
+
if (buf[0] == 't' &&
|
117
|
+
buf[1] == 'h' && buf[2] == 'i') {
|
118
|
+
token = Token::THIS;
|
119
|
+
}
|
120
|
+
break;
|
121
|
+
case 'd':
|
122
|
+
// void
|
123
|
+
if (buf[0] == 'v' &&
|
124
|
+
buf[1] == 'o' && buf[2] == 'i') {
|
125
|
+
token = Token::VOID;
|
126
|
+
}
|
127
|
+
break;
|
128
|
+
case 'h':
|
129
|
+
// with
|
130
|
+
if (buf[0] == 'w' &&
|
131
|
+
buf[1] == 'i' && buf[2] == 't') {
|
132
|
+
token = Token::WITH;
|
133
|
+
}
|
134
|
+
break;
|
135
|
+
case 'g':
|
136
|
+
// long (removed)
|
137
|
+
if (buf[0] == 'l' &&
|
138
|
+
buf[1] == 'o' && buf[2] == 'n') {
|
139
|
+
// token = Token::LONG;
|
140
|
+
}
|
141
|
+
break;
|
142
|
+
case 'm':
|
143
|
+
// enum
|
144
|
+
if (buf[0] == 'e' &&
|
145
|
+
buf[1] == 'n' && buf[2] == 'u') {
|
146
|
+
token = Token::ENUM;
|
147
|
+
}
|
148
|
+
break;
|
149
|
+
case 'r':
|
150
|
+
// char (removed)
|
151
|
+
if (buf[0] == 'c' &&
|
152
|
+
buf[1] == 'h' && buf[2] == 'a') {
|
153
|
+
// token = Token::CHAR;
|
154
|
+
}
|
155
|
+
break;
|
156
|
+
case 'o':
|
157
|
+
// goto (removed)
|
158
|
+
if (buf[0] == 'g' &&
|
159
|
+
buf[1] == 'o' && buf[2] == 't') {
|
160
|
+
// token = Token::GOTO;
|
161
|
+
}
|
162
|
+
break;
|
163
|
+
}
|
164
|
+
break;
|
165
|
+
case 5:
|
166
|
+
// break final float catch super while
|
167
|
+
// throw short class const false yield
|
168
|
+
// number 3 character is most duplicated
|
169
|
+
switch (buf[3]) {
|
170
|
+
case 'a':
|
171
|
+
// break final float
|
172
|
+
if (buf[0] == 'b' && buf[1] == 'r' &&
|
173
|
+
buf[2] == 'e' && buf[4] == 'k') {
|
174
|
+
// break
|
175
|
+
token = Token::BREAK;
|
176
|
+
} else if (buf[0] == 'f') {
|
177
|
+
if (buf[1] == 'i' &&
|
178
|
+
buf[2] == 'n' && buf[4] == 'l') {
|
179
|
+
// final (removed)
|
180
|
+
// token = Token::FINAL;
|
181
|
+
} else if (buf[1] == 'l' &&
|
182
|
+
buf[2] == 'o' && buf[4] == 't') {
|
183
|
+
// float (removed)
|
184
|
+
// token = Token::FLOAT;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
break;
|
188
|
+
case 'c':
|
189
|
+
if (buf[0] == 'c' && buf[1] == 'a' &&
|
190
|
+
buf[2] == 't' && buf[4] == 'h') {
|
191
|
+
// catch
|
192
|
+
token = Token::CATCH;
|
193
|
+
}
|
194
|
+
break;
|
195
|
+
case 'e':
|
196
|
+
if (buf[0] == 's' && buf[1] == 'u' &&
|
197
|
+
buf[2] == 'p' && buf[4] == 'r') {
|
198
|
+
// super
|
199
|
+
token = Token::SUPER;
|
200
|
+
}
|
201
|
+
break;
|
202
|
+
case 'l':
|
203
|
+
if (buf[0] == 'w' && buf[1] == 'h' &&
|
204
|
+
buf[2] == 'i' && buf[4] == 'e') {
|
205
|
+
// while
|
206
|
+
token = Token::WHILE;
|
207
|
+
} else if (strict &&
|
208
|
+
buf[0] == 'y' && buf[1] == 'i' &&
|
209
|
+
buf[2] == 'e' && buf[4] == 'd') {
|
210
|
+
// yield
|
211
|
+
token = Token::YIELD;
|
212
|
+
}
|
213
|
+
break;
|
214
|
+
case 'o':
|
215
|
+
if (buf[0] == 't' && buf[1] == 'h' &&
|
216
|
+
buf[2] == 'r' && buf[4] == 'w') {
|
217
|
+
// throw
|
218
|
+
token = Token::THROW;
|
219
|
+
}
|
220
|
+
break;
|
221
|
+
case 'r':
|
222
|
+
if (buf[0] == 's' && buf[1] == 'h' &&
|
223
|
+
buf[2] == 'o' && buf[4] == 't') {
|
224
|
+
// short (removed)
|
225
|
+
// token = Token::SHORT;
|
226
|
+
}
|
227
|
+
break;
|
228
|
+
case 's':
|
229
|
+
// class const false
|
230
|
+
if (buf[0] == 'c') {
|
231
|
+
if (buf[1] == 'l' &&
|
232
|
+
buf[2] == 'a' && buf[4] == 's') {
|
233
|
+
// class
|
234
|
+
token = Token::CLASS;
|
235
|
+
} else if (buf[1] == 'o' &&
|
236
|
+
buf[2] == 'n' && buf[4] == 't') {
|
237
|
+
// const
|
238
|
+
token = Token::CONST;
|
239
|
+
}
|
240
|
+
} else if (buf[0] == 'f' && buf[1] == 'a' &&
|
241
|
+
buf[2] == 'l' && buf[4] == 'e') {
|
242
|
+
// false
|
243
|
+
token = Token::FALSE_LITERAL;
|
244
|
+
}
|
245
|
+
break;
|
246
|
+
}
|
247
|
+
break;
|
248
|
+
case 6:
|
249
|
+
// double delete export import native
|
250
|
+
// public return static switch typeof throws
|
251
|
+
// number 0 character is most duplicated
|
252
|
+
switch (buf[0]) {
|
253
|
+
case 'd':
|
254
|
+
// double delete
|
255
|
+
if (buf[5] == 'e' &&
|
256
|
+
buf[4] == 'l' && buf[3] == 'b' &&
|
257
|
+
buf[2] == 'u' && buf[1] == 'o') {
|
258
|
+
// double
|
259
|
+
// token = Token::DOUBLE;
|
260
|
+
} else if (buf[5] == 'e' &&
|
261
|
+
buf[4] == 't' && buf[3] == 'e' &&
|
262
|
+
buf[2] == 'l' && buf[1] == 'e') {
|
263
|
+
// delete
|
264
|
+
token = Token::DELETE;
|
265
|
+
}
|
266
|
+
break;
|
267
|
+
case 'e':
|
268
|
+
// export
|
269
|
+
token = IsMatch("export", buf, Token::EXPORT);
|
270
|
+
break;
|
271
|
+
case 'i':
|
272
|
+
// import
|
273
|
+
token = IsMatch("import", buf, Token::IMPORT);
|
274
|
+
break;
|
275
|
+
case 'n':
|
276
|
+
// native (removed)
|
277
|
+
// token = IsMatch("native", buf, Token::NATIVE);
|
278
|
+
break;
|
279
|
+
case 'p':
|
280
|
+
// public
|
281
|
+
token = IsMatch("public", buf, Token::PUBLIC, strict);
|
282
|
+
break;
|
283
|
+
case 'r':
|
284
|
+
// return
|
285
|
+
token = IsMatch("return", buf, Token::RETURN);
|
286
|
+
break;
|
287
|
+
case 's':
|
288
|
+
// switch static
|
289
|
+
if (buf[1] == 'w' &&
|
290
|
+
buf[2] == 'i' && buf[3] == 't' &&
|
291
|
+
buf[4] == 'c' && buf[5] == 'h') {
|
292
|
+
// switch
|
293
|
+
token = Token::SWITCH;
|
294
|
+
} else if (strict &&
|
295
|
+
buf[1] == 't' &&
|
296
|
+
buf[2] == 'a' && buf[3] == 't' &&
|
297
|
+
buf[4] == 'i' && buf[5] == 'c') {
|
298
|
+
// static
|
299
|
+
token = Token::STATIC;
|
300
|
+
}
|
301
|
+
break;
|
302
|
+
case 't':
|
303
|
+
// typeof throws
|
304
|
+
if (buf[5] == 'f' &&
|
305
|
+
buf[4] == 'o' && buf[3] == 'e' &&
|
306
|
+
buf[2] == 'p' && buf[1] == 'y') {
|
307
|
+
// typeof
|
308
|
+
token = Token::TYPEOF;
|
309
|
+
} else if (buf[5] == 's' &&
|
310
|
+
buf[4] == 'w' && buf[3] == 'o' &&
|
311
|
+
buf[2] == 'r' && buf[1] == 'h') {
|
312
|
+
// throws (removed)
|
313
|
+
// token = Token::THROWS;
|
314
|
+
}
|
315
|
+
break;
|
316
|
+
}
|
317
|
+
break;
|
318
|
+
case 7:
|
319
|
+
// boolean default extends finally package private
|
320
|
+
// number 0 character is most duplicated
|
321
|
+
switch (buf[0]) {
|
322
|
+
case 'b':
|
323
|
+
// boolean (removed)
|
324
|
+
// token = IsMatch("boolean", buf, Token::BOOLEAN);
|
325
|
+
break;
|
326
|
+
case 'd':
|
327
|
+
token = IsMatch("default", buf, Token::DEFAULT);
|
328
|
+
break;
|
329
|
+
case 'e':
|
330
|
+
token = IsMatch("extends", buf, Token::EXTENDS);
|
331
|
+
break;
|
332
|
+
case 'f':
|
333
|
+
token = IsMatch("finally", buf, Token::FINALLY);
|
334
|
+
break;
|
335
|
+
case 'p':
|
336
|
+
if (buf[1] == 'a') {
|
337
|
+
token = IsMatch("package", buf, Token::PACKAGE, strict);
|
338
|
+
} else if (buf[1] == 'r') {
|
339
|
+
token = IsMatch("private", buf, Token::PRIVATE, strict);
|
340
|
+
}
|
341
|
+
break;
|
342
|
+
}
|
343
|
+
break;
|
344
|
+
case 8:
|
345
|
+
// debugger continue abstract volatile function
|
346
|
+
// number 4 character is most duplicated
|
347
|
+
switch (buf[4]) {
|
348
|
+
case 'g':
|
349
|
+
token = IsMatch("debugger", buf, Token::DEBUGGER);
|
350
|
+
break;
|
351
|
+
case 'i':
|
352
|
+
token = IsMatch("continue", buf, Token::CONTINUE);
|
353
|
+
break;
|
354
|
+
case 'r':
|
355
|
+
// abstract (removed)
|
356
|
+
// token = IsMatch("abstract", buf, Token::ABSTRACT);
|
357
|
+
break;
|
358
|
+
case 't':
|
359
|
+
if (buf[1] == 'o') {
|
360
|
+
// token = IsMatch("volatile", buf, Token::VOLATILE);
|
361
|
+
} else if (buf[1] == 'u') {
|
362
|
+
token = IsMatch("function", buf, Token::FUNCTION);
|
363
|
+
}
|
364
|
+
break;
|
365
|
+
}
|
366
|
+
break;
|
367
|
+
case 9:
|
368
|
+
// interface protected transient
|
369
|
+
if (buf[1] == 'n') {
|
370
|
+
token = IsMatch("interface", buf, Token::INTERFACE, strict);
|
371
|
+
} else if (buf[1] == 'r') {
|
372
|
+
if (buf[0] == 'p') {
|
373
|
+
token = IsMatch("protected", buf, Token::PROTECTED, strict);
|
374
|
+
} else if (buf[0] == 't') {
|
375
|
+
// transient (removed)
|
376
|
+
// token = IsMatch("transient", buf, Token::TRANSIENT);
|
377
|
+
}
|
378
|
+
}
|
379
|
+
break;
|
380
|
+
case 10:
|
381
|
+
// instanceof implements
|
382
|
+
if (buf[1] == 'n') {
|
383
|
+
token = IsMatch("instanceof", buf, Token::INSTANCEOF);
|
384
|
+
} else if (buf[1] == 'm') {
|
385
|
+
token = IsMatch("implements", buf, Token::IMPLEMENTS, strict);
|
386
|
+
}
|
387
|
+
break;
|
388
|
+
case 12:
|
389
|
+
// synchronized (removed)
|
390
|
+
// token = IsMatch("synchronized", buf, Token::SYNCHRONIZED);
|
391
|
+
token = Token::IDENTIFIER;
|
392
|
+
break;
|
393
|
+
}
|
394
|
+
return token;
|
395
|
+
}
|
396
|
+
|
397
|
+
template<typename Buffer>
|
398
|
+
static inline Token::Type IsMatch(char const * keyword,
|
399
|
+
const Buffer& buf,
|
400
|
+
Token::Type guess,
|
401
|
+
bool strict) {
|
402
|
+
if (!strict) {
|
403
|
+
return Token::IDENTIFIER;
|
404
|
+
}
|
405
|
+
typename Buffer::const_iterator it = buf.begin();
|
406
|
+
const typename Buffer::const_iterator last = buf.end();
|
407
|
+
do {
|
408
|
+
if (*it++ != *keyword++) {
|
409
|
+
return Token::IDENTIFIER;
|
410
|
+
}
|
411
|
+
} while (it != last);
|
412
|
+
return guess;
|
413
|
+
}
|
414
|
+
|
415
|
+
template<typename Buffer>
|
416
|
+
static inline Token::Type IsMatch(char const * keyword,
|
417
|
+
const Buffer& buf,
|
418
|
+
Token::Type guess) {
|
419
|
+
typename Buffer::const_iterator it = buf.begin();
|
420
|
+
const typename Buffer::const_iterator last = buf.end();
|
421
|
+
do {
|
422
|
+
if (*it++ != *keyword++) {
|
423
|
+
return Token::IDENTIFIER;
|
424
|
+
}
|
425
|
+
} while (it != last);
|
426
|
+
return guess;
|
427
|
+
}
|
428
|
+
};
|
429
|
+
|
430
|
+
template<>
|
431
|
+
class Keyword<IgnoreReservedWords> {
|
432
|
+
public:
|
433
|
+
template<typename Buffer>
|
434
|
+
static inline Token::Type Detect(const Buffer& buf, bool strict) {
|
435
|
+
return Token::IDENTIFIER;
|
436
|
+
}
|
437
|
+
};
|
438
|
+
|
439
|
+
template<>
|
440
|
+
class Keyword<IgnoreReservedWordsAndIdentifyGetterOrSetter> {
|
441
|
+
public:
|
442
|
+
template<typename Buffer>
|
443
|
+
static inline Token::Type Detect(const Buffer& buf, bool strict) {
|
444
|
+
if (buf.size() == 3) {
|
445
|
+
if (buf[1] == 'e' && buf[2] == 't') {
|
446
|
+
if (buf[0] == 'g') {
|
447
|
+
return Token::GET;
|
448
|
+
} else if (buf[0] == 's') {
|
449
|
+
return Token::SET;
|
450
|
+
}
|
451
|
+
}
|
452
|
+
}
|
453
|
+
return Token::IDENTIFIER;
|
454
|
+
}
|
455
|
+
};
|
456
|
+
|
457
|
+
|
458
|
+
|
459
|
+
} } } // namespace iv::core::detail
|
460
|
+
#endif // _IV_KEYWORD_H_
|