iv-phonic 0.0.1
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/.autotest +24 -0
- data/Manifest.txt +49 -0
- data/README.rdoc +32 -0
- data/Rakefile +54 -0
- data/ext/include/iv/algorithm.h +23 -0
- data/ext/include/iv/alloc.h +200 -0
- data/ext/include/iv/any.h +71 -0
- data/ext/include/iv/ast-factory.h +277 -0
- data/ext/include/iv/ast-fwd.h +92 -0
- data/ext/include/iv/ast-serializer.h +579 -0
- data/ext/include/iv/ast-visitor.h +121 -0
- data/ext/include/iv/ast.h +1127 -0
- data/ext/include/iv/chars.h +83 -0
- data/ext/include/iv/cmdline.h +830 -0
- data/ext/include/iv/conversions.h +308 -0
- data/ext/include/iv/dtoa.h +20 -0
- data/ext/include/iv/enable_if.h +18 -0
- data/ext/include/iv/errors.h +15 -0
- data/ext/include/iv/fixedcontainer.h +42 -0
- data/ext/include/iv/functor.h +29 -0
- data/ext/include/iv/lexer.h +1281 -0
- data/ext/include/iv/location.h +23 -0
- data/ext/include/iv/mt19937.h +175 -0
- data/ext/include/iv/noncopyable.h +30 -0
- data/ext/include/iv/none.h +10 -0
- data/ext/include/iv/parser.h +2150 -0
- data/ext/include/iv/source.h +27 -0
- data/ext/include/iv/space.h +178 -0
- data/ext/include/iv/static_assert.h +30 -0
- data/ext/include/iv/stringpiece.h +385 -0
- data/ext/include/iv/token.h +311 -0
- data/ext/include/iv/ucdata.h +58 -0
- data/ext/include/iv/uchar.h +8 -0
- data/ext/include/iv/ustring.h +28 -0
- data/ext/include/iv/ustringpiece.h +9 -0
- data/ext/include/iv/utils.h +83 -0
- data/ext/include/iv/xorshift.h +74 -0
- data/ext/iv/phonic/ast-fwd.h +21 -0
- data/ext/iv/phonic/ast.h +10 -0
- data/ext/iv/phonic/creator.h +530 -0
- data/ext/iv/phonic/encoding.h +110 -0
- data/ext/iv/phonic/extconf.rb +5 -0
- data/ext/iv/phonic/factory.h +247 -0
- data/ext/iv/phonic/parser.h +12 -0
- data/ext/iv/phonic/phonic.cc +69 -0
- data/ext/iv/phonic/rnode.h +15 -0
- data/ext/iv/phonic/rparser.h +48 -0
- data/ext/iv/phonic/source.h +146 -0
- data/test/test_iv_phonic.rb +32 -0
- metadata +159 -0
@@ -0,0 +1,2150 @@
|
|
1
|
+
#ifndef _IV_PARSER_H_
|
2
|
+
#define _IV_PARSER_H_
|
3
|
+
#include <cstdio>
|
4
|
+
#include <cstring>
|
5
|
+
#include <string>
|
6
|
+
#include <tr1/unordered_map>
|
7
|
+
#include <tr1/unordered_set>
|
8
|
+
#include <tr1/type_traits>
|
9
|
+
#include "static_assert.h"
|
10
|
+
#include "ast.h"
|
11
|
+
#include "ast-factory.h"
|
12
|
+
#include "source.h"
|
13
|
+
#include "lexer.h"
|
14
|
+
#include "noncopyable.h"
|
15
|
+
#include "utils.h"
|
16
|
+
#include "none.h"
|
17
|
+
|
18
|
+
#define IS(token)\
|
19
|
+
do {\
|
20
|
+
if (token_ != token) {\
|
21
|
+
*res = false;\
|
22
|
+
ReportUnexpectedToken(token);\
|
23
|
+
return NULL;\
|
24
|
+
}\
|
25
|
+
} while (0)
|
26
|
+
|
27
|
+
#define EXPECT(token)\
|
28
|
+
do {\
|
29
|
+
if (token_ != token) {\
|
30
|
+
*res = false;\
|
31
|
+
ReportUnexpectedToken(token);\
|
32
|
+
return NULL;\
|
33
|
+
}\
|
34
|
+
Next();\
|
35
|
+
} while (0)
|
36
|
+
|
37
|
+
#define UNEXPECT(token)\
|
38
|
+
do {\
|
39
|
+
*res = false;\
|
40
|
+
ReportUnexpectedToken(token);\
|
41
|
+
return NULL;\
|
42
|
+
} while (0)
|
43
|
+
|
44
|
+
#define RAISE(str)\
|
45
|
+
do {\
|
46
|
+
*res = false;\
|
47
|
+
SetErrorHeader(lexer_.line_number());\
|
48
|
+
error_.append(str);\
|
49
|
+
return NULL;\
|
50
|
+
} while (0)
|
51
|
+
|
52
|
+
#define RAISE_WITH_NUMBER(str, line)\
|
53
|
+
do {\
|
54
|
+
*res = false;\
|
55
|
+
SetErrorHeader(line);\
|
56
|
+
error_.append(str);\
|
57
|
+
return NULL;\
|
58
|
+
} while (0)
|
59
|
+
|
60
|
+
#define CHECK res);\
|
61
|
+
if (!*res) {\
|
62
|
+
return NULL;\
|
63
|
+
}\
|
64
|
+
((void)0
|
65
|
+
#define DUMMY ) // to make indentation work
|
66
|
+
#undef DUMMY
|
67
|
+
|
68
|
+
namespace iv {
|
69
|
+
namespace core {
|
70
|
+
namespace detail {
|
71
|
+
template<typename T>
|
72
|
+
class ParserData {
|
73
|
+
private:
|
74
|
+
static const char* use_strict;
|
75
|
+
static const char* arguments;
|
76
|
+
static const char* eval;
|
77
|
+
static const char* get;
|
78
|
+
static const char* set;
|
79
|
+
public:
|
80
|
+
static const UString kUseStrict;
|
81
|
+
static const UString kArguments;
|
82
|
+
static const UString kEval;
|
83
|
+
static const UString kGet;
|
84
|
+
static const UString kSet;
|
85
|
+
};
|
86
|
+
|
87
|
+
template<typename T>
|
88
|
+
const char * ParserData<T>::use_strict = "use strict";
|
89
|
+
|
90
|
+
template<typename T>
|
91
|
+
const char * ParserData<T>::arguments = "arguments";
|
92
|
+
|
93
|
+
template<typename T>
|
94
|
+
const char * ParserData<T>::eval = "eval";
|
95
|
+
|
96
|
+
template<typename T>
|
97
|
+
const char * ParserData<T>::get = "get";
|
98
|
+
|
99
|
+
template<typename T>
|
100
|
+
const char * ParserData<T>::set = "set";
|
101
|
+
|
102
|
+
template<typename T>
|
103
|
+
const UString ParserData<T>::kUseStrict(
|
104
|
+
ParserData<T>::use_strict,
|
105
|
+
ParserData<T>::use_strict + std::strlen(ParserData<T>::use_strict));
|
106
|
+
template<typename T>
|
107
|
+
const UString ParserData<T>::kArguments(
|
108
|
+
ParserData<T>::arguments,
|
109
|
+
ParserData<T>::arguments + std::strlen(ParserData<T>::arguments));
|
110
|
+
template<typename T>
|
111
|
+
const UString ParserData<T>::kEval(
|
112
|
+
ParserData<T>::eval,
|
113
|
+
ParserData<T>::eval + std::strlen(ParserData<T>::eval));
|
114
|
+
template<typename T>
|
115
|
+
const UString ParserData<T>::kGet(
|
116
|
+
ParserData<T>::get,
|
117
|
+
ParserData<T>::get + std::strlen(ParserData<T>::get));
|
118
|
+
template<typename T>
|
119
|
+
const UString ParserData<T>::kSet(
|
120
|
+
ParserData<T>::set,
|
121
|
+
ParserData<T>::set + std::strlen(ParserData<T>::set));
|
122
|
+
|
123
|
+
} // namespace iv::core::detail
|
124
|
+
|
125
|
+
typedef detail::ParserData<None> ParserData;
|
126
|
+
|
127
|
+
template<typename Factory>
|
128
|
+
class Parser : private Noncopyable<Parser<Factory> >::type {
|
129
|
+
public:
|
130
|
+
typedef Parser<Factory> this_type;
|
131
|
+
typedef Parser<Factory> parser_type;
|
132
|
+
#define V(AST) typedef typename ast::AST<Factory> AST;
|
133
|
+
AST_NODE_LIST(V)
|
134
|
+
#undef V
|
135
|
+
#define V(X, XS) typedef typename SpaceVector<Factory, X *>::type XS;
|
136
|
+
AST_LIST_LIST(V)
|
137
|
+
#undef V
|
138
|
+
#define V(S) typedef typename SpaceUString<Factory>::type S;
|
139
|
+
AST_STRING(V)
|
140
|
+
#undef V
|
141
|
+
class Target : private Noncopyable<Target>::type {
|
142
|
+
public:
|
143
|
+
Target(parser_type * parser, BreakableStatement* target)
|
144
|
+
: parser_(parser),
|
145
|
+
prev_(parser->target()),
|
146
|
+
node_(target) {
|
147
|
+
parser_->set_target(this);
|
148
|
+
if (parser_->labels()) {
|
149
|
+
target->set_labels(parser_->labels());
|
150
|
+
parser_->set_labels(NULL);
|
151
|
+
}
|
152
|
+
}
|
153
|
+
~Target() {
|
154
|
+
parser_->set_target(prev_);
|
155
|
+
}
|
156
|
+
inline Target* previous() const {
|
157
|
+
return prev_;
|
158
|
+
}
|
159
|
+
inline BreakableStatement* node() const {
|
160
|
+
return node_;
|
161
|
+
}
|
162
|
+
private:
|
163
|
+
parser_type* parser_;
|
164
|
+
Target* prev_;
|
165
|
+
BreakableStatement* node_;
|
166
|
+
};
|
167
|
+
|
168
|
+
Parser(BasicSource* source, Factory* space)
|
169
|
+
: lexer_(source),
|
170
|
+
error_(),
|
171
|
+
strict_(false),
|
172
|
+
factory_(space),
|
173
|
+
scope_(NULL),
|
174
|
+
target_(NULL),
|
175
|
+
labels_(NULL) {
|
176
|
+
}
|
177
|
+
|
178
|
+
// Program
|
179
|
+
// : SourceElements
|
180
|
+
FunctionLiteral* ParseProgram() {
|
181
|
+
FunctionLiteral* global = factory_->NewFunctionLiteral(
|
182
|
+
FunctionLiteral::GLOBAL);
|
183
|
+
assert(target_ == NULL);
|
184
|
+
bool error_flag = true;
|
185
|
+
bool *res = &error_flag;
|
186
|
+
{
|
187
|
+
const ScopeSwitcher switcher(this, global->scope());
|
188
|
+
Next();
|
189
|
+
ParseSourceElements(Token::EOS, global, CHECK);
|
190
|
+
}
|
191
|
+
return (error_flag) ? global : NULL;
|
192
|
+
}
|
193
|
+
|
194
|
+
// SourceElements
|
195
|
+
// : SourceElement
|
196
|
+
// | SourceElement SourceElements
|
197
|
+
//
|
198
|
+
// SourceElement
|
199
|
+
// : Statements
|
200
|
+
// | FunctionDeclaration
|
201
|
+
bool ParseSourceElements(Token::Type end,
|
202
|
+
FunctionLiteral* function, bool *res) {
|
203
|
+
Statement *stmt;
|
204
|
+
bool recognize_use_strict_directive = true;
|
205
|
+
const StrictSwitcher switcher(this);
|
206
|
+
while (token_ != end) {
|
207
|
+
if (token_ == Token::FUNCTION) {
|
208
|
+
// FunctionDeclaration
|
209
|
+
stmt = ParseFunctionDeclaration(CHECK);
|
210
|
+
function->AddStatement(stmt);
|
211
|
+
} else {
|
212
|
+
stmt = ParseStatement(CHECK);
|
213
|
+
// use strict directive check
|
214
|
+
if (recognize_use_strict_directive &&
|
215
|
+
!strict_ &&
|
216
|
+
stmt->AsExpressionStatement()) {
|
217
|
+
Expression* const expr = stmt->AsExpressionStatement()->expr();
|
218
|
+
if (expr->AsDirectivable()) {
|
219
|
+
if (expr->AsStringLiteral()->value().compare(
|
220
|
+
ParserData::kUseStrict.data()) == 0) {
|
221
|
+
switcher.SwitchStrictMode();
|
222
|
+
function->set_strict(true);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
}
|
226
|
+
function->AddStatement(stmt);
|
227
|
+
}
|
228
|
+
recognize_use_strict_directive = false;
|
229
|
+
}
|
230
|
+
return true;
|
231
|
+
}
|
232
|
+
|
233
|
+
// Statement
|
234
|
+
// : Block
|
235
|
+
// | FunctionStatement // This is not standard.
|
236
|
+
// | VariableStatement
|
237
|
+
// | EmptyStatement
|
238
|
+
// | ExpressionStatement
|
239
|
+
// | IfStatement
|
240
|
+
// | IterationStatement
|
241
|
+
// | ContinueStatement
|
242
|
+
// | BreakStatement
|
243
|
+
// | ReturnStatement
|
244
|
+
// | WithStatement
|
245
|
+
// | LabelledStatement
|
246
|
+
// | SwitchStatement
|
247
|
+
// | ThrowStatement
|
248
|
+
// | TryStatement
|
249
|
+
// | DebuggerStatement
|
250
|
+
Statement* ParseStatement(bool *res) {
|
251
|
+
Statement *result = NULL;
|
252
|
+
switch (token_) {
|
253
|
+
case Token::LBRACE:
|
254
|
+
// Block
|
255
|
+
result = ParseBlock(CHECK);
|
256
|
+
break;
|
257
|
+
|
258
|
+
case Token::CONST:
|
259
|
+
if (strict_) {
|
260
|
+
RAISE("\"const\" not allowed in strict code");
|
261
|
+
}
|
262
|
+
case Token::VAR:
|
263
|
+
// VariableStatement
|
264
|
+
result = ParseVariableStatement(CHECK);
|
265
|
+
break;
|
266
|
+
|
267
|
+
case Token::SEMICOLON:
|
268
|
+
// EmptyStatement
|
269
|
+
result = ParseEmptyStatement();
|
270
|
+
break;
|
271
|
+
|
272
|
+
case Token::IF:
|
273
|
+
// IfStatement
|
274
|
+
result = ParseIfStatement(CHECK);
|
275
|
+
break;
|
276
|
+
|
277
|
+
case Token::DO:
|
278
|
+
// IterationStatement
|
279
|
+
// do while
|
280
|
+
result = ParseDoWhileStatement(CHECK);
|
281
|
+
break;
|
282
|
+
|
283
|
+
case Token::WHILE:
|
284
|
+
// IterationStatement
|
285
|
+
// while
|
286
|
+
result = ParseWhileStatement(CHECK);
|
287
|
+
break;
|
288
|
+
|
289
|
+
case Token::FOR:
|
290
|
+
// IterationStatement
|
291
|
+
// for
|
292
|
+
result = ParseForStatement(CHECK);
|
293
|
+
break;
|
294
|
+
|
295
|
+
case Token::CONTINUE:
|
296
|
+
// ContinueStatement
|
297
|
+
result = ParseContinueStatement(CHECK);
|
298
|
+
break;
|
299
|
+
|
300
|
+
case Token::BREAK:
|
301
|
+
// BreakStatement
|
302
|
+
result = ParseBreakStatement(CHECK);
|
303
|
+
break;
|
304
|
+
|
305
|
+
case Token::RETURN:
|
306
|
+
// ReturnStatement
|
307
|
+
result = ParseReturnStatement(CHECK);
|
308
|
+
break;
|
309
|
+
|
310
|
+
case Token::WITH:
|
311
|
+
// WithStatement
|
312
|
+
result = ParseWithStatement(CHECK);
|
313
|
+
break;
|
314
|
+
|
315
|
+
case Token::SWITCH:
|
316
|
+
// SwitchStatement
|
317
|
+
result = ParseSwitchStatement(CHECK);
|
318
|
+
break;
|
319
|
+
|
320
|
+
case Token::THROW:
|
321
|
+
// ThrowStatement
|
322
|
+
result = ParseThrowStatement(CHECK);
|
323
|
+
break;
|
324
|
+
|
325
|
+
case Token::TRY:
|
326
|
+
// TryStatement
|
327
|
+
result = ParseTryStatement(CHECK);
|
328
|
+
break;
|
329
|
+
|
330
|
+
case Token::DEBUGGER:
|
331
|
+
// DebuggerStatement
|
332
|
+
result = ParseDebuggerStatement(CHECK);
|
333
|
+
break;
|
334
|
+
|
335
|
+
case Token::FUNCTION:
|
336
|
+
// FunctionStatement (not in ECMA-262 5th)
|
337
|
+
// FunctionExpression
|
338
|
+
result = ParseFunctionStatement(CHECK);
|
339
|
+
break;
|
340
|
+
|
341
|
+
case Token::IDENTIFIER:
|
342
|
+
// LabelledStatement or ExpressionStatement
|
343
|
+
result = ParseExpressionOrLabelledStatement(CHECK);
|
344
|
+
break;
|
345
|
+
|
346
|
+
case Token::ILLEGAL:
|
347
|
+
UNEXPECT(token_);
|
348
|
+
break;
|
349
|
+
|
350
|
+
default:
|
351
|
+
// ExpressionStatement or ILLEGAL
|
352
|
+
result = ParseExpressionStatement(CHECK);
|
353
|
+
break;
|
354
|
+
}
|
355
|
+
return result;
|
356
|
+
}
|
357
|
+
|
358
|
+
// FunctionDeclaration
|
359
|
+
// : FUNCTION IDENTIFIER '(' FormalParameterList_opt ')' '{' FunctionBody '}'
|
360
|
+
//
|
361
|
+
// FunctionStatement
|
362
|
+
// : FUNCTION IDENTIFIER '(' FormalParameterList_opt ')' '{' FunctionBody '}'
|
363
|
+
//
|
364
|
+
// FunctionExpression
|
365
|
+
// : FUNCTION
|
366
|
+
// IDENTIFIER_opt '(' FormalParameterList_opt ')' '{' FunctionBody '}'
|
367
|
+
//
|
368
|
+
// FunctionStatement is not standard, but implemented in SpiderMonkey
|
369
|
+
// and this statement is very useful for not breaking FunctionDeclaration.
|
370
|
+
Statement* ParseFunctionDeclaration(bool *res) {
|
371
|
+
assert(token_ == Token::FUNCTION);
|
372
|
+
Next();
|
373
|
+
IS(Token::IDENTIFIER);
|
374
|
+
FunctionLiteral* expr = ParseFunctionLiteral(
|
375
|
+
FunctionLiteral::DECLARATION,
|
376
|
+
FunctionLiteral::GENERAL, true, CHECK);
|
377
|
+
// define named function as FunctionDeclaration
|
378
|
+
scope_->AddFunctionDeclaration(expr);
|
379
|
+
return factory_->NewFunctionStatement(expr);
|
380
|
+
}
|
381
|
+
|
382
|
+
// Block
|
383
|
+
// : '{' '}'
|
384
|
+
// | '{' StatementList '}'
|
385
|
+
//
|
386
|
+
// StatementList
|
387
|
+
// : Statement
|
388
|
+
// | StatementList Statement
|
389
|
+
Block* ParseBlock(bool *res) {
|
390
|
+
assert(token_ == Token::LBRACE);
|
391
|
+
Block *block = factory_->NewBlock();
|
392
|
+
Statement *stmt;
|
393
|
+
Target target(this, block);
|
394
|
+
|
395
|
+
Next();
|
396
|
+
while (token_ != Token::RBRACE) {
|
397
|
+
stmt = ParseStatement(CHECK);
|
398
|
+
block->AddStatement(stmt);
|
399
|
+
}
|
400
|
+
Next();
|
401
|
+
return block;
|
402
|
+
}
|
403
|
+
|
404
|
+
// VariableStatement
|
405
|
+
// : VAR VariableDeclarationList ';'
|
406
|
+
// : CONST VariableDeclarationList ';'
|
407
|
+
Statement* ParseVariableStatement(bool *res) {
|
408
|
+
assert(token_ == Token::VAR || token_ == Token::CONST);
|
409
|
+
VariableStatement* stmt = factory_->NewVariableStatement(token_);
|
410
|
+
ParseVariableDeclarations(stmt, true, CHECK);
|
411
|
+
ExpectSemicolon(CHECK);
|
412
|
+
return stmt;
|
413
|
+
}
|
414
|
+
|
415
|
+
// VariableDeclarationList
|
416
|
+
// : VariableDeclaration
|
417
|
+
// | VariableDeclarationList ',' VariableDeclaration
|
418
|
+
//
|
419
|
+
// VariableDeclaration
|
420
|
+
// : IDENTIFIER Initialiser_opt
|
421
|
+
//
|
422
|
+
// Initialiser_opt
|
423
|
+
// :
|
424
|
+
// | Initialiser
|
425
|
+
//
|
426
|
+
// Initialiser
|
427
|
+
// : '=' AssignmentExpression
|
428
|
+
Statement* ParseVariableDeclarations(VariableStatement* stmt,
|
429
|
+
bool contains_in,
|
430
|
+
bool *res) {
|
431
|
+
Identifier *name;
|
432
|
+
Expression *expr;
|
433
|
+
Declaration *decl;
|
434
|
+
|
435
|
+
do {
|
436
|
+
Next();
|
437
|
+
IS(Token::IDENTIFIER);
|
438
|
+
name = factory_->NewIdentifier(lexer_.Buffer());
|
439
|
+
// section 12.2.1
|
440
|
+
// within the strict code, Identifier must not be "eval" or "arguments"
|
441
|
+
if (strict_) {
|
442
|
+
const EvalOrArguments val = IsEvalOrArguments(name);
|
443
|
+
if (val) {
|
444
|
+
if (val == kEval) {
|
445
|
+
RAISE("assignment to \"eval\" not allowed in strict code");
|
446
|
+
} else {
|
447
|
+
assert(val == kArguments);
|
448
|
+
RAISE("assignment to \"arguments\" not allowed in strict code");
|
449
|
+
}
|
450
|
+
}
|
451
|
+
}
|
452
|
+
Next();
|
453
|
+
|
454
|
+
if (token_ == Token::ASSIGN) {
|
455
|
+
Next();
|
456
|
+
// AssignmentExpression
|
457
|
+
expr = ParseAssignmentExpression(contains_in, CHECK);
|
458
|
+
decl = factory_->NewDeclaration(name, expr);
|
459
|
+
} else {
|
460
|
+
// Undefined Expression
|
461
|
+
decl = factory_->NewDeclaration(name, factory_->NewUndefined());
|
462
|
+
}
|
463
|
+
stmt->AddDeclaration(decl);
|
464
|
+
scope_->AddUnresolved(name, stmt->IsConst());
|
465
|
+
} while (token_ == Token::COMMA);
|
466
|
+
|
467
|
+
return stmt;
|
468
|
+
}
|
469
|
+
|
470
|
+
// EmptyStatement
|
471
|
+
// : ';'
|
472
|
+
Statement* ParseEmptyStatement() {
|
473
|
+
assert(token_ == Token::SEMICOLON);
|
474
|
+
Next();
|
475
|
+
return factory_->NewEmptyStatement();
|
476
|
+
}
|
477
|
+
|
478
|
+
// IfStatement
|
479
|
+
// : IF '(' Expression ')' Statement ELSE Statement
|
480
|
+
// | IF '(' Expression ')' Statement
|
481
|
+
Statement* ParseIfStatement(bool *res) {
|
482
|
+
assert(token_ == Token::IF);
|
483
|
+
IfStatement *if_stmt = NULL;
|
484
|
+
Statement* stmt;
|
485
|
+
Next();
|
486
|
+
|
487
|
+
EXPECT(Token::LPAREN);
|
488
|
+
|
489
|
+
Expression *expr = ParseExpression(true, CHECK);
|
490
|
+
|
491
|
+
EXPECT(Token::RPAREN);
|
492
|
+
|
493
|
+
stmt = ParseStatement(CHECK);
|
494
|
+
if_stmt = factory_->NewIfStatement(expr, stmt);
|
495
|
+
if (token_ == Token::ELSE) {
|
496
|
+
Next();
|
497
|
+
stmt = ParseStatement(CHECK);
|
498
|
+
if_stmt->SetElse(stmt);
|
499
|
+
}
|
500
|
+
return if_stmt;
|
501
|
+
}
|
502
|
+
|
503
|
+
// IterationStatement
|
504
|
+
// : DO Statement WHILE '(' Expression ')' ';'
|
505
|
+
// | WHILE '(' Expression ')' Statement
|
506
|
+
// | FOR '(' ExpressionNoIn_opt ';' Expression_opt ';' Expression_opt ')'
|
507
|
+
// Statement
|
508
|
+
// | FOR '(' VAR VariableDeclarationListNoIn ';'
|
509
|
+
// Expression_opt ';'
|
510
|
+
// Expression_opt ')'
|
511
|
+
// Statement
|
512
|
+
// | FOR '(' LeftHandSideExpression IN Expression ')' Statement
|
513
|
+
// | FOR '(' VAR VariableDeclarationNoIn IN Expression ')' Statement
|
514
|
+
Statement* ParseDoWhileStatement(bool *res) {
|
515
|
+
// DO Statement WHILE '(' Expression ')' ';'
|
516
|
+
assert(token_ == Token::DO);
|
517
|
+
DoWhileStatement* dowhile = factory_->NewDoWhileStatement();
|
518
|
+
Target target(this, dowhile);
|
519
|
+
Next();
|
520
|
+
|
521
|
+
Statement *stmt = ParseStatement(CHECK);
|
522
|
+
dowhile->set_body(stmt);
|
523
|
+
|
524
|
+
EXPECT(Token::WHILE);
|
525
|
+
|
526
|
+
EXPECT(Token::LPAREN);
|
527
|
+
|
528
|
+
Expression *expr = ParseExpression(true, CHECK);
|
529
|
+
dowhile->set_cond(expr);
|
530
|
+
|
531
|
+
EXPECT(Token::RPAREN);
|
532
|
+
|
533
|
+
ExpectSemicolon(CHECK);
|
534
|
+
return dowhile;
|
535
|
+
}
|
536
|
+
|
537
|
+
// WHILE '(' Expression ')' Statement
|
538
|
+
Statement* ParseWhileStatement(bool *res) {
|
539
|
+
assert(token_ == Token::WHILE);
|
540
|
+
Next();
|
541
|
+
|
542
|
+
EXPECT(Token::LPAREN);
|
543
|
+
|
544
|
+
Expression *expr = ParseExpression(true, CHECK);
|
545
|
+
WhileStatement* whilestmt = factory_->NewWhileStatement(expr);
|
546
|
+
Target target(this, whilestmt);
|
547
|
+
|
548
|
+
EXPECT(Token::RPAREN);
|
549
|
+
|
550
|
+
Statement* stmt = ParseStatement(CHECK);
|
551
|
+
whilestmt->set_body(stmt);
|
552
|
+
|
553
|
+
return whilestmt;
|
554
|
+
}
|
555
|
+
|
556
|
+
// FOR '(' ExpressionNoIn_opt ';' Expression_opt ';' Expression_opt ')'
|
557
|
+
// Statement
|
558
|
+
// FOR '(' VAR VariableDeclarationListNoIn ';'
|
559
|
+
// Expression_opt ';'
|
560
|
+
// Expression_opt ')'
|
561
|
+
// Statement
|
562
|
+
// FOR '(' LeftHandSideExpression IN Expression ')' Statement
|
563
|
+
// FOR '(' VAR VariableDeclarationNoIn IN Expression ')' Statement
|
564
|
+
Statement* ParseForStatement(bool *res) {
|
565
|
+
assert(token_ == Token::FOR);
|
566
|
+
Next();
|
567
|
+
|
568
|
+
EXPECT(Token::LPAREN);
|
569
|
+
|
570
|
+
Statement *init = NULL;
|
571
|
+
|
572
|
+
if (token_ != Token::SEMICOLON) {
|
573
|
+
if (token_ == Token::VAR || token_ == Token::CONST) {
|
574
|
+
VariableStatement *var = factory_->NewVariableStatement(token_);
|
575
|
+
ParseVariableDeclarations(var, false, CHECK);
|
576
|
+
init = var;
|
577
|
+
if (token_ == Token::IN) {
|
578
|
+
// for in loop
|
579
|
+
Next();
|
580
|
+
const Declarations& decls = var->decls();
|
581
|
+
if (decls.size() != 1) {
|
582
|
+
// ForInStatement requests VaraibleDeclarationNoIn (not List),
|
583
|
+
// so check declarations' size is 1.
|
584
|
+
RAISE("invalid for-in left-hand-side");
|
585
|
+
}
|
586
|
+
Expression *enumerable = ParseExpression(true, CHECK);
|
587
|
+
EXPECT(Token::RPAREN);
|
588
|
+
ForInStatement* forstmt =
|
589
|
+
factory_->NewForInStatement(init, enumerable);
|
590
|
+
Target target(this, forstmt);
|
591
|
+
Statement *body = ParseStatement(CHECK);
|
592
|
+
forstmt->set_body(body);
|
593
|
+
return forstmt;
|
594
|
+
}
|
595
|
+
} else {
|
596
|
+
Expression *init_expr = ParseExpression(false, CHECK);
|
597
|
+
init = factory_->NewExpressionStatement(init_expr);
|
598
|
+
if (token_ == Token::IN) {
|
599
|
+
// for in loop
|
600
|
+
if (!init_expr->IsValidLeftHandSide()) {
|
601
|
+
RAISE("invalid for-in left-hand-side");
|
602
|
+
}
|
603
|
+
Next();
|
604
|
+
Expression *enumerable = ParseExpression(true, CHECK);
|
605
|
+
EXPECT(Token::RPAREN);
|
606
|
+
ForInStatement* forstmt =
|
607
|
+
factory_->NewForInStatement(init, enumerable);
|
608
|
+
Target target(this, forstmt);
|
609
|
+
Statement *body = ParseStatement(CHECK);
|
610
|
+
forstmt->set_body(body);
|
611
|
+
return forstmt;
|
612
|
+
}
|
613
|
+
}
|
614
|
+
}
|
615
|
+
|
616
|
+
// ordinary for loop
|
617
|
+
EXPECT(Token::SEMICOLON);
|
618
|
+
|
619
|
+
Expression *cond = NULL;
|
620
|
+
if (token_ == Token::SEMICOLON) {
|
621
|
+
// no cond expr
|
622
|
+
Next();
|
623
|
+
} else {
|
624
|
+
cond = ParseExpression(true, CHECK);
|
625
|
+
EXPECT(Token::SEMICOLON);
|
626
|
+
}
|
627
|
+
|
628
|
+
ExpressionStatement *next = NULL;
|
629
|
+
if (token_ == Token::RPAREN) {
|
630
|
+
Next();
|
631
|
+
} else {
|
632
|
+
Expression *next_expr = ParseExpression(true, CHECK);
|
633
|
+
next = factory_->NewExpressionStatement(next_expr);
|
634
|
+
EXPECT(Token::RPAREN);
|
635
|
+
}
|
636
|
+
|
637
|
+
ForStatement *for_stmt = factory_->NewForStatement();
|
638
|
+
Target target(this, for_stmt);
|
639
|
+
Statement *body = ParseStatement(CHECK);
|
640
|
+
for_stmt->set_body(body);
|
641
|
+
if (init) {
|
642
|
+
for_stmt->SetInit(init);
|
643
|
+
}
|
644
|
+
if (cond) {
|
645
|
+
for_stmt->SetCondition(cond);
|
646
|
+
}
|
647
|
+
if (next) {
|
648
|
+
for_stmt->SetNext(next);
|
649
|
+
}
|
650
|
+
|
651
|
+
return for_stmt;
|
652
|
+
}
|
653
|
+
|
654
|
+
// ContinueStatement
|
655
|
+
// : CONTINUE Identifier_opt ';'
|
656
|
+
Statement* ParseContinueStatement(bool *res) {
|
657
|
+
assert(token_ == Token::CONTINUE);
|
658
|
+
ContinueStatement *continue_stmt = factory_->NewContinueStatement();
|
659
|
+
Next();
|
660
|
+
if (!lexer_.has_line_terminator_before_next() &&
|
661
|
+
token_ != Token::SEMICOLON &&
|
662
|
+
token_ != Token::RBRACE &&
|
663
|
+
token_ != Token::EOS) {
|
664
|
+
IS(Token::IDENTIFIER);
|
665
|
+
Identifier* label = factory_->NewIdentifier(lexer_.Buffer());
|
666
|
+
continue_stmt->SetLabel(label);
|
667
|
+
IterationStatement* target = LookupContinuableTarget(label);
|
668
|
+
if (target) {
|
669
|
+
continue_stmt->SetTarget(target);
|
670
|
+
} else {
|
671
|
+
RAISE("label not found");
|
672
|
+
}
|
673
|
+
Next();
|
674
|
+
} else {
|
675
|
+
IterationStatement* target = LookupContinuableTarget();
|
676
|
+
if (target) {
|
677
|
+
continue_stmt->SetTarget(target);
|
678
|
+
} else {
|
679
|
+
RAISE("label not found");
|
680
|
+
}
|
681
|
+
}
|
682
|
+
ExpectSemicolon(CHECK);
|
683
|
+
return continue_stmt;
|
684
|
+
}
|
685
|
+
|
686
|
+
// BreakStatement
|
687
|
+
// : BREAK Identifier_opt ';'
|
688
|
+
Statement* ParseBreakStatement(bool *res) {
|
689
|
+
assert(token_ == Token::BREAK);
|
690
|
+
BreakStatement *break_stmt = factory_->NewBreakStatement();
|
691
|
+
Next();
|
692
|
+
if (!lexer_.has_line_terminator_before_next() &&
|
693
|
+
token_ != Token::SEMICOLON &&
|
694
|
+
token_ != Token::RBRACE &&
|
695
|
+
token_ != Token::EOS) {
|
696
|
+
// label
|
697
|
+
IS(Token::IDENTIFIER);
|
698
|
+
Identifier* label = factory_->NewIdentifier(lexer_.Buffer());
|
699
|
+
break_stmt->SetLabel(label);
|
700
|
+
if (ContainsLabel(labels_, label)) {
|
701
|
+
// example
|
702
|
+
//
|
703
|
+
// do {
|
704
|
+
// test: break test;
|
705
|
+
// } while (0);
|
706
|
+
//
|
707
|
+
// This BreakStatement is interpreted as EmptyStatement
|
708
|
+
// In iv, BreakStatement with label, but without target is
|
709
|
+
// interpreted as EmptyStatement
|
710
|
+
} else {
|
711
|
+
BreakableStatement* target = LookupBreakableTarget(label);
|
712
|
+
if (target) {
|
713
|
+
break_stmt->SetTarget(target);
|
714
|
+
} else {
|
715
|
+
RAISE("label not found");
|
716
|
+
}
|
717
|
+
}
|
718
|
+
Next();
|
719
|
+
} else {
|
720
|
+
BreakableStatement* target = LookupBreakableTarget();
|
721
|
+
if (target) {
|
722
|
+
break_stmt->SetTarget(target);
|
723
|
+
} else {
|
724
|
+
RAISE("label not found");
|
725
|
+
}
|
726
|
+
}
|
727
|
+
ExpectSemicolon(CHECK);
|
728
|
+
return break_stmt;
|
729
|
+
}
|
730
|
+
|
731
|
+
// ReturnStatement
|
732
|
+
// : RETURN Expression_opt ';'
|
733
|
+
Statement* ParseReturnStatement(bool *res) {
|
734
|
+
assert(token_ == Token::RETURN);
|
735
|
+
Next();
|
736
|
+
if (lexer_.has_line_terminator_before_next() ||
|
737
|
+
token_ == Token::SEMICOLON ||
|
738
|
+
token_ == Token::RBRACE ||
|
739
|
+
token_ == Token::EOS) {
|
740
|
+
ExpectSemicolon(CHECK);
|
741
|
+
return factory_->NewReturnStatement(factory_->NewUndefined());
|
742
|
+
}
|
743
|
+
Expression *expr = ParseExpression(true, CHECK);
|
744
|
+
ExpectSemicolon(CHECK);
|
745
|
+
return factory_->NewReturnStatement(expr);
|
746
|
+
}
|
747
|
+
|
748
|
+
// WithStatement
|
749
|
+
// : WITH '(' Expression ')' Statement
|
750
|
+
Statement* ParseWithStatement(bool *res) {
|
751
|
+
assert(token_ == Token::WITH);
|
752
|
+
Next();
|
753
|
+
|
754
|
+
// section 12.10.1
|
755
|
+
// when in strict mode code, WithStatement is not allowed.
|
756
|
+
if (strict_) {
|
757
|
+
RAISE("with statement not allowed in strict code");
|
758
|
+
}
|
759
|
+
|
760
|
+
EXPECT(Token::LPAREN);
|
761
|
+
|
762
|
+
Expression *expr = ParseExpression(true, CHECK);
|
763
|
+
|
764
|
+
EXPECT(Token::RPAREN);
|
765
|
+
|
766
|
+
Statement *stmt = ParseStatement(CHECK);
|
767
|
+
return factory_->NewWithStatement(expr, stmt);
|
768
|
+
}
|
769
|
+
|
770
|
+
// SwitchStatement
|
771
|
+
// : SWITCH '(' Expression ')' CaseBlock
|
772
|
+
//
|
773
|
+
// CaseBlock
|
774
|
+
// : '{' CaseClauses_opt '}'
|
775
|
+
// | '{' CaseClauses_opt DefaultClause CaseClauses_opt '}'
|
776
|
+
Statement* ParseSwitchStatement(bool *res) {
|
777
|
+
assert(token_ == Token::SWITCH);
|
778
|
+
CaseClause *case_clause;
|
779
|
+
Next();
|
780
|
+
|
781
|
+
EXPECT(Token::LPAREN);
|
782
|
+
|
783
|
+
Expression *expr = ParseExpression(true, CHECK);
|
784
|
+
SwitchStatement *switch_stmt = factory_->NewSwitchStatement(expr);
|
785
|
+
Target target(this, switch_stmt);
|
786
|
+
|
787
|
+
EXPECT(Token::RPAREN);
|
788
|
+
|
789
|
+
EXPECT(Token::LBRACE);
|
790
|
+
|
791
|
+
while (token_ != Token::RBRACE) {
|
792
|
+
case_clause = ParseCaseClause(CHECK);
|
793
|
+
switch_stmt->AddCaseClause(case_clause);
|
794
|
+
}
|
795
|
+
Next();
|
796
|
+
|
797
|
+
return switch_stmt;
|
798
|
+
}
|
799
|
+
|
800
|
+
// CaseClauses
|
801
|
+
// : CaseClause
|
802
|
+
// | CaseClauses CaseClause
|
803
|
+
//
|
804
|
+
// CaseClause
|
805
|
+
// : CASE Expression ':' StatementList_opt
|
806
|
+
//
|
807
|
+
// DefaultClause
|
808
|
+
// : DEFAULT ':' StatementList_opt
|
809
|
+
CaseClause* ParseCaseClause(bool *res) {
|
810
|
+
assert(token_ == Token::CASE || token_ == Token::DEFAULT);
|
811
|
+
CaseClause *clause = factory_->NewCaseClause();
|
812
|
+
Statement *stmt;
|
813
|
+
|
814
|
+
if (token_ == Token::CASE) {
|
815
|
+
Next();
|
816
|
+
Expression *expr = ParseExpression(true, CHECK);
|
817
|
+
clause->SetExpression(expr);
|
818
|
+
} else {
|
819
|
+
EXPECT(Token::DEFAULT);
|
820
|
+
clause->SetDefault();
|
821
|
+
}
|
822
|
+
|
823
|
+
EXPECT(Token::COLON);
|
824
|
+
|
825
|
+
while (token_ != Token::RBRACE &&
|
826
|
+
token_ != Token::CASE &&
|
827
|
+
token_ != Token::DEFAULT) {
|
828
|
+
stmt = ParseStatement(CHECK);
|
829
|
+
clause->AddStatement(stmt);
|
830
|
+
}
|
831
|
+
|
832
|
+
return clause;
|
833
|
+
}
|
834
|
+
|
835
|
+
// ThrowStatement
|
836
|
+
// : THROW Expression ';'
|
837
|
+
Statement* ParseThrowStatement(bool *res) {
|
838
|
+
assert(token_ == Token::THROW);
|
839
|
+
Expression *expr;
|
840
|
+
Next();
|
841
|
+
// Throw requires Expression
|
842
|
+
if (lexer_.has_line_terminator_before_next()) {
|
843
|
+
RAISE("missing expression between throw and newline");
|
844
|
+
}
|
845
|
+
expr = ParseExpression(true, CHECK);
|
846
|
+
ExpectSemicolon(CHECK);
|
847
|
+
return factory_->NewThrowStatement(expr);
|
848
|
+
}
|
849
|
+
|
850
|
+
// TryStatement
|
851
|
+
// : TRY Block Catch
|
852
|
+
// | TRY Block Finally
|
853
|
+
// | TRY Block Catch Finally
|
854
|
+
//
|
855
|
+
// Catch
|
856
|
+
// : CATCH '(' IDENTIFIER ')' Block
|
857
|
+
//
|
858
|
+
// Finally
|
859
|
+
// : FINALLY Block
|
860
|
+
Statement* ParseTryStatement(bool *res) {
|
861
|
+
assert(token_ == Token::TRY);
|
862
|
+
Identifier *name;
|
863
|
+
Block *block;
|
864
|
+
bool has_catch_or_finally = false;
|
865
|
+
|
866
|
+
Next();
|
867
|
+
|
868
|
+
block = ParseBlock(CHECK);
|
869
|
+
TryStatement *try_stmt = factory_->NewTryStatement(block);
|
870
|
+
|
871
|
+
if (token_ == Token::CATCH) {
|
872
|
+
// Catch
|
873
|
+
has_catch_or_finally = true;
|
874
|
+
Next();
|
875
|
+
EXPECT(Token::LPAREN);
|
876
|
+
IS(Token::IDENTIFIER);
|
877
|
+
name = factory_->NewIdentifier(lexer_.Buffer());
|
878
|
+
// section 12.14.1
|
879
|
+
// within the strict code, Identifier must not be "eval" or "arguments"
|
880
|
+
if (strict_) {
|
881
|
+
const EvalOrArguments val = IsEvalOrArguments(name);
|
882
|
+
if (val) {
|
883
|
+
if (val == kEval) {
|
884
|
+
RAISE("catch placeholder \"eval\" not allowed in strict code");
|
885
|
+
} else {
|
886
|
+
assert(val == kArguments);
|
887
|
+
RAISE(
|
888
|
+
"catch placeholder \"arguments\" not allowed in strict code");
|
889
|
+
}
|
890
|
+
}
|
891
|
+
}
|
892
|
+
Next();
|
893
|
+
EXPECT(Token::RPAREN);
|
894
|
+
block = ParseBlock(CHECK);
|
895
|
+
try_stmt->SetCatch(name, block);
|
896
|
+
}
|
897
|
+
|
898
|
+
if (token_ == Token::FINALLY) {
|
899
|
+
// Finally
|
900
|
+
has_catch_or_finally= true;
|
901
|
+
Next();
|
902
|
+
block = ParseBlock(CHECK);
|
903
|
+
try_stmt->SetFinally(block);
|
904
|
+
}
|
905
|
+
|
906
|
+
if (!has_catch_or_finally) {
|
907
|
+
RAISE("missing catch or finally after try statement");
|
908
|
+
}
|
909
|
+
|
910
|
+
return try_stmt;
|
911
|
+
}
|
912
|
+
|
913
|
+
// DebuggerStatement
|
914
|
+
// : DEBUGGER ';'
|
915
|
+
Statement* ParseDebuggerStatement(bool *res) {
|
916
|
+
assert(token_ == Token::DEBUGGER);
|
917
|
+
Next();
|
918
|
+
ExpectSemicolon(CHECK);
|
919
|
+
return factory_->NewDebuggerStatement();
|
920
|
+
}
|
921
|
+
|
922
|
+
Statement* ParseExpressionStatement(bool *res) {
|
923
|
+
Expression* expr = ParseExpression(true, CHECK);
|
924
|
+
ExpectSemicolon(CHECK);
|
925
|
+
return factory_->NewExpressionStatement(expr);
|
926
|
+
}
|
927
|
+
|
928
|
+
// LabelledStatement
|
929
|
+
// : IDENTIFIER ':' Statement
|
930
|
+
//
|
931
|
+
// ExpressionStatement
|
932
|
+
// : Expression ';'
|
933
|
+
Statement* ParseExpressionOrLabelledStatement(bool *res) {
|
934
|
+
assert(token_ == Token::IDENTIFIER);
|
935
|
+
Expression* expr = ParseExpression(true, CHECK);
|
936
|
+
if (token_ == Token::COLON &&
|
937
|
+
expr->AsIdentifier()) {
|
938
|
+
// LabelledStatement
|
939
|
+
Next();
|
940
|
+
|
941
|
+
Identifiers* labels = labels_;
|
942
|
+
Identifier* const label = expr->AsIdentifier();
|
943
|
+
const bool exist_labels = labels;
|
944
|
+
if (!exist_labels) {
|
945
|
+
labels = factory_->NewLabels();
|
946
|
+
}
|
947
|
+
if (ContainsLabel(labels, label) || TargetsContainsLabel(label)) {
|
948
|
+
// duplicate label
|
949
|
+
RAISE("duplicate label");
|
950
|
+
}
|
951
|
+
labels->push_back(label);
|
952
|
+
LabelScope scope(this, labels, exist_labels);
|
953
|
+
|
954
|
+
Statement* stmt = ParseStatement(CHECK);
|
955
|
+
return factory_->NewLabelledStatement(expr, stmt);
|
956
|
+
}
|
957
|
+
ExpectSemicolon(CHECK);
|
958
|
+
return factory_->NewExpressionStatement(expr);
|
959
|
+
}
|
960
|
+
|
961
|
+
Statement* ParseFunctionStatement(bool *res) {
|
962
|
+
assert(token_ == Token::FUNCTION);
|
963
|
+
if (strict_) {
|
964
|
+
RAISE("function statement not allowed in strict code");
|
965
|
+
}
|
966
|
+
Next();
|
967
|
+
IS(Token::IDENTIFIER);
|
968
|
+
FunctionLiteral* expr = ParseFunctionLiteral(FunctionLiteral::STATEMENT,
|
969
|
+
FunctionLiteral::GENERAL,
|
970
|
+
true, CHECK);
|
971
|
+
// define named function as variable declaration
|
972
|
+
scope_->AddUnresolved(expr->name(), false);
|
973
|
+
return factory_->NewFunctionStatement(expr);
|
974
|
+
}
|
975
|
+
|
976
|
+
// Expression
|
977
|
+
// : AssignmentExpression
|
978
|
+
// | Expression ',' AssignmentExpression
|
979
|
+
Expression* ParseExpression(bool contains_in, bool *res) {
|
980
|
+
Expression *right;
|
981
|
+
Expression *result = ParseAssignmentExpression(contains_in, CHECK);
|
982
|
+
while (token_ == Token::COMMA) {
|
983
|
+
Next();
|
984
|
+
right = ParseAssignmentExpression(contains_in, CHECK);
|
985
|
+
result = factory_->NewBinaryOperation(Token::COMMA, result, right);
|
986
|
+
}
|
987
|
+
return result;
|
988
|
+
}
|
989
|
+
|
990
|
+
// AssignmentExpression
|
991
|
+
// : ConditionalExpression
|
992
|
+
// | LeftHandSideExpression AssignmentOperator AssignmentExpression
|
993
|
+
Expression* ParseAssignmentExpression(bool contains_in, bool *res) {
|
994
|
+
Expression *result = ParseConditionalExpression(contains_in, CHECK);
|
995
|
+
if (!Token::IsAssignOp(token_)) {
|
996
|
+
return result;
|
997
|
+
}
|
998
|
+
if (!result->IsValidLeftHandSide()) {
|
999
|
+
RAISE("invalid left-hand-side in assignment");
|
1000
|
+
}
|
1001
|
+
// section 11.13.1 throwing SyntaxError
|
1002
|
+
if (strict_ &&
|
1003
|
+
result->AsIdentifier()) {
|
1004
|
+
const EvalOrArguments val = IsEvalOrArguments(result->AsIdentifier());
|
1005
|
+
if (val) {
|
1006
|
+
if (val == kEval) {
|
1007
|
+
RAISE("assignment to \"eval\" not allowed in strict code");
|
1008
|
+
} else {
|
1009
|
+
assert(val == kArguments);
|
1010
|
+
RAISE("assignment to \"arguments\" not allowed in strict code");
|
1011
|
+
}
|
1012
|
+
}
|
1013
|
+
}
|
1014
|
+
const Token::Type op = token_;
|
1015
|
+
Next();
|
1016
|
+
Expression *right = ParseAssignmentExpression(contains_in, CHECK);
|
1017
|
+
return factory_->NewAssignment(op, result, right);
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
// ConditionalExpression
|
1021
|
+
// : LogicalOrExpression
|
1022
|
+
// | LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
|
1023
|
+
Expression* ParseConditionalExpression(bool contains_in, bool *res) {
|
1024
|
+
Expression *result;
|
1025
|
+
result = ParseBinaryExpression(contains_in, 9, CHECK);
|
1026
|
+
if (token_ == Token::CONDITIONAL) {
|
1027
|
+
Next();
|
1028
|
+
// see ECMA-262 section 11.12
|
1029
|
+
Expression *left = ParseAssignmentExpression(true, CHECK);
|
1030
|
+
EXPECT(Token::COLON);
|
1031
|
+
Expression *right = ParseAssignmentExpression(contains_in, CHECK);
|
1032
|
+
result = factory_->NewConditionalExpression(result, left, right);
|
1033
|
+
}
|
1034
|
+
return result;
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
// LogicalOrExpression
|
1038
|
+
// : LogicalAndExpression
|
1039
|
+
// | LogicalOrExpression LOGICAL_OR LogicalAndExpression
|
1040
|
+
//
|
1041
|
+
// LogicalAndExpression
|
1042
|
+
// : BitwiseOrExpression
|
1043
|
+
// | LogicalAndExpression LOGICAL_AND BitwiseOrExpression
|
1044
|
+
//
|
1045
|
+
// BitwiseOrExpression
|
1046
|
+
// : BitwiseXorExpression
|
1047
|
+
// | BitwiseOrExpression '|' BitwiseXorExpression
|
1048
|
+
//
|
1049
|
+
// BitwiseXorExpression
|
1050
|
+
// : BitwiseAndExpression
|
1051
|
+
// | BitwiseXorExpression '^' BitwiseAndExpression
|
1052
|
+
//
|
1053
|
+
// BitwiseAndExpression
|
1054
|
+
// : EqualityExpression
|
1055
|
+
// | BitwiseAndExpression '&' EqualityExpression
|
1056
|
+
//
|
1057
|
+
// EqualityExpression
|
1058
|
+
// : RelationalExpression
|
1059
|
+
// | EqualityExpression EQ_STRICT RelationalExpression
|
1060
|
+
// | EqualityExpression NE_STRICT RelationalExpression
|
1061
|
+
// | EqualityExpression EQ RelationalExpression
|
1062
|
+
// | EqualityExpression NE RelationalExpression
|
1063
|
+
//
|
1064
|
+
// RelationalExpression
|
1065
|
+
// : ShiftExpression
|
1066
|
+
// | RelationalExpression LT ShiftExpression
|
1067
|
+
// | RelationalExpression GT ShiftExpression
|
1068
|
+
// | RelationalExpression LTE ShiftExpression
|
1069
|
+
// | RelationalExpression GTE ShiftExpression
|
1070
|
+
// | RelationalExpression INSTANCEOF ShiftExpression
|
1071
|
+
// | RelationalExpression IN ShiftExpression
|
1072
|
+
//
|
1073
|
+
// ShiftExpression
|
1074
|
+
// : AdditiveExpression
|
1075
|
+
// | ShiftExpression SHL AdditiveExpression
|
1076
|
+
// | ShiftExpression SAR AdditiveExpression
|
1077
|
+
// | ShiftExpression SHR AdditiveExpression
|
1078
|
+
//
|
1079
|
+
// AdditiveExpression
|
1080
|
+
// : MultiplicativeExpression
|
1081
|
+
// | AdditiveExpression ADD MultiplicativeExpression
|
1082
|
+
// | AdditiveExpression SUB MultiplicativeExpression
|
1083
|
+
//
|
1084
|
+
// MultiplicativeExpression
|
1085
|
+
// : UnaryExpression
|
1086
|
+
// | MultiplicativeExpression MUL UnaryExpression
|
1087
|
+
// | MultiplicativeExpression DIV UnaryExpression
|
1088
|
+
// | MultiplicativeExpression MOD UnaryExpression
|
1089
|
+
Expression* ParseBinaryExpression(bool contains_in,
|
1090
|
+
int prec, bool *res) {
|
1091
|
+
Expression *left, *right;
|
1092
|
+
Token::Type op;
|
1093
|
+
left = ParseUnaryExpression(CHECK);
|
1094
|
+
// MultiplicativeExpression
|
1095
|
+
while (token_ == Token::MUL ||
|
1096
|
+
token_ == Token::DIV ||
|
1097
|
+
token_ == Token::MOD) {
|
1098
|
+
op = token_;
|
1099
|
+
Next();
|
1100
|
+
right = ParseUnaryExpression(CHECK);
|
1101
|
+
left = ReduceBinaryOperation(op, left, right);
|
1102
|
+
}
|
1103
|
+
if (prec < 1) return left;
|
1104
|
+
|
1105
|
+
// AdditiveExpression
|
1106
|
+
while (token_ == Token::ADD ||
|
1107
|
+
token_ == Token::SUB) {
|
1108
|
+
op = token_;
|
1109
|
+
Next();
|
1110
|
+
right = ParseBinaryExpression(contains_in, 0, CHECK);
|
1111
|
+
left = ReduceBinaryOperation(op, left, right);
|
1112
|
+
}
|
1113
|
+
if (prec < 2) return left;
|
1114
|
+
|
1115
|
+
// ShiftExpression
|
1116
|
+
while (token_ == Token::SHL ||
|
1117
|
+
token_ == Token::SAR ||
|
1118
|
+
token_ == Token::SHR) {
|
1119
|
+
op = token_;
|
1120
|
+
Next();
|
1121
|
+
right = ParseBinaryExpression(contains_in, 1, CHECK);
|
1122
|
+
left = ReduceBinaryOperation(op, left, right);
|
1123
|
+
}
|
1124
|
+
if (prec < 3) return left;
|
1125
|
+
|
1126
|
+
// RelationalExpression
|
1127
|
+
while ((Token::REL_FIRST < token_ &&
|
1128
|
+
token_ < Token::REL_LAST) ||
|
1129
|
+
(contains_in && token_ == Token::IN)) {
|
1130
|
+
op = token_;
|
1131
|
+
Next();
|
1132
|
+
right = ParseBinaryExpression(contains_in, 2, CHECK);
|
1133
|
+
left = factory_->NewBinaryOperation(op, left, right);
|
1134
|
+
}
|
1135
|
+
if (prec < 4) return left;
|
1136
|
+
|
1137
|
+
// EqualityExpression
|
1138
|
+
while (token_ == Token::EQ_STRICT ||
|
1139
|
+
token_ == Token::NE_STRICT ||
|
1140
|
+
token_ == Token::EQ ||
|
1141
|
+
token_ == Token::NE) {
|
1142
|
+
op = token_;
|
1143
|
+
Next();
|
1144
|
+
right = ParseBinaryExpression(contains_in, 3, CHECK);
|
1145
|
+
left = factory_->NewBinaryOperation(op, left, right);
|
1146
|
+
}
|
1147
|
+
if (prec < 5) return left;
|
1148
|
+
|
1149
|
+
// BitwiseAndExpression
|
1150
|
+
while (token_ == Token::BIT_AND) {
|
1151
|
+
op = token_;
|
1152
|
+
Next();
|
1153
|
+
right = ParseBinaryExpression(contains_in, 4, CHECK);
|
1154
|
+
left = ReduceBinaryOperation(op, left, right);
|
1155
|
+
}
|
1156
|
+
if (prec < 6) return left;
|
1157
|
+
|
1158
|
+
// BitwiseXorExpression
|
1159
|
+
while (token_ == Token::BIT_XOR) {
|
1160
|
+
op = token_;
|
1161
|
+
Next();
|
1162
|
+
right = ParseBinaryExpression(contains_in, 5, CHECK);
|
1163
|
+
left = ReduceBinaryOperation(op, left, right);
|
1164
|
+
}
|
1165
|
+
if (prec < 7) return left;
|
1166
|
+
|
1167
|
+
// BitwiseOrExpression
|
1168
|
+
while (token_ == Token::BIT_OR) {
|
1169
|
+
op = token_;
|
1170
|
+
Next();
|
1171
|
+
right = ParseBinaryExpression(contains_in, 6, CHECK);
|
1172
|
+
left = ReduceBinaryOperation(op, left, right);
|
1173
|
+
}
|
1174
|
+
if (prec < 8) return left;
|
1175
|
+
|
1176
|
+
// LogicalAndExpression
|
1177
|
+
while (token_ == Token::LOGICAL_AND) {
|
1178
|
+
op = token_;
|
1179
|
+
Next();
|
1180
|
+
right = ParseBinaryExpression(contains_in, 7, CHECK);
|
1181
|
+
left = factory_->NewBinaryOperation(op, left, right);
|
1182
|
+
}
|
1183
|
+
if (prec < 9) return left;
|
1184
|
+
|
1185
|
+
// LogicalOrExpression
|
1186
|
+
while (token_ == Token::LOGICAL_OR) {
|
1187
|
+
op = token_;
|
1188
|
+
Next();
|
1189
|
+
right = ParseBinaryExpression(contains_in, 8, CHECK);
|
1190
|
+
left = factory_->NewBinaryOperation(op, left, right);
|
1191
|
+
}
|
1192
|
+
return left;
|
1193
|
+
}
|
1194
|
+
|
1195
|
+
Expression* ReduceBinaryOperation(Token::Type op,
|
1196
|
+
Expression* left,
|
1197
|
+
Expression* right) {
|
1198
|
+
if (left->AsNumberLiteral() &&
|
1199
|
+
right->AsNumberLiteral()) {
|
1200
|
+
const double l_val = left->AsNumberLiteral()->value();
|
1201
|
+
const double r_val = right->AsNumberLiteral()->value();
|
1202
|
+
Expression* res;
|
1203
|
+
switch (op) {
|
1204
|
+
case Token::ADD:
|
1205
|
+
res = factory_->NewNumberLiteral(l_val + r_val);
|
1206
|
+
break;
|
1207
|
+
|
1208
|
+
case Token::SUB:
|
1209
|
+
res = factory_->NewNumberLiteral(l_val - r_val);
|
1210
|
+
break;
|
1211
|
+
|
1212
|
+
case Token::MUL:
|
1213
|
+
res = factory_->NewNumberLiteral(l_val * r_val);
|
1214
|
+
break;
|
1215
|
+
|
1216
|
+
case Token::DIV:
|
1217
|
+
res = factory_->NewNumberLiteral(l_val / r_val);
|
1218
|
+
break;
|
1219
|
+
|
1220
|
+
case Token::BIT_OR:
|
1221
|
+
res = factory_->NewNumberLiteral(
|
1222
|
+
DoubleToInt32(l_val) | DoubleToInt32(r_val));
|
1223
|
+
break;
|
1224
|
+
|
1225
|
+
case Token::BIT_AND:
|
1226
|
+
res = factory_->NewNumberLiteral(
|
1227
|
+
DoubleToInt32(l_val) & DoubleToInt32(r_val));
|
1228
|
+
break;
|
1229
|
+
|
1230
|
+
case Token::BIT_XOR:
|
1231
|
+
res = factory_->NewNumberLiteral(
|
1232
|
+
DoubleToInt32(l_val) ^ DoubleToInt32(r_val));
|
1233
|
+
break;
|
1234
|
+
|
1235
|
+
// section 11.7 Bitwise Shift Operators
|
1236
|
+
case Token::SHL: {
|
1237
|
+
const int32_t value = DoubleToInt32(l_val)
|
1238
|
+
<< (DoubleToInt32(r_val) & 0x1f);
|
1239
|
+
res = factory_->NewNumberLiteral(value);
|
1240
|
+
break;
|
1241
|
+
}
|
1242
|
+
|
1243
|
+
case Token::SHR: {
|
1244
|
+
const uint32_t shift = DoubleToInt32(r_val) & 0x1f;
|
1245
|
+
const uint32_t value = DoubleToUInt32(l_val) >> shift;
|
1246
|
+
res = factory_->NewNumberLiteral(value);
|
1247
|
+
break;
|
1248
|
+
}
|
1249
|
+
|
1250
|
+
case Token::SAR: {
|
1251
|
+
uint32_t shift = DoubleToInt32(r_val) & 0x1f;
|
1252
|
+
int32_t value = DoubleToInt32(l_val) >> shift;
|
1253
|
+
res = factory_->NewNumberLiteral(value);
|
1254
|
+
break;
|
1255
|
+
}
|
1256
|
+
|
1257
|
+
default:
|
1258
|
+
res = factory_->NewBinaryOperation(op, left, right);
|
1259
|
+
break;
|
1260
|
+
}
|
1261
|
+
return res;
|
1262
|
+
} else {
|
1263
|
+
return factory_->NewBinaryOperation(op, left, right);
|
1264
|
+
}
|
1265
|
+
}
|
1266
|
+
|
1267
|
+
// UnaryExpression
|
1268
|
+
// : PostfixExpression
|
1269
|
+
// | DELETE UnaryExpression
|
1270
|
+
// | VOID UnaryExpression
|
1271
|
+
// | TYPEOF UnaryExpression
|
1272
|
+
// | INC UnaryExpression
|
1273
|
+
// | DEC UnaryExpression
|
1274
|
+
// | '+' UnaryExpression
|
1275
|
+
// | '-' UnaryExpression
|
1276
|
+
// | '~' UnaryExpression
|
1277
|
+
// | '!' UnaryExpression
|
1278
|
+
Expression* ParseUnaryExpression(bool *res) {
|
1279
|
+
Expression *result, *expr;
|
1280
|
+
const Token::Type op = token_;
|
1281
|
+
switch (token_) {
|
1282
|
+
case Token::VOID:
|
1283
|
+
case Token::NOT:
|
1284
|
+
case Token::TYPEOF:
|
1285
|
+
Next();
|
1286
|
+
expr = ParseUnaryExpression(CHECK);
|
1287
|
+
result = factory_->NewUnaryOperation(op, expr);
|
1288
|
+
break;
|
1289
|
+
|
1290
|
+
case Token::DELETE:
|
1291
|
+
// a strict mode restriction in sec 11.4.1
|
1292
|
+
// raise SyntaxError when target is direct reference to a variable,
|
1293
|
+
// function argument, or function name
|
1294
|
+
Next();
|
1295
|
+
expr = ParseUnaryExpression(CHECK);
|
1296
|
+
if (strict_ &&
|
1297
|
+
expr->AsIdentifier()) {
|
1298
|
+
RAISE("delete to direct identifier not allowed in strict code");
|
1299
|
+
}
|
1300
|
+
result = factory_->NewUnaryOperation(op, expr);
|
1301
|
+
break;
|
1302
|
+
|
1303
|
+
case Token::BIT_NOT:
|
1304
|
+
Next();
|
1305
|
+
expr = ParseUnaryExpression(CHECK);
|
1306
|
+
if (expr->AsNumberLiteral()) {
|
1307
|
+
result = factory_->NewNumberLiteral(
|
1308
|
+
~DoubleToInt32(expr->AsNumberLiteral()->value()));
|
1309
|
+
} else {
|
1310
|
+
result = factory_->NewUnaryOperation(op, expr);
|
1311
|
+
}
|
1312
|
+
break;
|
1313
|
+
|
1314
|
+
case Token::ADD:
|
1315
|
+
Next();
|
1316
|
+
expr = ParseUnaryExpression(CHECK);
|
1317
|
+
if (expr->AsNumberLiteral()) {
|
1318
|
+
result = expr;
|
1319
|
+
} else {
|
1320
|
+
result = factory_->NewUnaryOperation(op, expr);
|
1321
|
+
}
|
1322
|
+
break;
|
1323
|
+
|
1324
|
+
case Token::SUB:
|
1325
|
+
Next();
|
1326
|
+
expr = ParseUnaryExpression(CHECK);
|
1327
|
+
if (expr->AsNumberLiteral()) {
|
1328
|
+
result = factory_->NewNumberLiteral(
|
1329
|
+
-(expr->AsNumberLiteral()->value()));
|
1330
|
+
} else {
|
1331
|
+
result = factory_->NewUnaryOperation(op, expr);
|
1332
|
+
}
|
1333
|
+
break;
|
1334
|
+
|
1335
|
+
case Token::INC:
|
1336
|
+
case Token::DEC:
|
1337
|
+
Next();
|
1338
|
+
expr = ParseMemberExpression(true, CHECK);
|
1339
|
+
if (!expr->IsValidLeftHandSide()) {
|
1340
|
+
RAISE("invalid left-hand-side in prefix expression");
|
1341
|
+
}
|
1342
|
+
// section 11.4.4, 11.4.5 throwing SyntaxError
|
1343
|
+
if (strict_ &&
|
1344
|
+
expr->AsIdentifier()) {
|
1345
|
+
const EvalOrArguments val = IsEvalOrArguments(expr->AsIdentifier());
|
1346
|
+
if (val) {
|
1347
|
+
if (val == kEval) {
|
1348
|
+
RAISE("prefix expression to \"eval\" "
|
1349
|
+
"not allowed in strict code");
|
1350
|
+
} else {
|
1351
|
+
assert(val == kArguments);
|
1352
|
+
RAISE("prefix expression to \"arguments\" "
|
1353
|
+
"not allowed in strict code");
|
1354
|
+
}
|
1355
|
+
}
|
1356
|
+
}
|
1357
|
+
result = factory_->NewUnaryOperation(op, expr);
|
1358
|
+
break;
|
1359
|
+
|
1360
|
+
default:
|
1361
|
+
result = ParsePostfixExpression(CHECK);
|
1362
|
+
break;
|
1363
|
+
}
|
1364
|
+
return result;
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
// PostfixExpression
|
1368
|
+
// : LeftHandSideExpression
|
1369
|
+
// | LeftHandSideExpression INCREMENT
|
1370
|
+
// | LeftHandSideExpression DECREMENT
|
1371
|
+
Expression* ParsePostfixExpression(bool *res) {
|
1372
|
+
Expression *expr;
|
1373
|
+
expr = ParseMemberExpression(true, CHECK);
|
1374
|
+
if (!lexer_.has_line_terminator_before_next() &&
|
1375
|
+
(token_ == Token::INC || token_ == Token::DEC)) {
|
1376
|
+
if (!expr->IsValidLeftHandSide()) {
|
1377
|
+
RAISE("invalid left-hand-side in postfix expression");
|
1378
|
+
}
|
1379
|
+
// section 11.3.1, 11.3.2 throwing SyntaxError
|
1380
|
+
if (strict_ &&
|
1381
|
+
expr->AsIdentifier()) {
|
1382
|
+
const EvalOrArguments val = IsEvalOrArguments(expr->AsIdentifier());
|
1383
|
+
if (val) {
|
1384
|
+
if (val == kEval) {
|
1385
|
+
RAISE("postfix expression to \"eval\" not allowed in strict code");
|
1386
|
+
} else {
|
1387
|
+
assert(val == kArguments);
|
1388
|
+
RAISE("postfix expression to \"arguments\" "
|
1389
|
+
"not allowed in strict code");
|
1390
|
+
}
|
1391
|
+
}
|
1392
|
+
}
|
1393
|
+
expr = factory_->NewPostfixExpression(token_, expr);
|
1394
|
+
Next();
|
1395
|
+
}
|
1396
|
+
return expr;
|
1397
|
+
}
|
1398
|
+
|
1399
|
+
// LeftHandSideExpression
|
1400
|
+
// : NewExpression
|
1401
|
+
// | CallExpression
|
1402
|
+
//
|
1403
|
+
// NewExpression
|
1404
|
+
// : MemberExpression
|
1405
|
+
// | NEW NewExpression
|
1406
|
+
//
|
1407
|
+
// MemberExpression
|
1408
|
+
// : PrimaryExpression
|
1409
|
+
// | FunctionExpression
|
1410
|
+
// | MemberExpression '[' Expression ']'
|
1411
|
+
// | NEW MemberExpression Arguments
|
1412
|
+
Expression* ParseMemberExpression(bool allow_call, bool *res) {
|
1413
|
+
Expression *expr;
|
1414
|
+
if (token_ != Token::NEW) {
|
1415
|
+
if (token_ == Token::FUNCTION) {
|
1416
|
+
// FunctionExpression
|
1417
|
+
Next();
|
1418
|
+
expr = ParseFunctionLiteral(FunctionLiteral::EXPRESSION,
|
1419
|
+
FunctionLiteral::GENERAL, true, CHECK);
|
1420
|
+
} else {
|
1421
|
+
expr = ParsePrimaryExpression(CHECK);
|
1422
|
+
}
|
1423
|
+
} else {
|
1424
|
+
Next();
|
1425
|
+
Expression *target = ParseMemberExpression(false, CHECK);
|
1426
|
+
ConstructorCall *con = factory_->NewConstructorCall(target);
|
1427
|
+
if (token_ == Token::LPAREN) {
|
1428
|
+
ParseArguments(con, CHECK);
|
1429
|
+
}
|
1430
|
+
expr = con;
|
1431
|
+
}
|
1432
|
+
FunctionCall *funcall;
|
1433
|
+
while (true) {
|
1434
|
+
switch (token_) {
|
1435
|
+
case Token::LBRACK: {
|
1436
|
+
Next();
|
1437
|
+
Expression* index = ParseExpression(true, CHECK);
|
1438
|
+
expr = factory_->NewIndexAccess(expr, index);
|
1439
|
+
EXPECT(Token::RBRACK);
|
1440
|
+
break;
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
case Token::PERIOD: {
|
1444
|
+
Next(Lexer::kIgnoreReservedWords); // IDENTIFIERNAME
|
1445
|
+
IS(Token::IDENTIFIER);
|
1446
|
+
Identifier* ident = factory_->NewIdentifier(lexer_.Buffer());
|
1447
|
+
Next();
|
1448
|
+
expr = factory_->NewIdentifierAccess(expr, ident);
|
1449
|
+
break;
|
1450
|
+
}
|
1451
|
+
|
1452
|
+
case Token::LPAREN:
|
1453
|
+
if (allow_call) {
|
1454
|
+
funcall = factory_->NewFunctionCall(expr);
|
1455
|
+
ParseArguments(funcall, CHECK);
|
1456
|
+
expr = funcall;
|
1457
|
+
} else {
|
1458
|
+
return expr;
|
1459
|
+
}
|
1460
|
+
break;
|
1461
|
+
|
1462
|
+
default:
|
1463
|
+
return expr;
|
1464
|
+
}
|
1465
|
+
}
|
1466
|
+
}
|
1467
|
+
|
1468
|
+
// PrimaryExpression
|
1469
|
+
// : THIS
|
1470
|
+
// | IDENTIFIER
|
1471
|
+
// | Literal
|
1472
|
+
// | ArrayLiteral
|
1473
|
+
// | ObjectLiteral
|
1474
|
+
// | '(' Expression ')'
|
1475
|
+
//
|
1476
|
+
// Literal
|
1477
|
+
// : NULL_LITERAL
|
1478
|
+
// | TRUE_LITERAL
|
1479
|
+
// | FALSE_LITERAL
|
1480
|
+
// | NUMBER
|
1481
|
+
// | STRING
|
1482
|
+
// | REGEXP
|
1483
|
+
Expression* ParsePrimaryExpression(bool *res) {
|
1484
|
+
Expression *result = NULL;
|
1485
|
+
switch (token_) {
|
1486
|
+
case Token::THIS:
|
1487
|
+
result = factory_->NewThisLiteral();
|
1488
|
+
Next();
|
1489
|
+
break;
|
1490
|
+
|
1491
|
+
case Token::IDENTIFIER:
|
1492
|
+
result = factory_->NewIdentifier(lexer_.Buffer());
|
1493
|
+
Next();
|
1494
|
+
break;
|
1495
|
+
|
1496
|
+
case Token::NULL_LITERAL:
|
1497
|
+
result = factory_->NewNullLiteral();
|
1498
|
+
Next();
|
1499
|
+
break;
|
1500
|
+
|
1501
|
+
case Token::TRUE_LITERAL:
|
1502
|
+
result = factory_->NewTrueLiteral();
|
1503
|
+
Next();
|
1504
|
+
break;
|
1505
|
+
|
1506
|
+
case Token::FALSE_LITERAL:
|
1507
|
+
result = factory_->NewFalseLiteral();
|
1508
|
+
Next();
|
1509
|
+
break;
|
1510
|
+
|
1511
|
+
case Token::NUMBER:
|
1512
|
+
// section 7.8.3
|
1513
|
+
// strict mode forbids Octal Digits Literal
|
1514
|
+
if (strict_ && lexer_.NumericType() == Lexer::OCTAL) {
|
1515
|
+
RAISE("octal integer literal not allowed in strict code");
|
1516
|
+
}
|
1517
|
+
result = factory_->NewNumberLiteral(lexer_.Numeric());
|
1518
|
+
Next();
|
1519
|
+
break;
|
1520
|
+
|
1521
|
+
case Token::STRING: {
|
1522
|
+
const Lexer::State state = lexer_.StringEscapeType();
|
1523
|
+
if (strict_ && state == Lexer::OCTAL) {
|
1524
|
+
RAISE("octal excape sequence not allowed in strict code");
|
1525
|
+
}
|
1526
|
+
if (state == Lexer::NONE) {
|
1527
|
+
result = factory_->NewDirectivable(lexer_.Buffer());
|
1528
|
+
} else {
|
1529
|
+
result = factory_->NewStringLiteral(lexer_.Buffer());
|
1530
|
+
}
|
1531
|
+
Next();
|
1532
|
+
break;
|
1533
|
+
}
|
1534
|
+
|
1535
|
+
case Token::DIV:
|
1536
|
+
result = ParseRegExpLiteral(false, CHECK);
|
1537
|
+
break;
|
1538
|
+
|
1539
|
+
case Token::ASSIGN_DIV:
|
1540
|
+
result = ParseRegExpLiteral(true, CHECK);
|
1541
|
+
break;
|
1542
|
+
|
1543
|
+
case Token::LBRACK:
|
1544
|
+
result = ParseArrayLiteral(CHECK);
|
1545
|
+
break;
|
1546
|
+
|
1547
|
+
case Token::LBRACE:
|
1548
|
+
result = ParseObjectLiteral(CHECK);
|
1549
|
+
break;
|
1550
|
+
|
1551
|
+
case Token::LPAREN:
|
1552
|
+
Next();
|
1553
|
+
result = ParseExpression(true, CHECK);
|
1554
|
+
EXPECT(Token::RPAREN);
|
1555
|
+
break;
|
1556
|
+
|
1557
|
+
default:
|
1558
|
+
RAISE("invalid primary expression token");
|
1559
|
+
break;
|
1560
|
+
}
|
1561
|
+
return result;
|
1562
|
+
}
|
1563
|
+
|
1564
|
+
// Arguments
|
1565
|
+
// : '(' ')'
|
1566
|
+
// | '(' ArgumentList ')'
|
1567
|
+
//
|
1568
|
+
// ArgumentList
|
1569
|
+
// : AssignmentExpression
|
1570
|
+
// | ArgumentList ',' AssignmentExpression
|
1571
|
+
Call* ParseArguments(Call* func, bool *res) {
|
1572
|
+
Expression *expr;
|
1573
|
+
Next();
|
1574
|
+
while (token_ != Token::RPAREN) {
|
1575
|
+
expr = ParseAssignmentExpression(true, CHECK);
|
1576
|
+
func->AddArgument(expr);
|
1577
|
+
if (token_ != Token::RPAREN) {
|
1578
|
+
EXPECT(Token::COMMA);
|
1579
|
+
}
|
1580
|
+
}
|
1581
|
+
Next();
|
1582
|
+
return func;
|
1583
|
+
}
|
1584
|
+
|
1585
|
+
Expression* ParseRegExpLiteral(bool contains_eq, bool *res) {
|
1586
|
+
if (lexer_.ScanRegExpLiteral(contains_eq)) {
|
1587
|
+
RegExpLiteral* expr;
|
1588
|
+
const std::vector<uc16> content(lexer_.Buffer());
|
1589
|
+
if (!lexer_.ScanRegExpFlags()) {
|
1590
|
+
RAISE("invalid regular expression flag");
|
1591
|
+
} else {
|
1592
|
+
expr = factory_->NewRegExpLiteral(content, lexer_.Buffer());
|
1593
|
+
if (!expr) {
|
1594
|
+
RAISE("invalid regular expression");
|
1595
|
+
}
|
1596
|
+
}
|
1597
|
+
Next();
|
1598
|
+
return expr;
|
1599
|
+
} else {
|
1600
|
+
RAISE("invalid regular expression");
|
1601
|
+
}
|
1602
|
+
}
|
1603
|
+
|
1604
|
+
// ArrayLiteral
|
1605
|
+
// : '[' Elision_opt ']'
|
1606
|
+
// | '[' ElementList ']'
|
1607
|
+
// | '[' ElementList ',' Elision_opt ']'
|
1608
|
+
//
|
1609
|
+
// ElementList
|
1610
|
+
// : Elision_opt AssignmentExpression
|
1611
|
+
// | ElementList ',' Elision_opt AssignmentExpression
|
1612
|
+
//
|
1613
|
+
// Elision
|
1614
|
+
// : ','
|
1615
|
+
// | Elision ','
|
1616
|
+
Expression* ParseArrayLiteral(bool *res) {
|
1617
|
+
ArrayLiteral *array = factory_->NewArrayLiteral();
|
1618
|
+
Expression *expr;
|
1619
|
+
Next();
|
1620
|
+
while (token_ != Token::RBRACK) {
|
1621
|
+
if (token_ == Token::COMMA) {
|
1622
|
+
// when Token::COMMA, only increment length
|
1623
|
+
array->AddItem(NULL);
|
1624
|
+
} else {
|
1625
|
+
expr = ParseAssignmentExpression(true, CHECK);
|
1626
|
+
array->AddItem(expr);
|
1627
|
+
}
|
1628
|
+
if (token_ != Token::RBRACK) {
|
1629
|
+
EXPECT(Token::COMMA);
|
1630
|
+
}
|
1631
|
+
}
|
1632
|
+
Next();
|
1633
|
+
return array;
|
1634
|
+
}
|
1635
|
+
|
1636
|
+
|
1637
|
+
|
1638
|
+
// ObjectLiteral
|
1639
|
+
// : '{' PropertyNameAndValueList_opt '}'
|
1640
|
+
//
|
1641
|
+
// PropertyNameAndValueList_opt
|
1642
|
+
// :
|
1643
|
+
// | PropertyNameAndValueList
|
1644
|
+
//
|
1645
|
+
// PropertyNameAndValueList
|
1646
|
+
// : PropertyAssignment
|
1647
|
+
// | PropertyNameAndValueList ',' PropertyAssignment
|
1648
|
+
//
|
1649
|
+
// PropertyAssignment
|
1650
|
+
// : PropertyName ':' AssignmentExpression
|
1651
|
+
// | 'get' PropertyName '(' ')' '{' FunctionBody '}'
|
1652
|
+
// | 'set' PropertyName '(' PropertySetParameterList ')' '{' FunctionBody '}'
|
1653
|
+
//
|
1654
|
+
// PropertyName
|
1655
|
+
// : IDENTIFIER
|
1656
|
+
// | STRING
|
1657
|
+
// | NUMBER
|
1658
|
+
//
|
1659
|
+
// PropertySetParameterList
|
1660
|
+
// : IDENTIFIER
|
1661
|
+
Expression* ParseObjectLiteral(bool *res) {
|
1662
|
+
typedef std::tr1::unordered_map<IdentifierKey, int> ObjectMap;
|
1663
|
+
ObjectLiteral *object = factory_->NewObjectLiteral();
|
1664
|
+
ObjectMap map;
|
1665
|
+
Expression *expr;
|
1666
|
+
Identifier *ident;
|
1667
|
+
|
1668
|
+
// IDENTIFIERNAME
|
1669
|
+
Next(Lexer::kIgnoreReservedWordsAndIdentifyGetterOrSetter);
|
1670
|
+
while (token_ != Token::RBRACE) {
|
1671
|
+
if (token_ == Token::GET || token_ == Token::SET) {
|
1672
|
+
const bool is_get = token_ == Token::GET;
|
1673
|
+
// this is getter or setter or usual prop
|
1674
|
+
Next(Lexer::kIgnoreReservedWords); // IDENTIFIERNAME
|
1675
|
+
if (token_ == Token::COLON) {
|
1676
|
+
// property
|
1677
|
+
ident = factory_->NewIdentifier(
|
1678
|
+
is_get ? ParserData::kGet : ParserData::kSet);
|
1679
|
+
Next();
|
1680
|
+
expr = ParseAssignmentExpression(true, CHECK);
|
1681
|
+
object->AddDataProperty(ident, expr);
|
1682
|
+
typename ObjectMap::iterator it = map.find(ident);
|
1683
|
+
if (it == map.end()) {
|
1684
|
+
map.insert(std::make_pair(ident, ObjectLiteral::DATA));
|
1685
|
+
} else {
|
1686
|
+
if (it->second != ObjectLiteral::DATA) {
|
1687
|
+
RAISE("accessor property and data property "
|
1688
|
+
"exist with the same name");
|
1689
|
+
} else {
|
1690
|
+
if (strict_) {
|
1691
|
+
RAISE("multiple data property assignments "
|
1692
|
+
"with the same name not allowed in strict code");
|
1693
|
+
}
|
1694
|
+
}
|
1695
|
+
}
|
1696
|
+
} else {
|
1697
|
+
// getter or setter
|
1698
|
+
if (token_ == Token::IDENTIFIER ||
|
1699
|
+
token_ == Token::STRING ||
|
1700
|
+
token_ == Token::NUMBER) {
|
1701
|
+
if (token_ == Token::NUMBER) {
|
1702
|
+
ident = factory_->NewIdentifier(lexer_.Buffer8());
|
1703
|
+
} else {
|
1704
|
+
ident = factory_->NewIdentifier(lexer_.Buffer());
|
1705
|
+
}
|
1706
|
+
Next();
|
1707
|
+
typename ObjectLiteral::PropertyDescriptorType type =
|
1708
|
+
(is_get) ? ObjectLiteral::GET : ObjectLiteral::SET;
|
1709
|
+
expr = ParseFunctionLiteral(
|
1710
|
+
FunctionLiteral::EXPRESSION,
|
1711
|
+
(is_get) ? FunctionLiteral::GETTER : FunctionLiteral::SETTER,
|
1712
|
+
false, CHECK);
|
1713
|
+
object->AddAccessor(type, ident, expr);
|
1714
|
+
typename ObjectMap::iterator it = map.find(ident);
|
1715
|
+
if (it == map.end()) {
|
1716
|
+
map.insert(std::make_pair(ident, type));
|
1717
|
+
} else if (it->second & (ObjectLiteral::DATA | type)) {
|
1718
|
+
if (it->second & ObjectLiteral::DATA) {
|
1719
|
+
RAISE("data property and accessor property "
|
1720
|
+
"exist with the same name");
|
1721
|
+
} else {
|
1722
|
+
RAISE("multiple same accessor properties "
|
1723
|
+
"exist with the same name");
|
1724
|
+
}
|
1725
|
+
} else {
|
1726
|
+
it->second |= type;
|
1727
|
+
}
|
1728
|
+
} else {
|
1729
|
+
RAISE("invalid property name");
|
1730
|
+
}
|
1731
|
+
}
|
1732
|
+
} else if (token_ == Token::IDENTIFIER ||
|
1733
|
+
token_ == Token::STRING ||
|
1734
|
+
token_ == Token::NUMBER) {
|
1735
|
+
ident = factory_->NewIdentifier(lexer_.Buffer());
|
1736
|
+
Next();
|
1737
|
+
EXPECT(Token::COLON);
|
1738
|
+
expr = ParseAssignmentExpression(true, CHECK);
|
1739
|
+
object->AddDataProperty(ident, expr);
|
1740
|
+
typename ObjectMap::iterator it = map.find(ident);
|
1741
|
+
if (it == map.end()) {
|
1742
|
+
map.insert(std::make_pair(ident, ObjectLiteral::DATA));
|
1743
|
+
} else {
|
1744
|
+
if (it->second != ObjectLiteral::DATA) {
|
1745
|
+
RAISE("accessor property and data property "
|
1746
|
+
"exist with the same name");
|
1747
|
+
} else {
|
1748
|
+
if (strict_) {
|
1749
|
+
RAISE("multiple data property assignments "
|
1750
|
+
"with the same name not allowed in strict code");
|
1751
|
+
}
|
1752
|
+
}
|
1753
|
+
}
|
1754
|
+
} else {
|
1755
|
+
RAISE("invalid property name");
|
1756
|
+
}
|
1757
|
+
|
1758
|
+
if (token_ != Token::RBRACE) {
|
1759
|
+
IS(Token::COMMA);
|
1760
|
+
// IDENTIFIERNAME
|
1761
|
+
Next(Lexer::kIgnoreReservedWordsAndIdentifyGetterOrSetter);
|
1762
|
+
}
|
1763
|
+
}
|
1764
|
+
Next();
|
1765
|
+
return object;
|
1766
|
+
}
|
1767
|
+
|
1768
|
+
FunctionLiteral* ParseFunctionLiteral(
|
1769
|
+
typename FunctionLiteral::DeclType decl_type,
|
1770
|
+
typename FunctionLiteral::ArgType arg_type,
|
1771
|
+
bool allow_identifier,
|
1772
|
+
bool *res) {
|
1773
|
+
// IDENTIFIER
|
1774
|
+
// IDENTIFIER_opt
|
1775
|
+
std::tr1::unordered_set<IdentifierKey> param_set;
|
1776
|
+
std::size_t throw_error_if_strict_code_line = 0;
|
1777
|
+
enum {
|
1778
|
+
kDetectNone = 0,
|
1779
|
+
kDetectEvalName,
|
1780
|
+
kDetectArgumentsName,
|
1781
|
+
kDetectEvalParameter,
|
1782
|
+
kDetectArgumentsParameter,
|
1783
|
+
kDetectDuplicateParameter
|
1784
|
+
} throw_error_if_strict_code = kDetectNone;
|
1785
|
+
|
1786
|
+
FunctionLiteral *literal = factory_->NewFunctionLiteral(decl_type);
|
1787
|
+
literal->set_strict(strict_);
|
1788
|
+
if (allow_identifier && token_ == Token::IDENTIFIER) {
|
1789
|
+
Identifier* const name = factory_->NewIdentifier(lexer_.Buffer());
|
1790
|
+
literal->SetName(name);
|
1791
|
+
const EvalOrArguments val = IsEvalOrArguments(name);
|
1792
|
+
if (val) {
|
1793
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1794
|
+
kDetectEvalName : kDetectArgumentsName;
|
1795
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1796
|
+
}
|
1797
|
+
Next();
|
1798
|
+
}
|
1799
|
+
const ScopeSwitcher switcher(this, literal->scope());
|
1800
|
+
literal->set_start_position(lexer_.pos() - 2);
|
1801
|
+
|
1802
|
+
// '(' FormalParameterList_opt ')'
|
1803
|
+
EXPECT(Token::LPAREN);
|
1804
|
+
|
1805
|
+
if (arg_type == FunctionLiteral::GETTER) {
|
1806
|
+
// if getter, parameter count is 0
|
1807
|
+
EXPECT(Token::RPAREN);
|
1808
|
+
} else if (arg_type == FunctionLiteral::SETTER) {
|
1809
|
+
// if setter, parameter count is 1
|
1810
|
+
IS(Token::IDENTIFIER);
|
1811
|
+
Identifier* const ident = factory_->NewIdentifier(lexer_.Buffer());
|
1812
|
+
if (!throw_error_if_strict_code) {
|
1813
|
+
const EvalOrArguments val = IsEvalOrArguments(ident);
|
1814
|
+
if (val) {
|
1815
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1816
|
+
kDetectEvalParameter : kDetectArgumentsParameter;
|
1817
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1818
|
+
}
|
1819
|
+
}
|
1820
|
+
literal->AddParameter(ident);
|
1821
|
+
Next();
|
1822
|
+
EXPECT(Token::RPAREN);
|
1823
|
+
} else {
|
1824
|
+
while (token_ != Token::RPAREN) {
|
1825
|
+
IS(Token::IDENTIFIER);
|
1826
|
+
Identifier* const ident = factory_->NewIdentifier(lexer_.Buffer());
|
1827
|
+
if (!throw_error_if_strict_code) {
|
1828
|
+
const EvalOrArguments val = IsEvalOrArguments(ident);
|
1829
|
+
if (val) {
|
1830
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1831
|
+
kDetectEvalParameter : kDetectArgumentsParameter;
|
1832
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1833
|
+
}
|
1834
|
+
if ((!throw_error_if_strict_code) &&
|
1835
|
+
(param_set.find(ident) != param_set.end())) {
|
1836
|
+
throw_error_if_strict_code = kDetectDuplicateParameter;
|
1837
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1838
|
+
}
|
1839
|
+
}
|
1840
|
+
literal->AddParameter(ident);
|
1841
|
+
param_set.insert(ident);
|
1842
|
+
Next();
|
1843
|
+
if (token_ != Token::RPAREN) {
|
1844
|
+
EXPECT(Token::COMMA);
|
1845
|
+
}
|
1846
|
+
}
|
1847
|
+
Next();
|
1848
|
+
}
|
1849
|
+
|
1850
|
+
// '{' FunctionBody '}'
|
1851
|
+
//
|
1852
|
+
// FunctionBody
|
1853
|
+
// :
|
1854
|
+
// | SourceElements
|
1855
|
+
EXPECT(Token::LBRACE);
|
1856
|
+
|
1857
|
+
ParseSourceElements(Token::RBRACE, literal, CHECK);
|
1858
|
+
if (strict_ || literal->strict()) {
|
1859
|
+
// section 13.1
|
1860
|
+
// Strict Mode Restrictions
|
1861
|
+
switch (throw_error_if_strict_code) {
|
1862
|
+
case kDetectNone:
|
1863
|
+
break;
|
1864
|
+
case kDetectEvalName:
|
1865
|
+
RAISE_WITH_NUMBER(
|
1866
|
+
"function name \"eval\" not allowed in strict code",
|
1867
|
+
throw_error_if_strict_code_line);
|
1868
|
+
break;
|
1869
|
+
case kDetectArgumentsName:
|
1870
|
+
RAISE_WITH_NUMBER(
|
1871
|
+
"function name \"arguments\" not allowed in strict code",
|
1872
|
+
throw_error_if_strict_code_line);
|
1873
|
+
break;
|
1874
|
+
case kDetectEvalParameter:
|
1875
|
+
RAISE_WITH_NUMBER(
|
1876
|
+
"parameter \"eval\" not allowed in strict code",
|
1877
|
+
throw_error_if_strict_code_line);
|
1878
|
+
break;
|
1879
|
+
case kDetectArgumentsParameter:
|
1880
|
+
RAISE_WITH_NUMBER(
|
1881
|
+
"parameter \"arguments\" not allowed in strict code",
|
1882
|
+
throw_error_if_strict_code_line);
|
1883
|
+
break;
|
1884
|
+
case kDetectDuplicateParameter:
|
1885
|
+
RAISE_WITH_NUMBER(
|
1886
|
+
"duplicate parameter not allowed in strict code",
|
1887
|
+
throw_error_if_strict_code_line);
|
1888
|
+
break;
|
1889
|
+
}
|
1890
|
+
}
|
1891
|
+
literal->set_end_position(lexer_.pos() - 2);
|
1892
|
+
literal->SubStringSource(lexer_.source());
|
1893
|
+
Next();
|
1894
|
+
return literal;
|
1895
|
+
}
|
1896
|
+
|
1897
|
+
bool ContainsLabel(const Identifiers* const labels,
|
1898
|
+
const Identifier * const label) const {
|
1899
|
+
assert(label != NULL);
|
1900
|
+
if (labels) {
|
1901
|
+
const SpaceUString& value = label->value();
|
1902
|
+
for (typename Identifiers::const_iterator it = labels->begin(),
|
1903
|
+
last = labels->end();
|
1904
|
+
it != last; ++it) {
|
1905
|
+
if ((*it)->value() == value) {
|
1906
|
+
return true;
|
1907
|
+
}
|
1908
|
+
}
|
1909
|
+
}
|
1910
|
+
return false;
|
1911
|
+
}
|
1912
|
+
|
1913
|
+
bool TargetsContainsLabel(const Identifier* const label) const {
|
1914
|
+
assert(label != NULL);
|
1915
|
+
for (Target* target = target_;
|
1916
|
+
target != NULL;
|
1917
|
+
target = target->previous()) {
|
1918
|
+
if (ContainsLabel(target->node()->labels(), label)) {
|
1919
|
+
return true;
|
1920
|
+
}
|
1921
|
+
}
|
1922
|
+
return false;
|
1923
|
+
}
|
1924
|
+
|
1925
|
+
BreakableStatement* LookupBreakableTarget(
|
1926
|
+
const Identifier* const label) const {
|
1927
|
+
assert(label != NULL);
|
1928
|
+
for (const Target* target = target_;
|
1929
|
+
target != NULL;
|
1930
|
+
target = target->previous()) {
|
1931
|
+
if (ContainsLabel(target->node()->labels(), label)) {
|
1932
|
+
return target->node();
|
1933
|
+
}
|
1934
|
+
}
|
1935
|
+
return NULL;
|
1936
|
+
}
|
1937
|
+
|
1938
|
+
BreakableStatement* LookupBreakableTarget() const {
|
1939
|
+
for (const Target* target = target_;
|
1940
|
+
target != NULL;
|
1941
|
+
target = target->previous()) {
|
1942
|
+
if (target->node()->AsAnonymousBreakableStatement()) {
|
1943
|
+
return target->node();
|
1944
|
+
}
|
1945
|
+
}
|
1946
|
+
return NULL;
|
1947
|
+
}
|
1948
|
+
|
1949
|
+
IterationStatement* LookupContinuableTarget(
|
1950
|
+
const Identifier* const label) const {
|
1951
|
+
assert(label != NULL);
|
1952
|
+
for (const Target* target = target_;
|
1953
|
+
target != NULL;
|
1954
|
+
target = target->previous()) {
|
1955
|
+
IterationStatement* const iter = target->node()->AsIterationStatement();
|
1956
|
+
if (iter && ContainsLabel(iter->labels(), label)) {
|
1957
|
+
return iter;
|
1958
|
+
}
|
1959
|
+
}
|
1960
|
+
return NULL;
|
1961
|
+
}
|
1962
|
+
|
1963
|
+
IterationStatement* LookupContinuableTarget() const {
|
1964
|
+
for (const Target* target = target_;
|
1965
|
+
target != NULL;
|
1966
|
+
target = target->previous()) {
|
1967
|
+
IterationStatement* const iter = target->node()->AsIterationStatement();
|
1968
|
+
if (iter) {
|
1969
|
+
return iter;
|
1970
|
+
}
|
1971
|
+
}
|
1972
|
+
return NULL;
|
1973
|
+
}
|
1974
|
+
|
1975
|
+
inline void SetErrorHeader() {
|
1976
|
+
SetErrorHeader(lexer_.line_number());
|
1977
|
+
}
|
1978
|
+
|
1979
|
+
void SetErrorHeader(std::size_t line) {
|
1980
|
+
std::tr1::array<char, 40> buf;
|
1981
|
+
error_.append(lexer_.filename());
|
1982
|
+
int num = std::snprintf(buf.data(), buf.size(),
|
1983
|
+
":%lu: SyntaxError: ",
|
1984
|
+
static_cast<unsigned long>(line)); // NOLINT
|
1985
|
+
error_.append(buf.data(), num);
|
1986
|
+
}
|
1987
|
+
|
1988
|
+
void ReportUnexpectedToken(Token::Type expected_token) {
|
1989
|
+
SetErrorHeader();
|
1990
|
+
switch (token_) {
|
1991
|
+
case Token::STRING:
|
1992
|
+
error_.append("unexpected string");
|
1993
|
+
break;
|
1994
|
+
case Token::NUMBER:
|
1995
|
+
error_.append("unexpected number");
|
1996
|
+
break;
|
1997
|
+
case Token::IDENTIFIER:
|
1998
|
+
error_.append("unexpected identifier");
|
1999
|
+
break;
|
2000
|
+
case Token::EOS:
|
2001
|
+
error_.append("unexpected EOS");
|
2002
|
+
break;
|
2003
|
+
case Token::ILLEGAL: {
|
2004
|
+
error_.append("illegal character");
|
2005
|
+
break;
|
2006
|
+
}
|
2007
|
+
default: {
|
2008
|
+
error_.append("unexpected token ");
|
2009
|
+
error_.append(Token::ToString(token_));
|
2010
|
+
break;
|
2011
|
+
}
|
2012
|
+
}
|
2013
|
+
}
|
2014
|
+
|
2015
|
+
bool ExpectSemicolon(bool *res) {
|
2016
|
+
if (token_ == Token::SEMICOLON) {
|
2017
|
+
Next();
|
2018
|
+
return true;
|
2019
|
+
}
|
2020
|
+
if (lexer_.has_line_terminator_before_next() ||
|
2021
|
+
token_ == Token::RBRACE ||
|
2022
|
+
token_ == Token::EOS ) {
|
2023
|
+
return true;
|
2024
|
+
}
|
2025
|
+
UNEXPECT(token_);
|
2026
|
+
}
|
2027
|
+
|
2028
|
+
inline Lexer& lexer() {
|
2029
|
+
return lexer_;
|
2030
|
+
}
|
2031
|
+
inline Token::Type Next(Lexer::LexType type = Lexer::kIdentifyReservedWords) {
|
2032
|
+
return token_ = lexer_.Next(
|
2033
|
+
type | (strict_ ? Lexer::kStrict : Lexer::kClear));
|
2034
|
+
}
|
2035
|
+
inline Token::Type Peek() const {
|
2036
|
+
return token_;
|
2037
|
+
}
|
2038
|
+
inline Scope* scope() const {
|
2039
|
+
return scope_;
|
2040
|
+
}
|
2041
|
+
inline void set_scope(Scope* scope) {
|
2042
|
+
scope_ = scope;
|
2043
|
+
}
|
2044
|
+
inline const std::string& error() const {
|
2045
|
+
return error_;
|
2046
|
+
}
|
2047
|
+
inline Target* target() const {
|
2048
|
+
return target_;
|
2049
|
+
}
|
2050
|
+
inline void set_target(Target* target) {
|
2051
|
+
target_ = target;
|
2052
|
+
}
|
2053
|
+
inline Identifiers* labels() const {
|
2054
|
+
return labels_;
|
2055
|
+
}
|
2056
|
+
inline void set_labels(Identifiers* labels) {
|
2057
|
+
labels_ = labels;
|
2058
|
+
}
|
2059
|
+
inline bool strict() const {
|
2060
|
+
return strict_;
|
2061
|
+
}
|
2062
|
+
inline void set_strict(bool strict) {
|
2063
|
+
strict_ = strict;
|
2064
|
+
}
|
2065
|
+
|
2066
|
+
protected:
|
2067
|
+
class ScopeSwitcher : private Noncopyable<ScopeSwitcher>::type {
|
2068
|
+
public:
|
2069
|
+
ScopeSwitcher(parser_type* parser, Scope* scope)
|
2070
|
+
: parser_(parser) {
|
2071
|
+
scope->SetUpperScope(parser_->scope());
|
2072
|
+
parser_->set_scope(scope);
|
2073
|
+
}
|
2074
|
+
~ScopeSwitcher() {
|
2075
|
+
assert(parser_->scope() != NULL);
|
2076
|
+
parser_->set_scope(parser_->scope()->GetUpperScope());
|
2077
|
+
}
|
2078
|
+
private:
|
2079
|
+
parser_type* parser_;
|
2080
|
+
};
|
2081
|
+
|
2082
|
+
class LabelScope : private Noncopyable<LabelScope>::type {
|
2083
|
+
public:
|
2084
|
+
LabelScope(parser_type* parser,
|
2085
|
+
Identifiers* labels, bool exist_labels)
|
2086
|
+
: parser_(parser),
|
2087
|
+
exist_labels_(exist_labels) {
|
2088
|
+
parser_->set_labels(labels);
|
2089
|
+
}
|
2090
|
+
~LabelScope() {
|
2091
|
+
if (!exist_labels_) {
|
2092
|
+
parser_->set_labels(NULL);
|
2093
|
+
}
|
2094
|
+
}
|
2095
|
+
private:
|
2096
|
+
parser_type* parser_;
|
2097
|
+
bool exist_labels_;
|
2098
|
+
};
|
2099
|
+
|
2100
|
+
class StrictSwitcher : private Noncopyable<StrictSwitcher>::type {
|
2101
|
+
public:
|
2102
|
+
explicit StrictSwitcher(parser_type* parser)
|
2103
|
+
: parser_(parser),
|
2104
|
+
prev_(parser->strict()) {
|
2105
|
+
}
|
2106
|
+
~StrictSwitcher() {
|
2107
|
+
parser_->set_strict(prev_);
|
2108
|
+
}
|
2109
|
+
inline void SwitchStrictMode() const {
|
2110
|
+
parser_->set_strict(true);
|
2111
|
+
}
|
2112
|
+
private:
|
2113
|
+
parser_type* parser_;
|
2114
|
+
bool prev_;
|
2115
|
+
};
|
2116
|
+
|
2117
|
+
enum EvalOrArguments {
|
2118
|
+
kNone = 0,
|
2119
|
+
kEval = 1,
|
2120
|
+
kArguments = 2
|
2121
|
+
};
|
2122
|
+
|
2123
|
+
static EvalOrArguments IsEvalOrArguments(const Identifier* ident) {
|
2124
|
+
const SpaceUString& str = ident->value();
|
2125
|
+
if (str.compare(ParserData::kEval.data()) == 0) {
|
2126
|
+
return kEval;
|
2127
|
+
} else if (str.compare(ParserData::kArguments.data()) == 0) {
|
2128
|
+
return kArguments;
|
2129
|
+
} else {
|
2130
|
+
return kNone;
|
2131
|
+
}
|
2132
|
+
}
|
2133
|
+
|
2134
|
+
Lexer lexer_;
|
2135
|
+
Token::Type token_;
|
2136
|
+
std::string error_;
|
2137
|
+
bool strict_;
|
2138
|
+
Factory* factory_;
|
2139
|
+
Scope* scope_;
|
2140
|
+
Target* target_;
|
2141
|
+
Identifiers* labels_;
|
2142
|
+
};
|
2143
|
+
#undef IS
|
2144
|
+
#undef EXPECT
|
2145
|
+
#undef UNEXPECT
|
2146
|
+
#undef RAISE
|
2147
|
+
#undef RAISE_WITH_NUMBER
|
2148
|
+
#undef CHECK
|
2149
|
+
} } // namespace iv::core
|
2150
|
+
#endif // _IV_PARSER_H_
|