iv-phonic 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -2
- data/ext/include/iv/ast-factory.h +42 -30
- data/ext/include/iv/ast-fwd.h +22 -12
- data/ext/include/iv/ast-serializer.h +26 -32
- data/ext/include/iv/ast-visitor.h +0 -2
- data/ext/include/iv/ast.h +122 -244
- data/ext/include/iv/lexer.h +1 -1
- data/ext/include/iv/parser.h +199 -193
- data/ext/iv/phonic/creator.h +0 -8
- data/ext/iv/phonic/factory.h +45 -32
- data/ext/iv/phonic/phonic.cc +0 -47
- metadata +3 -3
data/ext/include/iv/parser.h
CHANGED
@@ -140,15 +140,20 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
140
140
|
#undef V
|
141
141
|
class Target : private Noncopyable<Target>::type {
|
142
142
|
public:
|
143
|
-
|
143
|
+
typedef typename SpaceVector<Factory, Identifier*>::type Identifiers;
|
144
|
+
enum Type {
|
145
|
+
kNamedOnlyStatement = 0, // (00)2
|
146
|
+
kIterationStatement = 2, // (10)2
|
147
|
+
kSwitchStatement = 3 // (11)2
|
148
|
+
};
|
149
|
+
Target(parser_type* parser, Type type)
|
144
150
|
: parser_(parser),
|
145
151
|
prev_(parser->target()),
|
146
|
-
|
152
|
+
labels_(parser->labels()),
|
153
|
+
node_(NULL),
|
154
|
+
type_(type) {
|
147
155
|
parser_->set_target(this);
|
148
|
-
|
149
|
-
target->set_labels(parser_->labels());
|
150
|
-
parser_->set_labels(NULL);
|
151
|
-
}
|
156
|
+
parser_->set_labels(NULL);
|
152
157
|
}
|
153
158
|
~Target() {
|
154
159
|
parser_->set_target(prev_);
|
@@ -156,13 +161,36 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
156
161
|
inline Target* previous() const {
|
157
162
|
return prev_;
|
158
163
|
}
|
159
|
-
inline
|
164
|
+
inline bool IsAnonymous() const {
|
165
|
+
return type_ & 2;
|
166
|
+
}
|
167
|
+
inline bool IsIteration() const {
|
168
|
+
return type_ == kIterationStatement;
|
169
|
+
}
|
170
|
+
inline bool IsSwitch() const {
|
171
|
+
return type_ == kSwitchStatement;
|
172
|
+
}
|
173
|
+
inline bool IsNamedOnly() const {
|
174
|
+
return !IsAnonymous();
|
175
|
+
}
|
176
|
+
inline BreakableStatement** node() {
|
177
|
+
node_ = new(parser_->factory())BreakableStatement*();
|
160
178
|
return node_;
|
161
179
|
}
|
180
|
+
inline Identifiers* labels() const {
|
181
|
+
return labels_;
|
182
|
+
}
|
183
|
+
inline void set_node(BreakableStatement* node) {
|
184
|
+
if (node_) {
|
185
|
+
*node_ = node;
|
186
|
+
}
|
187
|
+
}
|
162
188
|
private:
|
163
189
|
parser_type* parser_;
|
164
190
|
Target* prev_;
|
165
|
-
|
191
|
+
Identifiers* labels_;
|
192
|
+
BreakableStatement** node_;
|
193
|
+
int type_;
|
166
194
|
};
|
167
195
|
|
168
196
|
Parser(BasicSource* source, Factory* space)
|
@@ -200,7 +228,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
200
228
|
// | FunctionDeclaration
|
201
229
|
bool ParseSourceElements(Token::Type end,
|
202
230
|
FunctionLiteral* function, bool *res) {
|
203
|
-
Statement
|
231
|
+
Statement* stmt;
|
204
232
|
bool recognize_use_strict_directive = true;
|
205
233
|
const StrictSwitcher switcher(this);
|
206
234
|
while (token_ != end) {
|
@@ -369,11 +397,9 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
369
397
|
// and this statement is very useful for not breaking FunctionDeclaration.
|
370
398
|
Statement* ParseFunctionDeclaration(bool *res) {
|
371
399
|
assert(token_ == Token::FUNCTION);
|
372
|
-
|
373
|
-
IS(Token::IDENTIFIER);
|
374
|
-
FunctionLiteral* expr = ParseFunctionLiteral(
|
400
|
+
FunctionLiteral* const expr = ParseFunctionLiteral(
|
375
401
|
FunctionLiteral::DECLARATION,
|
376
|
-
FunctionLiteral::GENERAL,
|
402
|
+
FunctionLiteral::GENERAL, CHECK);
|
377
403
|
// define named function as FunctionDeclaration
|
378
404
|
scope_->AddFunctionDeclaration(expr);
|
379
405
|
return factory_->NewFunctionStatement(expr);
|
@@ -388,9 +414,9 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
388
414
|
// | StatementList Statement
|
389
415
|
Block* ParseBlock(bool *res) {
|
390
416
|
assert(token_ == Token::LBRACE);
|
391
|
-
Block
|
392
|
-
Statement
|
393
|
-
Target target(this,
|
417
|
+
Block* const block = factory_->NewBlock();
|
418
|
+
Statement* stmt;
|
419
|
+
Target target(this, Target::kNamedOnlyStatement);
|
394
420
|
|
395
421
|
Next();
|
396
422
|
while (token_ != Token::RBRACE) {
|
@@ -398,6 +424,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
398
424
|
block->AddStatement(stmt);
|
399
425
|
}
|
400
426
|
Next();
|
427
|
+
target.set_node(block);
|
401
428
|
return block;
|
402
429
|
}
|
403
430
|
|
@@ -406,7 +433,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
406
433
|
// : CONST VariableDeclarationList ';'
|
407
434
|
Statement* ParseVariableStatement(bool *res) {
|
408
435
|
assert(token_ == Token::VAR || token_ == Token::CONST);
|
409
|
-
VariableStatement* stmt = factory_->NewVariableStatement(token_);
|
436
|
+
VariableStatement* const stmt = factory_->NewVariableStatement(token_);
|
410
437
|
ParseVariableDeclarations(stmt, true, CHECK);
|
411
438
|
ExpectSemicolon(CHECK);
|
412
439
|
return stmt;
|
@@ -428,14 +455,14 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
428
455
|
Statement* ParseVariableDeclarations(VariableStatement* stmt,
|
429
456
|
bool contains_in,
|
430
457
|
bool *res) {
|
431
|
-
Identifier
|
432
|
-
Expression
|
433
|
-
Declaration
|
458
|
+
Identifier* name;
|
459
|
+
Expression* expr;
|
460
|
+
Declaration* decl;
|
434
461
|
|
435
462
|
do {
|
436
463
|
Next();
|
437
464
|
IS(Token::IDENTIFIER);
|
438
|
-
name =
|
465
|
+
name = ParseIdentifier(lexer_.Buffer());
|
439
466
|
// section 12.2.1
|
440
467
|
// within the strict code, Identifier must not be "eval" or "arguments"
|
441
468
|
if (strict_) {
|
@@ -449,7 +476,6 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
449
476
|
}
|
450
477
|
}
|
451
478
|
}
|
452
|
-
Next();
|
453
479
|
|
454
480
|
if (token_ == Token::ASSIGN) {
|
455
481
|
Next();
|
@@ -480,24 +506,23 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
480
506
|
// | IF '(' Expression ')' Statement
|
481
507
|
Statement* ParseIfStatement(bool *res) {
|
482
508
|
assert(token_ == Token::IF);
|
483
|
-
|
484
|
-
Statement* stmt;
|
509
|
+
Statement* else_statement = NULL;
|
485
510
|
Next();
|
486
511
|
|
487
512
|
EXPECT(Token::LPAREN);
|
488
513
|
|
489
|
-
Expression
|
514
|
+
Expression* const expr = ParseExpression(true, CHECK);
|
490
515
|
|
491
516
|
EXPECT(Token::RPAREN);
|
492
517
|
|
493
|
-
|
494
|
-
if_stmt = factory_->NewIfStatement(expr, stmt);
|
518
|
+
Statement* const then_statement = ParseStatement(CHECK);
|
495
519
|
if (token_ == Token::ELSE) {
|
496
520
|
Next();
|
497
|
-
|
498
|
-
if_stmt->SetElse(stmt);
|
521
|
+
else_statement = ParseStatement(CHECK);
|
499
522
|
}
|
500
|
-
return
|
523
|
+
return factory_->NewIfStatement(expr,
|
524
|
+
then_statement,
|
525
|
+
else_statement);
|
501
526
|
}
|
502
527
|
|
503
528
|
// IterationStatement
|
@@ -514,23 +539,22 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
514
539
|
Statement* ParseDoWhileStatement(bool *res) {
|
515
540
|
// DO Statement WHILE '(' Expression ')' ';'
|
516
541
|
assert(token_ == Token::DO);
|
517
|
-
|
518
|
-
Target target(this, dowhile);
|
542
|
+
Target target(this, Target::kIterationStatement);
|
519
543
|
Next();
|
520
544
|
|
521
|
-
Statement
|
522
|
-
dowhile->set_body(stmt);
|
545
|
+
Statement* const stmt = ParseStatement(CHECK);
|
523
546
|
|
524
547
|
EXPECT(Token::WHILE);
|
525
548
|
|
526
549
|
EXPECT(Token::LPAREN);
|
527
550
|
|
528
|
-
Expression
|
529
|
-
dowhile->set_cond(expr);
|
551
|
+
Expression* const expr = ParseExpression(true, CHECK);
|
530
552
|
|
531
553
|
EXPECT(Token::RPAREN);
|
532
554
|
|
533
555
|
ExpectSemicolon(CHECK);
|
556
|
+
DoWhileStatement* const dowhile = factory_->NewDoWhileStatement(stmt, expr);
|
557
|
+
target.set_node(dowhile);
|
534
558
|
return dowhile;
|
535
559
|
}
|
536
560
|
|
@@ -541,15 +565,15 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
541
565
|
|
542
566
|
EXPECT(Token::LPAREN);
|
543
567
|
|
544
|
-
Expression
|
545
|
-
|
546
|
-
Target target(this, whilestmt);
|
568
|
+
Expression* const expr = ParseExpression(true, CHECK);
|
569
|
+
Target target(this, Target::kIterationStatement);
|
547
570
|
|
548
571
|
EXPECT(Token::RPAREN);
|
549
572
|
|
550
|
-
Statement* stmt = ParseStatement(CHECK);
|
551
|
-
whilestmt->
|
573
|
+
Statement* const stmt = ParseStatement(CHECK);
|
574
|
+
WhileStatement* const whilestmt = factory_->NewWhileStatement(stmt, expr);
|
552
575
|
|
576
|
+
target.set_node(whilestmt);
|
553
577
|
return whilestmt;
|
554
578
|
}
|
555
579
|
|
@@ -571,7 +595,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
571
595
|
|
572
596
|
if (token_ != Token::SEMICOLON) {
|
573
597
|
if (token_ == Token::VAR || token_ == Token::CONST) {
|
574
|
-
VariableStatement
|
598
|
+
VariableStatement* const var = factory_->NewVariableStatement(token_);
|
575
599
|
ParseVariableDeclarations(var, false, CHECK);
|
576
600
|
init = var;
|
577
601
|
if (token_ == Token::IN) {
|
@@ -583,17 +607,17 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
583
607
|
// so check declarations' size is 1.
|
584
608
|
RAISE("invalid for-in left-hand-side");
|
585
609
|
}
|
586
|
-
Expression
|
610
|
+
Expression* const enumerable = ParseExpression(true, CHECK);
|
587
611
|
EXPECT(Token::RPAREN);
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
forstmt
|
612
|
+
Target target(this, Target::kIterationStatement);
|
613
|
+
Statement* const body = ParseStatement(CHECK);
|
614
|
+
ForInStatement* const forstmt =
|
615
|
+
factory_->NewForInStatement(body, init, enumerable);
|
616
|
+
target.set_node(forstmt);
|
593
617
|
return forstmt;
|
594
618
|
}
|
595
619
|
} else {
|
596
|
-
Expression
|
620
|
+
Expression* const init_expr = ParseExpression(false, CHECK);
|
597
621
|
init = factory_->NewExpressionStatement(init_expr);
|
598
622
|
if (token_ == Token::IN) {
|
599
623
|
// for in loop
|
@@ -601,13 +625,13 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
601
625
|
RAISE("invalid for-in left-hand-side");
|
602
626
|
}
|
603
627
|
Next();
|
604
|
-
Expression
|
628
|
+
Expression* const enumerable = ParseExpression(true, CHECK);
|
605
629
|
EXPECT(Token::RPAREN);
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
forstmt
|
630
|
+
Target target(this, Target::kIterationStatement);
|
631
|
+
Statement* const body = ParseStatement(CHECK);
|
632
|
+
ForInStatement* const forstmt =
|
633
|
+
factory_->NewForInStatement(body, init, enumerable);
|
634
|
+
target.set_node(forstmt);
|
611
635
|
return forstmt;
|
612
636
|
}
|
613
637
|
}
|
@@ -616,7 +640,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
616
640
|
// ordinary for loop
|
617
641
|
EXPECT(Token::SEMICOLON);
|
618
642
|
|
619
|
-
Expression
|
643
|
+
Expression* cond = NULL;
|
620
644
|
if (token_ == Token::SEMICOLON) {
|
621
645
|
// no cond expr
|
622
646
|
Next();
|
@@ -625,7 +649,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
625
649
|
EXPECT(Token::SEMICOLON);
|
626
650
|
}
|
627
651
|
|
628
|
-
ExpressionStatement
|
652
|
+
ExpressionStatement* next = NULL;
|
629
653
|
if (token_ == Token::RPAREN) {
|
630
654
|
Next();
|
631
655
|
} else {
|
@@ -634,60 +658,47 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
634
658
|
EXPECT(Token::RPAREN);
|
635
659
|
}
|
636
660
|
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
}
|
644
|
-
if (cond) {
|
645
|
-
for_stmt->SetCondition(cond);
|
646
|
-
}
|
647
|
-
if (next) {
|
648
|
-
for_stmt->SetNext(next);
|
649
|
-
}
|
650
|
-
|
651
|
-
return for_stmt;
|
661
|
+
Target target(this, Target::kIterationStatement);
|
662
|
+
Statement* const body = ParseStatement(CHECK);
|
663
|
+
ForStatement* const forstmt =
|
664
|
+
factory_->NewForStatement(body, init, cond, next);
|
665
|
+
target.set_node(forstmt);
|
666
|
+
return forstmt;
|
652
667
|
}
|
653
668
|
|
654
669
|
// ContinueStatement
|
655
670
|
// : CONTINUE Identifier_opt ';'
|
656
671
|
Statement* ParseContinueStatement(bool *res) {
|
657
672
|
assert(token_ == Token::CONTINUE);
|
658
|
-
|
673
|
+
Identifier* label = NULL;
|
674
|
+
IterationStatement** target;
|
659
675
|
Next();
|
660
676
|
if (!lexer_.has_line_terminator_before_next() &&
|
661
677
|
token_ != Token::SEMICOLON &&
|
662
678
|
token_ != Token::RBRACE &&
|
663
679
|
token_ != Token::EOS) {
|
664
680
|
IS(Token::IDENTIFIER);
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
if (target) {
|
669
|
-
continue_stmt->SetTarget(target);
|
670
|
-
} else {
|
681
|
+
label = ParseIdentifier(lexer_.Buffer());
|
682
|
+
target = LookupContinuableTarget(label);
|
683
|
+
if (!target) {
|
671
684
|
RAISE("label not found");
|
672
685
|
}
|
673
|
-
Next();
|
674
686
|
} else {
|
675
|
-
|
676
|
-
if (target) {
|
677
|
-
continue_stmt->SetTarget(target);
|
678
|
-
} else {
|
687
|
+
target = LookupContinuableTarget();
|
688
|
+
if (!target) {
|
679
689
|
RAISE("label not found");
|
680
690
|
}
|
681
691
|
}
|
682
692
|
ExpectSemicolon(CHECK);
|
683
|
-
return
|
693
|
+
return factory_->NewContinueStatement(label, target);
|
684
694
|
}
|
685
695
|
|
686
696
|
// BreakStatement
|
687
697
|
// : BREAK Identifier_opt ';'
|
688
698
|
Statement* ParseBreakStatement(bool *res) {
|
689
699
|
assert(token_ == Token::BREAK);
|
690
|
-
|
700
|
+
Identifier* label = NULL;
|
701
|
+
BreakableStatement** target = NULL;
|
691
702
|
Next();
|
692
703
|
if (!lexer_.has_line_terminator_before_next() &&
|
693
704
|
token_ != Token::SEMICOLON &&
|
@@ -695,8 +706,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
695
706
|
token_ != Token::EOS) {
|
696
707
|
// label
|
697
708
|
IS(Token::IDENTIFIER);
|
698
|
-
|
699
|
-
break_stmt->SetLabel(label);
|
709
|
+
label = ParseIdentifier(lexer_.Buffer());
|
700
710
|
if (ContainsLabel(labels_, label)) {
|
701
711
|
// example
|
702
712
|
//
|
@@ -708,24 +718,19 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
708
718
|
// In iv, BreakStatement with label, but without target is
|
709
719
|
// interpreted as EmptyStatement
|
710
720
|
} else {
|
711
|
-
|
712
|
-
if (target) {
|
713
|
-
break_stmt->SetTarget(target);
|
714
|
-
} else {
|
721
|
+
target = LookupBreakableTarget(label);
|
722
|
+
if (!target) {
|
715
723
|
RAISE("label not found");
|
716
724
|
}
|
717
725
|
}
|
718
|
-
Next();
|
719
726
|
} else {
|
720
|
-
|
721
|
-
if (target) {
|
722
|
-
break_stmt->SetTarget(target);
|
723
|
-
} else {
|
727
|
+
target = LookupBreakableTarget();
|
728
|
+
if (!target) {
|
724
729
|
RAISE("label not found");
|
725
730
|
}
|
726
731
|
}
|
727
732
|
ExpectSemicolon(CHECK);
|
728
|
-
return
|
733
|
+
return factory_->NewBreakStatement(label, target);
|
729
734
|
}
|
730
735
|
|
731
736
|
// ReturnStatement
|
@@ -782,7 +787,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
782
787
|
|
783
788
|
Expression *expr = ParseExpression(true, CHECK);
|
784
789
|
SwitchStatement *switch_stmt = factory_->NewSwitchStatement(expr);
|
785
|
-
Target target(this,
|
790
|
+
Target target(this, Target::kSwitchStatement);
|
786
791
|
|
787
792
|
EXPECT(Token::RPAREN);
|
788
793
|
|
@@ -794,6 +799,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
794
799
|
}
|
795
800
|
Next();
|
796
801
|
|
802
|
+
target.set_node(switch_stmt);
|
797
803
|
return switch_stmt;
|
798
804
|
}
|
799
805
|
|
@@ -808,16 +814,16 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
808
814
|
// : DEFAULT ':' StatementList_opt
|
809
815
|
CaseClause* ParseCaseClause(bool *res) {
|
810
816
|
assert(token_ == Token::CASE || token_ == Token::DEFAULT);
|
811
|
-
CaseClause
|
812
|
-
Statement
|
817
|
+
CaseClause* clause;
|
818
|
+
Statement* stmt;
|
813
819
|
|
814
820
|
if (token_ == Token::CASE) {
|
815
821
|
Next();
|
816
|
-
Expression
|
817
|
-
clause->
|
822
|
+
Expression* const expr = ParseExpression(true, CHECK);
|
823
|
+
clause = factory_->NewCaseClause(false, expr);
|
818
824
|
} else {
|
819
825
|
EXPECT(Token::DEFAULT);
|
820
|
-
clause->
|
826
|
+
clause = factory_->NewCaseClause(true, NULL);
|
821
827
|
}
|
822
828
|
|
823
829
|
EXPECT(Token::COLON);
|
@@ -836,13 +842,12 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
836
842
|
// : THROW Expression ';'
|
837
843
|
Statement* ParseThrowStatement(bool *res) {
|
838
844
|
assert(token_ == Token::THROW);
|
839
|
-
Expression *expr;
|
840
845
|
Next();
|
841
846
|
// Throw requires Expression
|
842
847
|
if (lexer_.has_line_terminator_before_next()) {
|
843
848
|
RAISE("missing expression between throw and newline");
|
844
849
|
}
|
845
|
-
expr = ParseExpression(true, CHECK);
|
850
|
+
Expression* const expr = ParseExpression(true, CHECK);
|
846
851
|
ExpectSemicolon(CHECK);
|
847
852
|
return factory_->NewThrowStatement(expr);
|
848
853
|
}
|
@@ -859,14 +864,14 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
859
864
|
// : FINALLY Block
|
860
865
|
Statement* ParseTryStatement(bool *res) {
|
861
866
|
assert(token_ == Token::TRY);
|
862
|
-
Identifier
|
863
|
-
Block
|
867
|
+
Identifier* name = NULL;
|
868
|
+
Block* catch_block = NULL;
|
869
|
+
Block* finally_block = NULL;
|
864
870
|
bool has_catch_or_finally = false;
|
865
871
|
|
866
872
|
Next();
|
867
873
|
|
868
|
-
|
869
|
-
TryStatement *try_stmt = factory_->NewTryStatement(block);
|
874
|
+
Block* const try_block = ParseBlock(CHECK);
|
870
875
|
|
871
876
|
if (token_ == Token::CATCH) {
|
872
877
|
// Catch
|
@@ -874,7 +879,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
874
879
|
Next();
|
875
880
|
EXPECT(Token::LPAREN);
|
876
881
|
IS(Token::IDENTIFIER);
|
877
|
-
name =
|
882
|
+
name = ParseIdentifier(lexer_.Buffer());
|
878
883
|
// section 12.14.1
|
879
884
|
// within the strict code, Identifier must not be "eval" or "arguments"
|
880
885
|
if (strict_) {
|
@@ -889,25 +894,23 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
889
894
|
}
|
890
895
|
}
|
891
896
|
}
|
892
|
-
Next();
|
893
897
|
EXPECT(Token::RPAREN);
|
894
|
-
|
895
|
-
try_stmt->SetCatch(name, block);
|
898
|
+
catch_block = ParseBlock(CHECK);
|
896
899
|
}
|
897
900
|
|
898
901
|
if (token_ == Token::FINALLY) {
|
899
902
|
// Finally
|
900
903
|
has_catch_or_finally= true;
|
901
904
|
Next();
|
902
|
-
|
903
|
-
try_stmt->SetFinally(block);
|
905
|
+
finally_block = ParseBlock(CHECK);
|
904
906
|
}
|
905
907
|
|
906
908
|
if (!has_catch_or_finally) {
|
907
909
|
RAISE("missing catch or finally after try statement");
|
908
910
|
}
|
909
911
|
|
910
|
-
return
|
912
|
+
return factory_->NewTryStatement(try_block,
|
913
|
+
name, catch_block, finally_block);
|
911
914
|
}
|
912
915
|
|
913
916
|
// DebuggerStatement
|
@@ -920,7 +923,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
920
923
|
}
|
921
924
|
|
922
925
|
Statement* ParseExpressionStatement(bool *res) {
|
923
|
-
Expression* expr = ParseExpression(true, CHECK);
|
926
|
+
Expression* const expr = ParseExpression(true, CHECK);
|
924
927
|
ExpectSemicolon(CHECK);
|
925
928
|
return factory_->NewExpressionStatement(expr);
|
926
929
|
}
|
@@ -932,7 +935,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
932
935
|
// : Expression ';'
|
933
936
|
Statement* ParseExpressionOrLabelledStatement(bool *res) {
|
934
937
|
assert(token_ == Token::IDENTIFIER);
|
935
|
-
Expression* expr = ParseExpression(true, CHECK);
|
938
|
+
Expression* const expr = ParseExpression(true, CHECK);
|
936
939
|
if (token_ == Token::COLON &&
|
937
940
|
expr->AsIdentifier()) {
|
938
941
|
// LabelledStatement
|
@@ -949,9 +952,9 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
949
952
|
RAISE("duplicate label");
|
950
953
|
}
|
951
954
|
labels->push_back(label);
|
952
|
-
LabelScope scope(this, labels, exist_labels);
|
955
|
+
const LabelScope scope(this, labels, exist_labels);
|
953
956
|
|
954
|
-
Statement* stmt = ParseStatement(CHECK);
|
957
|
+
Statement* const stmt = ParseStatement(CHECK);
|
955
958
|
return factory_->NewLabelledStatement(expr, stmt);
|
956
959
|
}
|
957
960
|
ExpectSemicolon(CHECK);
|
@@ -963,11 +966,10 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
963
966
|
if (strict_) {
|
964
967
|
RAISE("function statement not allowed in strict code");
|
965
968
|
}
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
true, CHECK);
|
969
|
+
FunctionLiteral* const expr = ParseFunctionLiteral(
|
970
|
+
FunctionLiteral::STATEMENT,
|
971
|
+
FunctionLiteral::GENERAL,
|
972
|
+
CHECK);
|
971
973
|
// define named function as variable declaration
|
972
974
|
scope_->AddUnresolved(expr->name(), false);
|
973
975
|
return factory_->NewFunctionStatement(expr);
|
@@ -977,8 +979,8 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
977
979
|
// : AssignmentExpression
|
978
980
|
// | Expression ',' AssignmentExpression
|
979
981
|
Expression* ParseExpression(bool contains_in, bool *res) {
|
980
|
-
Expression
|
981
|
-
Expression
|
982
|
+
Expression* right;
|
983
|
+
Expression* result = ParseAssignmentExpression(contains_in, CHECK);
|
982
984
|
while (token_ == Token::COMMA) {
|
983
985
|
Next();
|
984
986
|
right = ParseAssignmentExpression(contains_in, CHECK);
|
@@ -991,7 +993,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
991
993
|
// : ConditionalExpression
|
992
994
|
// | LeftHandSideExpression AssignmentOperator AssignmentExpression
|
993
995
|
Expression* ParseAssignmentExpression(bool contains_in, bool *res) {
|
994
|
-
Expression
|
996
|
+
Expression* const result = ParseConditionalExpression(contains_in, CHECK);
|
995
997
|
if (!Token::IsAssignOp(token_)) {
|
996
998
|
return result;
|
997
999
|
}
|
@@ -1013,7 +1015,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1013
1015
|
}
|
1014
1016
|
const Token::Type op = token_;
|
1015
1017
|
Next();
|
1016
|
-
Expression
|
1018
|
+
Expression* const right = ParseAssignmentExpression(contains_in, CHECK);
|
1017
1019
|
return factory_->NewAssignment(op, result, right);
|
1018
1020
|
}
|
1019
1021
|
|
@@ -1021,14 +1023,13 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1021
1023
|
// : LogicalOrExpression
|
1022
1024
|
// | LogicalOrExpression '?' AssignmentExpression ':' AssignmentExpression
|
1023
1025
|
Expression* ParseConditionalExpression(bool contains_in, bool *res) {
|
1024
|
-
Expression
|
1025
|
-
result = ParseBinaryExpression(contains_in, 9, CHECK);
|
1026
|
+
Expression* result = ParseBinaryExpression(contains_in, 9, CHECK);
|
1026
1027
|
if (token_ == Token::CONDITIONAL) {
|
1027
1028
|
Next();
|
1028
1029
|
// see ECMA-262 section 11.12
|
1029
|
-
Expression
|
1030
|
+
Expression* const left = ParseAssignmentExpression(true, CHECK);
|
1030
1031
|
EXPECT(Token::COLON);
|
1031
|
-
Expression
|
1032
|
+
Expression* const right = ParseAssignmentExpression(contains_in, CHECK);
|
1032
1033
|
result = factory_->NewConditionalExpression(result, left, right);
|
1033
1034
|
}
|
1034
1035
|
return result;
|
@@ -1369,8 +1370,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1369
1370
|
// | LeftHandSideExpression INCREMENT
|
1370
1371
|
// | LeftHandSideExpression DECREMENT
|
1371
1372
|
Expression* ParsePostfixExpression(bool *res) {
|
1372
|
-
Expression
|
1373
|
-
expr = ParseMemberExpression(true, CHECK);
|
1373
|
+
Expression* expr = ParseMemberExpression(true, CHECK);
|
1374
1374
|
if (!lexer_.has_line_terminator_before_next() &&
|
1375
1375
|
(token_ == Token::INC || token_ == Token::DEC)) {
|
1376
1376
|
if (!expr->IsValidLeftHandSide()) {
|
@@ -1414,9 +1414,8 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1414
1414
|
if (token_ != Token::NEW) {
|
1415
1415
|
if (token_ == Token::FUNCTION) {
|
1416
1416
|
// FunctionExpression
|
1417
|
-
Next();
|
1418
1417
|
expr = ParseFunctionLiteral(FunctionLiteral::EXPRESSION,
|
1419
|
-
FunctionLiteral::GENERAL,
|
1418
|
+
FunctionLiteral::GENERAL, CHECK);
|
1420
1419
|
} else {
|
1421
1420
|
expr = ParsePrimaryExpression(CHECK);
|
1422
1421
|
}
|
@@ -1429,7 +1428,6 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1429
1428
|
}
|
1430
1429
|
expr = con;
|
1431
1430
|
}
|
1432
|
-
FunctionCall *funcall;
|
1433
1431
|
while (true) {
|
1434
1432
|
switch (token_) {
|
1435
1433
|
case Token::LBRACK: {
|
@@ -1443,15 +1441,14 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1443
1441
|
case Token::PERIOD: {
|
1444
1442
|
Next(Lexer::kIgnoreReservedWords); // IDENTIFIERNAME
|
1445
1443
|
IS(Token::IDENTIFIER);
|
1446
|
-
Identifier* ident =
|
1447
|
-
Next();
|
1444
|
+
Identifier* const ident = ParseIdentifier(lexer_.Buffer());
|
1448
1445
|
expr = factory_->NewIdentifierAccess(expr, ident);
|
1449
1446
|
break;
|
1450
1447
|
}
|
1451
1448
|
|
1452
1449
|
case Token::LPAREN:
|
1453
1450
|
if (allow_call) {
|
1454
|
-
funcall = factory_->NewFunctionCall(expr);
|
1451
|
+
FunctionCall* const funcall = factory_->NewFunctionCall(expr);
|
1455
1452
|
ParseArguments(funcall, CHECK);
|
1456
1453
|
expr = funcall;
|
1457
1454
|
} else {
|
@@ -1481,7 +1478,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1481
1478
|
// | STRING
|
1482
1479
|
// | REGEXP
|
1483
1480
|
Expression* ParsePrimaryExpression(bool *res) {
|
1484
|
-
Expression
|
1481
|
+
Expression* result = NULL;
|
1485
1482
|
switch (token_) {
|
1486
1483
|
case Token::THIS:
|
1487
1484
|
result = factory_->NewThisLiteral();
|
@@ -1489,8 +1486,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1489
1486
|
break;
|
1490
1487
|
|
1491
1488
|
case Token::IDENTIFIER:
|
1492
|
-
result =
|
1493
|
-
Next();
|
1489
|
+
result = ParseIdentifier(lexer_.Buffer());
|
1494
1490
|
break;
|
1495
1491
|
|
1496
1492
|
case Token::NULL_LITERAL:
|
@@ -1569,7 +1565,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1569
1565
|
// : AssignmentExpression
|
1570
1566
|
// | ArgumentList ',' AssignmentExpression
|
1571
1567
|
Call* ParseArguments(Call* func, bool *res) {
|
1572
|
-
Expression
|
1568
|
+
Expression* expr;
|
1573
1569
|
Next();
|
1574
1570
|
while (token_ != Token::RPAREN) {
|
1575
1571
|
expr = ParseAssignmentExpression(true, CHECK);
|
@@ -1614,8 +1610,8 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1614
1610
|
// : ','
|
1615
1611
|
// | Elision ','
|
1616
1612
|
Expression* ParseArrayLiteral(bool *res) {
|
1617
|
-
ArrayLiteral
|
1618
|
-
Expression
|
1613
|
+
ArrayLiteral* const array = factory_->NewArrayLiteral();
|
1614
|
+
Expression* expr;
|
1619
1615
|
Next();
|
1620
1616
|
while (token_ != Token::RBRACK) {
|
1621
1617
|
if (token_ == Token::COMMA) {
|
@@ -1660,10 +1656,10 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1660
1656
|
// : IDENTIFIER
|
1661
1657
|
Expression* ParseObjectLiteral(bool *res) {
|
1662
1658
|
typedef std::tr1::unordered_map<IdentifierKey, int> ObjectMap;
|
1663
|
-
ObjectLiteral
|
1659
|
+
ObjectLiteral* const object = factory_->NewObjectLiteral();
|
1664
1660
|
ObjectMap map;
|
1665
|
-
Expression
|
1666
|
-
Identifier
|
1661
|
+
Expression* expr;
|
1662
|
+
Identifier* ident;
|
1667
1663
|
|
1668
1664
|
// IDENTIFIERNAME
|
1669
1665
|
Next(Lexer::kIgnoreReservedWordsAndIdentifyGetterOrSetter);
|
@@ -1674,9 +1670,8 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1674
1670
|
Next(Lexer::kIgnoreReservedWords); // IDENTIFIERNAME
|
1675
1671
|
if (token_ == Token::COLON) {
|
1676
1672
|
// property
|
1677
|
-
ident =
|
1673
|
+
ident = ParseIdentifier(
|
1678
1674
|
is_get ? ParserData::kGet : ParserData::kSet);
|
1679
|
-
Next();
|
1680
1675
|
expr = ParseAssignmentExpression(true, CHECK);
|
1681
1676
|
object->AddDataProperty(ident, expr);
|
1682
1677
|
typename ObjectMap::iterator it = map.find(ident);
|
@@ -1699,17 +1694,16 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1699
1694
|
token_ == Token::STRING ||
|
1700
1695
|
token_ == Token::NUMBER) {
|
1701
1696
|
if (token_ == Token::NUMBER) {
|
1702
|
-
ident =
|
1697
|
+
ident = ParseIdentifier(lexer_.Buffer8());
|
1703
1698
|
} else {
|
1704
|
-
ident =
|
1699
|
+
ident = ParseIdentifier(lexer_.Buffer());
|
1705
1700
|
}
|
1706
|
-
Next();
|
1707
1701
|
typename ObjectLiteral::PropertyDescriptorType type =
|
1708
1702
|
(is_get) ? ObjectLiteral::GET : ObjectLiteral::SET;
|
1709
1703
|
expr = ParseFunctionLiteral(
|
1710
1704
|
FunctionLiteral::EXPRESSION,
|
1711
1705
|
(is_get) ? FunctionLiteral::GETTER : FunctionLiteral::SETTER,
|
1712
|
-
|
1706
|
+
CHECK);
|
1713
1707
|
object->AddAccessor(type, ident, expr);
|
1714
1708
|
typename ObjectMap::iterator it = map.find(ident);
|
1715
1709
|
if (it == map.end()) {
|
@@ -1732,8 +1726,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1732
1726
|
} else if (token_ == Token::IDENTIFIER ||
|
1733
1727
|
token_ == Token::STRING ||
|
1734
1728
|
token_ == Token::NUMBER) {
|
1735
|
-
ident =
|
1736
|
-
Next();
|
1729
|
+
ident = ParseIdentifier(lexer_.Buffer());
|
1737
1730
|
EXPECT(Token::COLON);
|
1738
1731
|
expr = ParseAssignmentExpression(true, CHECK);
|
1739
1732
|
object->AddDataProperty(ident, expr);
|
@@ -1768,7 +1761,6 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1768
1761
|
FunctionLiteral* ParseFunctionLiteral(
|
1769
1762
|
typename FunctionLiteral::DeclType decl_type,
|
1770
1763
|
typename FunctionLiteral::ArgType arg_type,
|
1771
|
-
bool allow_identifier,
|
1772
1764
|
bool *res) {
|
1773
1765
|
// IDENTIFIER
|
1774
1766
|
// IDENTIFIER_opt
|
@@ -1783,19 +1775,27 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1783
1775
|
kDetectDuplicateParameter
|
1784
1776
|
} throw_error_if_strict_code = kDetectNone;
|
1785
1777
|
|
1786
|
-
FunctionLiteral
|
1778
|
+
FunctionLiteral* const literal = factory_->NewFunctionLiteral(decl_type);
|
1787
1779
|
literal->set_strict(strict_);
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
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
|
-
}
|
1780
|
+
|
1781
|
+
if (arg_type == FunctionLiteral::GENERAL) {
|
1782
|
+
assert(token_ == Token::FUNCTION);
|
1797
1783
|
Next();
|
1784
|
+
if (token_ == Token::IDENTIFIER) {
|
1785
|
+
Identifier* const name = ParseIdentifier(lexer_.Buffer());
|
1786
|
+
literal->SetName(name);
|
1787
|
+
const EvalOrArguments val = IsEvalOrArguments(name);
|
1788
|
+
if (val) {
|
1789
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1790
|
+
kDetectEvalName : kDetectArgumentsName;
|
1791
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1792
|
+
}
|
1793
|
+
} else if (decl_type == FunctionLiteral::DECLARATION ||
|
1794
|
+
decl_type == FunctionLiteral::STATEMENT) {
|
1795
|
+
IS(Token::IDENTIFIER);
|
1796
|
+
}
|
1798
1797
|
}
|
1798
|
+
|
1799
1799
|
const ScopeSwitcher switcher(this, literal->scope());
|
1800
1800
|
literal->set_start_position(lexer_.pos() - 2);
|
1801
1801
|
|
@@ -1808,7 +1808,7 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1808
1808
|
} else if (arg_type == FunctionLiteral::SETTER) {
|
1809
1809
|
// if setter, parameter count is 1
|
1810
1810
|
IS(Token::IDENTIFIER);
|
1811
|
-
Identifier* const ident =
|
1811
|
+
Identifier* const ident = ParseIdentifier(lexer_.Buffer());
|
1812
1812
|
if (!throw_error_if_strict_code) {
|
1813
1813
|
const EvalOrArguments val = IsEvalOrArguments(ident);
|
1814
1814
|
if (val) {
|
@@ -1818,12 +1818,11 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1818
1818
|
}
|
1819
1819
|
}
|
1820
1820
|
literal->AddParameter(ident);
|
1821
|
-
Next();
|
1822
1821
|
EXPECT(Token::RPAREN);
|
1823
1822
|
} else {
|
1824
1823
|
while (token_ != Token::RPAREN) {
|
1825
1824
|
IS(Token::IDENTIFIER);
|
1826
|
-
Identifier* const ident =
|
1825
|
+
Identifier* const ident = ParseIdentifier(lexer_.Buffer());
|
1827
1826
|
if (!throw_error_if_strict_code) {
|
1828
1827
|
const EvalOrArguments val = IsEvalOrArguments(ident);
|
1829
1828
|
if (val) {
|
@@ -1839,7 +1838,6 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1839
1838
|
}
|
1840
1839
|
literal->AddParameter(ident);
|
1841
1840
|
param_set.insert(ident);
|
1842
|
-
Next();
|
1843
1841
|
if (token_ != Token::RPAREN) {
|
1844
1842
|
EXPECT(Token::COMMA);
|
1845
1843
|
}
|
@@ -1894,11 +1892,18 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1894
1892
|
return literal;
|
1895
1893
|
}
|
1896
1894
|
|
1895
|
+
template<typename Range>
|
1896
|
+
Identifier* ParseIdentifier(const Range& range) {
|
1897
|
+
Identifier* const ident = factory_->NewIdentifier(range);
|
1898
|
+
Next();
|
1899
|
+
return ident;
|
1900
|
+
}
|
1901
|
+
|
1897
1902
|
bool ContainsLabel(const Identifiers* const labels,
|
1898
1903
|
const Identifier * const label) const {
|
1899
1904
|
assert(label != NULL);
|
1900
1905
|
if (labels) {
|
1901
|
-
const
|
1906
|
+
const typename Identifier::value_type& value = label->value();
|
1902
1907
|
for (typename Identifiers::const_iterator it = labels->begin(),
|
1903
1908
|
last = labels->end();
|
1904
1909
|
it != last; ++it) {
|
@@ -1912,61 +1917,59 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
1912
1917
|
|
1913
1918
|
bool TargetsContainsLabel(const Identifier* const label) const {
|
1914
1919
|
assert(label != NULL);
|
1915
|
-
for (Target* target = target_;
|
1920
|
+
for (const Target* target = target_;
|
1916
1921
|
target != NULL;
|
1917
1922
|
target = target->previous()) {
|
1918
|
-
if (ContainsLabel(target->
|
1923
|
+
if (ContainsLabel(target->labels(), label)) {
|
1919
1924
|
return true;
|
1920
1925
|
}
|
1921
1926
|
}
|
1922
1927
|
return false;
|
1923
1928
|
}
|
1924
1929
|
|
1925
|
-
BreakableStatement
|
1930
|
+
BreakableStatement** LookupBreakableTarget(
|
1926
1931
|
const Identifier* const label) const {
|
1927
1932
|
assert(label != NULL);
|
1928
|
-
for (
|
1933
|
+
for (Target* target = target_;
|
1929
1934
|
target != NULL;
|
1930
1935
|
target = target->previous()) {
|
1931
|
-
if (ContainsLabel(target->
|
1936
|
+
if (ContainsLabel(target->labels(), label)) {
|
1932
1937
|
return target->node();
|
1933
1938
|
}
|
1934
1939
|
}
|
1935
1940
|
return NULL;
|
1936
1941
|
}
|
1937
1942
|
|
1938
|
-
BreakableStatement
|
1939
|
-
for (
|
1943
|
+
BreakableStatement** LookupBreakableTarget() const {
|
1944
|
+
for (Target* target = target_;
|
1940
1945
|
target != NULL;
|
1941
1946
|
target = target->previous()) {
|
1942
|
-
if (target->
|
1947
|
+
if (target->IsAnonymous()) {
|
1943
1948
|
return target->node();
|
1944
1949
|
}
|
1945
1950
|
}
|
1946
1951
|
return NULL;
|
1947
1952
|
}
|
1948
1953
|
|
1949
|
-
IterationStatement
|
1954
|
+
IterationStatement** LookupContinuableTarget(
|
1950
1955
|
const Identifier* const label) const {
|
1951
1956
|
assert(label != NULL);
|
1952
|
-
for (
|
1957
|
+
for (Target* target = target_;
|
1953
1958
|
target != NULL;
|
1954
1959
|
target = target->previous()) {
|
1955
|
-
|
1956
|
-
|
1957
|
-
return iter;
|
1960
|
+
if (target->IsIteration() && ContainsLabel(target->labels(), label)) {
|
1961
|
+
return reinterpret_cast<IterationStatement**>(target->node());
|
1958
1962
|
}
|
1959
1963
|
}
|
1960
1964
|
return NULL;
|
1961
1965
|
}
|
1962
1966
|
|
1963
|
-
IterationStatement
|
1964
|
-
for (
|
1967
|
+
IterationStatement** LookupContinuableTarget() const {
|
1968
|
+
for (Target* target = target_;
|
1965
1969
|
target != NULL;
|
1966
1970
|
target = target->previous()) {
|
1967
|
-
|
1968
|
-
|
1969
|
-
return iter;
|
1971
|
+
if (target->IsIteration()) {
|
1972
|
+
return reinterpret_cast<IterationStatement**>(target->node());
|
1970
1973
|
}
|
1971
1974
|
}
|
1972
1975
|
return NULL;
|
@@ -2050,6 +2053,9 @@ class Parser : private Noncopyable<Parser<Factory> >::type {
|
|
2050
2053
|
inline void set_target(Target* target) {
|
2051
2054
|
target_ = target;
|
2052
2055
|
}
|
2056
|
+
inline Factory* factory() const {
|
2057
|
+
return factory_;
|
2058
|
+
}
|
2053
2059
|
inline Identifiers* labels() const {
|
2054
2060
|
return labels_;
|
2055
2061
|
}
|