iv-phonic 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|