iv-phonic 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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_