iv-phonic 0.0.7 → 0.0.8
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 +1 -1
- data/Rakefile +1 -1
- data/ext/include/iv/ast.h +8 -3
- data/ext/include/iv/character.h +878 -0
- data/ext/include/iv/chars.h +15 -39
- data/ext/include/iv/conversions.h +41 -18
- data/ext/include/iv/dtoa.h +4 -4
- data/ext/include/iv/lexer.h +16 -4
- data/ext/include/iv/location.h +2 -0
- data/ext/include/iv/parser.h +98 -50
- data/ext/include/iv/stringpiece.h +3 -3
- data/ext/include/iv/ustringpiece.h +3 -3
- data/ext/iv/phonic/parser.h +1 -1
- metadata +4 -4
- data/ext/include/iv/algorithm.h +0 -23
data/ext/include/iv/chars.h
CHANGED
@@ -3,78 +3,54 @@
|
|
3
3
|
#include <cassert>
|
4
4
|
#include <tr1/cstdint>
|
5
5
|
#include "uchar.h"
|
6
|
-
#include "
|
6
|
+
#include "character.h"
|
7
7
|
|
8
8
|
namespace iv {
|
9
9
|
namespace core {
|
10
10
|
|
11
11
|
class Chars {
|
12
12
|
public:
|
13
|
-
enum CharCategory {
|
14
|
-
UPPERCASE_LETTER = 1 << UC16::kUpperCaseLetter,
|
15
|
-
LOWERCASE_LETTER = 1 << UC16::kLowerCaseLetter,
|
16
|
-
TITLECASE_LETTER = 1 << UC16::kTitleCaseLetter,
|
17
|
-
MODIFIER_LETTER = 1 << UC16::kModifierLetter,
|
18
|
-
OTHER_LETTER = 1 << UC16::kOtherLetter,
|
19
|
-
NON_SPACING_MARK = 1 << UC16::kNonSpacingMark,
|
20
|
-
COMBINING_SPACING_MARK = 1 << UC16::kCombiningSpacingMark,
|
21
|
-
DECIMAL_DIGIT_NUMBER = 1 << UC16::kDecimalDigitNumber,
|
22
|
-
SPACE_SEPARATOR = 1 << UC16::kSpaceSeparator,
|
23
|
-
CONNECTOR_PUNCTUATION = 1 << UC16::kConnectorPunctuation
|
24
|
-
};
|
25
13
|
static inline uint32_t Category(const int c) {
|
26
|
-
|
27
|
-
return (c < 0) ? 1 : (1 << UnicodeData::kCategory[c]);
|
14
|
+
return (c < 0) ? 0 : character::GetCategory(c);
|
28
15
|
}
|
29
16
|
static inline bool IsASCII(const int c) {
|
30
|
-
return
|
17
|
+
return (c >= 0) && character::IsASCII(c);
|
31
18
|
}
|
32
19
|
static inline bool IsASCIIAlpha(const int c) {
|
33
|
-
return (c
|
20
|
+
return (c >= 0) && character::IsASCIIAlpha(c);
|
34
21
|
}
|
35
22
|
static inline bool IsASCIIAlphanumeric(const int c) {
|
36
|
-
return (c >=
|
23
|
+
return (c >= 0) && character::IsASCIIAlphanumeric(c);
|
37
24
|
}
|
38
25
|
static inline bool IsNonASCIIIdentifierStart(const int c) {
|
39
|
-
return
|
40
|
-
TITLECASE_LETTER | MODIFIER_LETTER | OTHER_LETTER);
|
26
|
+
return (c >= 0) && character::IsNonASCIIIdentifierStart(c);
|
41
27
|
}
|
42
28
|
static inline bool IsNonASCIIIdentifierPart(const int c) {
|
43
|
-
return
|
44
|
-
TITLECASE_LETTER | MODIFIER_LETTER |
|
45
|
-
OTHER_LETTER | NON_SPACING_MARK |
|
46
|
-
COMBINING_SPACING_MARK |
|
47
|
-
DECIMAL_DIGIT_NUMBER |
|
48
|
-
CONNECTOR_PUNCTUATION);
|
29
|
+
return (c >= 0) && character::IsNonASCIIIdentifierPart(c);
|
49
30
|
}
|
50
31
|
static inline bool IsSeparatorSpace(const int c) {
|
51
|
-
return
|
32
|
+
return (c >= 0) && character::IsSeparatorSpace(c);
|
52
33
|
}
|
53
34
|
static inline bool IsWhiteSpace(const int c) {
|
54
|
-
return
|
55
|
-
(c == ' ' || c == '\t' || c == 0xB || c == 0xC) : IsSeparatorSpace(c);
|
35
|
+
return (c >= 0) && character::IsWhiteSpace(c);
|
56
36
|
}
|
57
37
|
static inline bool IsLineTerminator(const int c) {
|
58
|
-
return c
|
38
|
+
return (c >= 0) && character::IsLineTerminator(c);
|
59
39
|
}
|
60
40
|
static inline bool IsHexDigit(const int c) {
|
61
|
-
return (c >=
|
41
|
+
return (c >= 0) && character::IsHexDigit(c);
|
62
42
|
}
|
63
43
|
static inline bool IsDecimalDigit(const int c) {
|
64
|
-
return c >=
|
44
|
+
return (c >= 0) && character::IsDecimalDigit(c);
|
65
45
|
}
|
66
46
|
static inline bool IsOctalDigit(const int c) {
|
67
|
-
return c >=
|
47
|
+
return (c >= 0) && character::IsOctalDigit(c);
|
68
48
|
}
|
69
49
|
static inline bool IsIdentifierStart(const int c) {
|
70
|
-
return
|
71
|
-
c == '\\' || IsASCIIAlpha(c) :
|
72
|
-
IsNonASCIIIdentifierStart(c);
|
50
|
+
return (c >= 0) && character::IsIdentifierStart(c);
|
73
51
|
}
|
74
52
|
static inline bool IsIdentifierPart(const int c) {
|
75
|
-
return
|
76
|
-
c == '\\' || IsASCIIAlphanumeric(c) :
|
77
|
-
IsNonASCIIIdentifierPart(c);
|
53
|
+
return (c >= 0) && character::IsIdentifierPart(c);
|
78
54
|
}
|
79
55
|
};
|
80
56
|
|
@@ -1,12 +1,13 @@
|
|
1
|
-
#ifndef
|
2
|
-
#define
|
1
|
+
#ifndef _IV_CONVERSIONS_H_
|
2
|
+
#define _IV_CONVERSIONS_H_
|
3
3
|
#include <cstdio>
|
4
4
|
#include <cmath>
|
5
5
|
#include <string>
|
6
6
|
#include <limits>
|
7
7
|
#include <tr1/array>
|
8
8
|
#include <tr1/cstdint>
|
9
|
-
#include
|
9
|
+
#include <tr1/cmath>
|
10
|
+
#include "character.h"
|
10
11
|
#include "dtoa.h"
|
11
12
|
#include "ustringpiece.h"
|
12
13
|
#include "none.h"
|
@@ -60,7 +61,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
60
61
|
}
|
61
62
|
|
62
63
|
while (it != last &&
|
63
|
-
(
|
64
|
+
(character::IsWhiteSpace(*it) || character::IsLineTerminator(*it))) {
|
64
65
|
++it;
|
65
66
|
}
|
66
67
|
|
@@ -83,7 +84,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
83
84
|
return Conversions::kNaN;
|
84
85
|
}
|
85
86
|
|
86
|
-
if (
|
87
|
+
if (character::IsDecimalDigit(*it)) {
|
87
88
|
if (*it == '0') {
|
88
89
|
is_found_zero = true;
|
89
90
|
++it;
|
@@ -99,14 +100,14 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
99
100
|
buffer[pos++] = *it;
|
100
101
|
++it;
|
101
102
|
++significant_digits;
|
102
|
-
if (it == last || !
|
103
|
+
if (it == last || !character::IsHexDigit(*it)) {
|
103
104
|
return Conversions::kNaN;
|
104
105
|
}
|
105
106
|
// waste leading zero
|
106
107
|
while (it != last && *it == '0') {
|
107
108
|
++it;
|
108
109
|
}
|
109
|
-
while (it != last &&
|
110
|
+
while (it != last && character::IsHexDigit(*it)) {
|
110
111
|
if (significant_digits < Conversions::kMaxSignificantDigits) {
|
111
112
|
buffer[pos++] = *it;
|
112
113
|
++it;
|
@@ -124,7 +125,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
124
125
|
}
|
125
126
|
if (is_decimal) {
|
126
127
|
while (it != last &&
|
127
|
-
|
128
|
+
character::IsDecimalDigit(*it)) {
|
128
129
|
if (significant_digits < Conversions::kMaxSignificantDigits) {
|
129
130
|
buffer[pos++] = *it;
|
130
131
|
++significant_digits;
|
@@ -137,7 +138,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
137
138
|
buffer[pos++] = '.';
|
138
139
|
++it;
|
139
140
|
while (it != last &&
|
140
|
-
|
141
|
+
character::IsDecimalDigit(*it)) {
|
141
142
|
if (significant_digits < Conversions::kMaxSignificantDigits) {
|
142
143
|
buffer[pos++] = *it;
|
143
144
|
++significant_digits;
|
@@ -152,7 +153,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
152
153
|
++it;
|
153
154
|
const Iter start = it;
|
154
155
|
while (it != last &&
|
155
|
-
|
156
|
+
character::IsDecimalDigit(*it)) {
|
156
157
|
if (significant_digits < Conversions::kMaxSignificantDigits) {
|
157
158
|
buffer[pos++] = *it;
|
158
159
|
++significant_digits;
|
@@ -173,7 +174,8 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
173
174
|
}
|
174
175
|
// infinity
|
175
176
|
while (it != last &&
|
176
|
-
(
|
177
|
+
(character::IsWhiteSpace(*it) ||
|
178
|
+
character::IsLineTerminator(*it))) {
|
177
179
|
++it;
|
178
180
|
}
|
179
181
|
if (it == last || parse_float) {
|
@@ -209,7 +211,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
209
211
|
++it;
|
210
212
|
is_signed_exp = true;
|
211
213
|
}
|
212
|
-
if (it == last || !
|
214
|
+
if (it == last || !character::IsDecimalDigit(*it)) {
|
213
215
|
if (parse_float) {
|
214
216
|
--it;
|
215
217
|
--pos;
|
@@ -229,7 +231,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
229
231
|
exponent = exponent * 10 + (*it - '0');
|
230
232
|
}
|
231
233
|
++it;
|
232
|
-
} while (it != last &&
|
234
|
+
} while (it != last && character::IsDecimalDigit(*it));
|
233
235
|
exponent+=insignificant_digits;
|
234
236
|
if (exponent > 9999) {
|
235
237
|
exponent = 9999;
|
@@ -242,7 +244,7 @@ inline double StringToDouble(Iter it, Iter last, bool parse_float) {
|
|
242
244
|
exponent_pasing_done:
|
243
245
|
|
244
246
|
while (it != last &&
|
245
|
-
(
|
247
|
+
(character::IsWhiteSpace(*it) || character::IsLineTerminator(*it))) {
|
246
248
|
++it;
|
247
249
|
}
|
248
250
|
|
@@ -305,7 +307,7 @@ inline double StringToIntegerWithRadix(Iter it, Iter last,
|
|
305
307
|
int radix, bool strip_prefix) {
|
306
308
|
// remove leading white space
|
307
309
|
while (it != last &&
|
308
|
-
(
|
310
|
+
(character::IsWhiteSpace(*it) || character::IsLineTerminator(*it))) {
|
309
311
|
++it;
|
310
312
|
}
|
311
313
|
|
@@ -411,6 +413,27 @@ inline uint32_t DoubleToUInt32(double d) {
|
|
411
413
|
return static_cast<uint32_t>(DoubleToInt32(d));
|
412
414
|
}
|
413
415
|
|
416
|
+
inline int64_t DoubleToInt64(double d) {
|
417
|
+
int64_t i = static_cast<int64_t>(d);
|
418
|
+
if (static_cast<double>(i) == d) {
|
419
|
+
return i;
|
420
|
+
}
|
421
|
+
if (!std::isfinite(d) || d == 0) {
|
422
|
+
return 0;
|
423
|
+
}
|
424
|
+
if (Conversions::DoubleToInt32_Two32 >= d) {
|
425
|
+
return static_cast<int64_t>(DoubleToInt32(d));
|
426
|
+
}
|
427
|
+
const int32_t lo = DoubleToInt32(
|
428
|
+
std::fmod(d, Conversions::DoubleToInt32_Two32));
|
429
|
+
const int32_t hi = DoubleToInt32(d / Conversions::DoubleToInt32_Two32);
|
430
|
+
return hi * 4294967296ULL + lo;
|
431
|
+
}
|
432
|
+
|
433
|
+
inline uint64_t DoubleToUInt64(double d) {
|
434
|
+
return static_cast<uint64_t>(DoubleToInt64(d));
|
435
|
+
}
|
436
|
+
|
414
437
|
inline double DoubleToInteger(double d) {
|
415
438
|
if (std::isnan(d)) {
|
416
439
|
return 0;
|
@@ -434,7 +457,7 @@ inline bool ConvertToUInt32(Iter it, const Iter last, uint32_t* value) {
|
|
434
457
|
return true;
|
435
458
|
}
|
436
459
|
}
|
437
|
-
if (it != last &&
|
460
|
+
if (it != last && character::IsDecimalDigit(*it)) {
|
438
461
|
ch = *it - '0';
|
439
462
|
*value = ch;
|
440
463
|
} else {
|
@@ -444,7 +467,7 @@ inline bool ConvertToUInt32(Iter it, const Iter last, uint32_t* value) {
|
|
444
467
|
uint32_t prev = *value;
|
445
468
|
for (;it != last; ++it) {
|
446
469
|
prev = *value;
|
447
|
-
if (
|
470
|
+
if (character::IsDecimalDigit(*it)) {
|
448
471
|
ch = *it - '0';
|
449
472
|
*value = ch + (prev * 10);
|
450
473
|
} else {
|
@@ -512,4 +535,4 @@ inline std::string DoubleToStringWithRadix(double v, int radix) {
|
|
512
535
|
}
|
513
536
|
|
514
537
|
} } // namespace iv::core
|
515
|
-
#endif //
|
538
|
+
#endif // _IV_CONVERSIONS_H_
|
data/ext/include/iv/dtoa.h
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#ifndef
|
2
|
-
#define
|
1
|
+
#ifndef _IV_DTOA_H_
|
2
|
+
#define _IV_DTOA_H_
|
3
3
|
// Double to String
|
4
4
|
|
5
5
|
// David M Gay's algorithm and V8 fast-dtoa
|
@@ -16,5 +16,5 @@ namespace core {
|
|
16
16
|
|
17
17
|
using v8::internal::DoubleToCString;
|
18
18
|
|
19
|
-
} } // namespace iv::
|
20
|
-
#endif //
|
19
|
+
} } // namespace iv::core
|
20
|
+
#endif // _IV_DTOA_H_
|
data/ext/include/iv/lexer.h
CHANGED
@@ -364,7 +364,7 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
364
364
|
return buffer16_;
|
365
365
|
}
|
366
366
|
|
367
|
-
inline const std::
|
367
|
+
inline const std::vector<char>& Buffer8() const {
|
368
368
|
return buffer8_;
|
369
369
|
}
|
370
370
|
|
@@ -482,6 +482,17 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
482
482
|
Advance();
|
483
483
|
}
|
484
484
|
|
485
|
+
void Initialize(const Source* src) {
|
486
|
+
using std::swap;
|
487
|
+
source_ = src;
|
488
|
+
pos_ = 0;
|
489
|
+
end_ = source_->size();
|
490
|
+
has_line_terminator_before_next_ = false;
|
491
|
+
has_shebang_ = false;
|
492
|
+
line_number_ = 1;
|
493
|
+
swap(location_, Location());
|
494
|
+
}
|
495
|
+
|
485
496
|
inline void Advance() {
|
486
497
|
if (pos_ == end_) {
|
487
498
|
c_ = -1;
|
@@ -795,13 +806,14 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
795
806
|
|
796
807
|
if (type == OCTAL) {
|
797
808
|
double val = 0;
|
798
|
-
for (std::
|
809
|
+
for (typename std::vector<char>::const_iterator it = buffer8_.begin(),
|
799
810
|
last = buffer8_.end(); it != last; ++it) {
|
800
811
|
val = val * 8 + (*it - '0');
|
801
812
|
}
|
802
813
|
numeric_ = val;
|
803
814
|
} else {
|
804
|
-
|
815
|
+
const std::string buf(buffer8_.begin(), buffer8_.end());
|
816
|
+
numeric_ = std::atof(buf.c_str());
|
805
817
|
}
|
806
818
|
type_ = type;
|
807
819
|
return Token::NUMBER;
|
@@ -857,7 +869,7 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
857
869
|
}
|
858
870
|
|
859
871
|
const Source* source_;
|
860
|
-
std::
|
872
|
+
std::vector<char> buffer8_;
|
861
873
|
std::vector<uc16> buffer16_;
|
862
874
|
double numeric_;
|
863
875
|
State type_;
|
data/ext/include/iv/location.h
CHANGED
data/ext/include/iv/parser.h
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
#include "noncopyable.h"
|
14
14
|
#include "utils.h"
|
15
15
|
#include "ustring.h"
|
16
|
+
#include "enable_if.h"
|
16
17
|
#include "none.h"
|
17
18
|
|
18
19
|
#define IS(token)\
|
@@ -134,11 +135,12 @@ const UString ParserData<T>::kSet(
|
|
134
135
|
|
135
136
|
typedef detail::ParserData<None> ParserData;
|
136
137
|
|
137
|
-
template<typename Factory, typename Source>
|
138
|
-
class Parser
|
138
|
+
template<typename Factory, typename Source, bool UseFunctionStatement>
|
139
|
+
class Parser
|
140
|
+
: private Noncopyable<Parser<Factory, Source, UseFunctionStatement> >::type {
|
139
141
|
public:
|
140
|
-
typedef Parser<Factory, Source> this_type;
|
141
|
-
typedef
|
142
|
+
typedef Parser<Factory, Source, UseFunctionStatement> this_type;
|
143
|
+
typedef this_type parser_type;
|
142
144
|
typedef Lexer<Source> lexer_type;
|
143
145
|
#define V(AST) typedef typename ast::AST<Factory> AST;
|
144
146
|
AST_NODE_LIST(V)
|
@@ -213,7 +215,7 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
213
215
|
|
214
216
|
class TargetScope : private Noncopyable<Target>::type {
|
215
217
|
public:
|
216
|
-
TargetScope(parser_type* parser)
|
218
|
+
explicit TargetScope(parser_type* parser)
|
217
219
|
: parser_(parser),
|
218
220
|
target_(parser->target()),
|
219
221
|
labels_(parser->labels()) {
|
@@ -266,33 +268,39 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
266
268
|
// : Statements
|
267
269
|
// | FunctionDeclaration
|
268
270
|
bool ParseSourceElements(Token::Type end,
|
269
|
-
FunctionLiteral* function,
|
271
|
+
FunctionLiteral* function,
|
272
|
+
bool *res) {
|
270
273
|
Statement* stmt;
|
271
|
-
bool
|
274
|
+
bool recognize_directive = true;
|
272
275
|
const StrictSwitcher switcher(this);
|
273
276
|
while (token_ != end) {
|
274
277
|
if (token_ == Token::FUNCTION) {
|
275
278
|
// FunctionDeclaration
|
276
279
|
stmt = ParseFunctionDeclaration(CHECK);
|
277
280
|
function->AddStatement(stmt);
|
281
|
+
recognize_directive = false;
|
278
282
|
} else {
|
279
283
|
stmt = ParseStatement(CHECK);
|
280
|
-
//
|
281
|
-
if (
|
282
|
-
|
283
|
-
stmt->AsExpressionStatement())
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
284
|
+
// directive prologue
|
285
|
+
if (recognize_directive) {
|
286
|
+
if (stmt->AsExpressionStatement()) {
|
287
|
+
Expression* const expr = stmt->AsExpressionStatement()->expr();
|
288
|
+
if (expr->AsDirectivable()) {
|
289
|
+
// expression is directive
|
290
|
+
if (expr->AsStringLiteral()->value().compare(
|
291
|
+
ParserData::kUseStrict.data()) == 0) {
|
292
|
+
switcher.SwitchStrictMode();
|
293
|
+
function->set_strict(true);
|
294
|
+
}
|
295
|
+
} else {
|
296
|
+
recognize_directive = false;
|
290
297
|
}
|
298
|
+
} else {
|
299
|
+
recognize_directive = false;
|
291
300
|
}
|
292
301
|
}
|
293
302
|
function->AddStatement(stmt);
|
294
303
|
}
|
295
|
-
recognize_use_strict_directive = false;
|
296
304
|
}
|
297
305
|
return true;
|
298
306
|
}
|
@@ -402,7 +410,7 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
402
410
|
case Token::FUNCTION:
|
403
411
|
// FunctionStatement (not in ECMA-262 5th)
|
404
412
|
// FunctionExpression
|
405
|
-
result = ParseFunctionStatement(CHECK);
|
413
|
+
result = ParseFunctionStatement<UseFunctionStatement>(CHECK);
|
406
414
|
break;
|
407
415
|
|
408
416
|
case Token::IDENTIFIER:
|
@@ -784,6 +792,13 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
784
792
|
Statement* ParseReturnStatement(bool *res) {
|
785
793
|
assert(token_ == Token::RETURN);
|
786
794
|
Next();
|
795
|
+
|
796
|
+
if (scope_->IsGlobal()) {
|
797
|
+
// return statement found in global
|
798
|
+
// SyntaxError
|
799
|
+
RAISE("\"return\" not in function");
|
800
|
+
}
|
801
|
+
|
787
802
|
if (lexer_.has_line_terminator_before_next() ||
|
788
803
|
token_ == Token::SEMICOLON ||
|
789
804
|
token_ == Token::RBRACE ||
|
@@ -839,8 +854,21 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
839
854
|
|
840
855
|
EXPECT(Token::LBRACE);
|
841
856
|
|
857
|
+
bool default_found = false;
|
842
858
|
while (token_ != Token::RBRACE) {
|
843
|
-
|
859
|
+
if (token_ == Token::CASE ||
|
860
|
+
token_ == Token::DEFAULT) {
|
861
|
+
case_clause = ParseCaseClause(CHECK);
|
862
|
+
} else {
|
863
|
+
UNEXPECT(token_);
|
864
|
+
}
|
865
|
+
if (case_clause->IsDefault()) {
|
866
|
+
if (default_found) {
|
867
|
+
RAISE("duplicate default clause in switch");
|
868
|
+
} else {
|
869
|
+
default_found = true;
|
870
|
+
}
|
871
|
+
}
|
844
872
|
switch_stmt->AddCaseClause(case_clause);
|
845
873
|
}
|
846
874
|
Next();
|
@@ -918,6 +946,7 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
918
946
|
|
919
947
|
Next();
|
920
948
|
|
949
|
+
IS(Token::LBRACE);
|
921
950
|
Block* const try_block = ParseBlock(CHECK);
|
922
951
|
|
923
952
|
if (token_ == Token::CATCH) {
|
@@ -942,6 +971,7 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
942
971
|
}
|
943
972
|
}
|
944
973
|
EXPECT(Token::RPAREN);
|
974
|
+
IS(Token::LBRACE);
|
945
975
|
catch_block = ParseBlock(CHECK);
|
946
976
|
}
|
947
977
|
|
@@ -949,6 +979,7 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
949
979
|
// Finally
|
950
980
|
has_catch_or_finally= true;
|
951
981
|
Next();
|
982
|
+
IS(Token::LBRACE);
|
952
983
|
finally_block = ParseBlock(CHECK);
|
953
984
|
}
|
954
985
|
|
@@ -1008,7 +1039,9 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
1008
1039
|
return factory_->NewExpressionStatement(expr);
|
1009
1040
|
}
|
1010
1041
|
|
1011
|
-
|
1042
|
+
template<bool Use>
|
1043
|
+
Statement* ParseFunctionStatement(bool *res,
|
1044
|
+
typename enable_if_c<Use>::type* = 0) {
|
1012
1045
|
assert(token_ == Token::FUNCTION);
|
1013
1046
|
if (strict_) {
|
1014
1047
|
RAISE("function statement not allowed in strict code");
|
@@ -1022,6 +1055,15 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
1022
1055
|
return factory_->NewFunctionStatement(expr);
|
1023
1056
|
}
|
1024
1057
|
|
1058
|
+
template<bool Use>
|
1059
|
+
Statement* ParseFunctionStatement(bool *res,
|
1060
|
+
typename enable_if_c<!Use>::type* = 0) {
|
1061
|
+
// FunctionStatement is not Standard
|
1062
|
+
// so, if template parameter UseFunctionStatement is false,
|
1063
|
+
// this parser reject FunctionStatement
|
1064
|
+
RAISE("function statement is not Standard");
|
1065
|
+
}
|
1066
|
+
|
1025
1067
|
// Expression
|
1026
1068
|
// : AssignmentExpression
|
1027
1069
|
// | Expression ',' AssignmentExpression
|
@@ -1614,14 +1656,16 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
1614
1656
|
template<typename Callable>
|
1615
1657
|
Callable* ParseArguments(Callable* func, bool *res) {
|
1616
1658
|
Next();
|
1617
|
-
|
1618
|
-
Expression* const
|
1619
|
-
func->AddArgument(
|
1620
|
-
|
1621
|
-
|
1659
|
+
if (token_ != Token::RPAREN) {
|
1660
|
+
Expression* const first = ParseAssignmentExpression(true, CHECK);
|
1661
|
+
func->AddArgument(first);
|
1662
|
+
while (token_ == Token::COMMA) {
|
1663
|
+
Next();
|
1664
|
+
Expression* const expr = ParseAssignmentExpression(true, CHECK);
|
1665
|
+
func->AddArgument(expr);
|
1622
1666
|
}
|
1623
1667
|
}
|
1624
|
-
|
1668
|
+
EXPECT(Token::RPAREN);
|
1625
1669
|
return func;
|
1626
1670
|
}
|
1627
1671
|
|
@@ -1871,29 +1915,33 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
1871
1915
|
literal->AddParameter(ident);
|
1872
1916
|
EXPECT(Token::RPAREN);
|
1873
1917
|
} else {
|
1874
|
-
|
1875
|
-
|
1876
|
-
|
1877
|
-
|
1878
|
-
|
1879
|
-
|
1880
|
-
|
1881
|
-
|
1882
|
-
|
1918
|
+
if (token_ != Token::RPAREN) {
|
1919
|
+
do {
|
1920
|
+
IS(Token::IDENTIFIER);
|
1921
|
+
Identifier* const ident = ParseIdentifier(lexer_.Buffer());
|
1922
|
+
if (!throw_error_if_strict_code) {
|
1923
|
+
const EvalOrArguments val = IsEvalOrArguments(ident);
|
1924
|
+
if (val) {
|
1925
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1926
|
+
kDetectEvalParameter : kDetectArgumentsParameter;
|
1927
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1928
|
+
}
|
1929
|
+
if ((!throw_error_if_strict_code) &&
|
1930
|
+
(param_set.find(ident) != param_set.end())) {
|
1931
|
+
throw_error_if_strict_code = kDetectDuplicateParameter;
|
1932
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1933
|
+
}
|
1883
1934
|
}
|
1884
|
-
|
1885
|
-
|
1886
|
-
|
1887
|
-
|
1935
|
+
literal->AddParameter(ident);
|
1936
|
+
param_set.insert(ident);
|
1937
|
+
if (token_ == Token::COMMA) {
|
1938
|
+
Next();
|
1939
|
+
} else {
|
1940
|
+
break;
|
1888
1941
|
}
|
1889
|
-
}
|
1890
|
-
literal->AddParameter(ident);
|
1891
|
-
param_set.insert(ident);
|
1892
|
-
if (token_ != Token::RPAREN) {
|
1893
|
-
EXPECT(Token::COMMA);
|
1894
|
-
}
|
1942
|
+
} while (true);
|
1895
1943
|
}
|
1896
|
-
|
1944
|
+
EXPECT(Token::RPAREN);
|
1897
1945
|
}
|
1898
1946
|
|
1899
1947
|
// '{' FunctionBody '}'
|
@@ -2032,9 +2080,9 @@ class Parser : private Noncopyable<Parser<Factory, Source> >::type {
|
|
2032
2080
|
void SetErrorHeader(std::size_t line) {
|
2033
2081
|
std::tr1::array<char, 40> buf;
|
2034
2082
|
error_.append(lexer_.filename());
|
2035
|
-
int num = std::snprintf(buf.data(), buf.size(),
|
2036
|
-
|
2037
|
-
|
2083
|
+
const int num = std::snprintf(buf.data(), buf.size(),
|
2084
|
+
":%lu: SyntaxError: ",
|
2085
|
+
static_cast<unsigned long>(line)); // NOLINT
|
2038
2086
|
error_.append(buf.data(), num);
|
2039
2087
|
}
|
2040
2088
|
|