iv-phonic 0.0.9 → 0.1.0
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/Rakefile +1 -1
- data/ext/include/iv/ast.h +63 -77
- data/ext/include/iv/ast_factory.h +25 -28
- data/ext/include/iv/character.h +4 -4
- data/ext/include/iv/cmdline.h +127 -2
- data/ext/include/iv/conversions.h +25 -2
- data/ext/include/iv/lexer.h +17 -11
- data/ext/include/iv/parser.h +137 -77
- data/ext/include/iv/token.h +30 -18
- data/ext/iv/phonic/factory.h +26 -21
- data/ext/iv/phonic/parser.h +1 -1
- metadata +4 -20
data/ext/include/iv/lexer.h
CHANGED
@@ -262,7 +262,7 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
262
262
|
Advance();
|
263
263
|
if (Chars::IsDecimalDigit(c_)) {
|
264
264
|
// float number parse
|
265
|
-
token = ScanNumber(
|
265
|
+
token = ScanNumber<true>();
|
266
266
|
} else {
|
267
267
|
token = Token::PERIOD;
|
268
268
|
}
|
@@ -342,7 +342,7 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
342
342
|
if (Chars::IsIdentifierStart(c_)) {
|
343
343
|
token = ScanIdentifier<LexType>(strict);
|
344
344
|
} else if (Chars::IsDecimalDigit(c_)) {
|
345
|
-
token = ScanNumber(
|
345
|
+
token = ScanNumber<false>();
|
346
346
|
} else if (Chars::IsLineTerminator(c_)) {
|
347
347
|
SkipLineTerminator();
|
348
348
|
has_line_terminator_before_next_ = true;
|
@@ -733,7 +733,8 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
733
733
|
return true;
|
734
734
|
}
|
735
735
|
|
736
|
-
|
736
|
+
template<bool period>
|
737
|
+
Token::Type ScanNumber() {
|
737
738
|
buffer8_.clear();
|
738
739
|
State type = DECIMAL;
|
739
740
|
if (period) {
|
@@ -798,16 +799,21 @@ class Lexer: private Noncopyable<Lexer<Source> >::type {
|
|
798
799
|
return Token::ILLEGAL;
|
799
800
|
}
|
800
801
|
|
801
|
-
|
802
|
-
|
803
|
-
for (typename std::vector<char>::const_iterator it = buffer8_.begin(),
|
804
|
-
last = buffer8_.end(); it != last; ++it) {
|
805
|
-
val = val * 8 + (*it - '0');
|
806
|
-
}
|
807
|
-
numeric_ = val;
|
808
|
-
} else {
|
802
|
+
|
803
|
+
if (type == DECIMAL) {
|
809
804
|
const std::string buf(buffer8_.begin(), buffer8_.end());
|
810
805
|
numeric_ = std::atof(buf.c_str());
|
806
|
+
} else if (type == HEX) {
|
807
|
+
assert(buffer8_.size() > 2); // first 0x
|
808
|
+
numeric_ = ParseIntegerOverflow(buffer8_.begin() + 2,
|
809
|
+
buffer8_.end(),
|
810
|
+
16);
|
811
|
+
} else {
|
812
|
+
assert(type == OCTAL);
|
813
|
+
assert(buffer8_.size() > 1); // first 0
|
814
|
+
numeric_ = ParseIntegerOverflow(buffer8_.begin() + 1,
|
815
|
+
buffer8_.end(),
|
816
|
+
8);
|
811
817
|
}
|
812
818
|
type_ = type;
|
813
819
|
return Token::NUMBER;
|
data/ext/include/iv/parser.h
CHANGED
@@ -135,11 +135,16 @@ const UString ParserData<T>::kSet(
|
|
135
135
|
|
136
136
|
typedef detail::ParserData<None> ParserData;
|
137
137
|
|
138
|
-
template<typename Factory,
|
138
|
+
template<typename Factory,
|
139
|
+
typename Source,
|
140
|
+
bool UseFunctionStatement,
|
141
|
+
bool ReduceExpressions>
|
139
142
|
class Parser
|
140
|
-
: private Noncopyable<
|
143
|
+
: private Noncopyable<
|
144
|
+
Parser<Factory, Source, UseFunctionStatement, ReduceExpressions> >::type {
|
141
145
|
public:
|
142
|
-
typedef Parser<Factory, Source,
|
146
|
+
typedef Parser<Factory, Source,
|
147
|
+
UseFunctionStatement, ReduceExpressions> this_type;
|
143
148
|
typedef this_type parser_type;
|
144
149
|
typedef Lexer<Source> lexer_type;
|
145
150
|
#define V(AST) typedef typename ast::AST<Factory> AST;
|
@@ -461,16 +466,17 @@ class Parser
|
|
461
466
|
// | StatementList Statement
|
462
467
|
Block* ParseBlock(bool *res) {
|
463
468
|
assert(token_ == Token::LBRACE);
|
464
|
-
|
469
|
+
Statements* const body = factory_->template NewVector<Statement*>();
|
465
470
|
Statement* stmt;
|
466
471
|
Target target(this, Target::kNamedOnlyStatement);
|
467
472
|
|
468
473
|
Next();
|
469
474
|
while (token_ != Token::RBRACE) {
|
470
475
|
stmt = ParseStatement(CHECK);
|
471
|
-
|
476
|
+
body->push_back(stmt);
|
472
477
|
}
|
473
478
|
Next();
|
479
|
+
Block* const block = factory_->NewBlock(body);
|
474
480
|
target.set_node(block);
|
475
481
|
return block;
|
476
482
|
}
|
@@ -480,10 +486,10 @@ class Parser
|
|
480
486
|
// : CONST VariableDeclarationList ';'
|
481
487
|
Statement* ParseVariableStatement(bool *res) {
|
482
488
|
assert(token_ == Token::VAR || token_ == Token::CONST);
|
483
|
-
|
484
|
-
ParseVariableDeclarations(
|
489
|
+
Declarations* const decls = factory_->template NewVector<Declaration*>();
|
490
|
+
ParseVariableDeclarations(decls, token_ == Token::CONST, true, CHECK);
|
485
491
|
ExpectSemicolon(CHECK);
|
486
|
-
return
|
492
|
+
return factory_->NewVariableStatement(token_, decls);
|
487
493
|
}
|
488
494
|
|
489
495
|
// VariableDeclarationList
|
@@ -499,9 +505,10 @@ class Parser
|
|
499
505
|
//
|
500
506
|
// Initialiser
|
501
507
|
// : '=' AssignmentExpression
|
502
|
-
|
503
|
-
|
504
|
-
|
508
|
+
Declarations* ParseVariableDeclarations(Declarations* decls,
|
509
|
+
bool is_const,
|
510
|
+
bool contains_in,
|
511
|
+
bool *res) {
|
505
512
|
Identifier* name;
|
506
513
|
Expression* expr;
|
507
514
|
Declaration* decl;
|
@@ -533,11 +540,11 @@ class Parser
|
|
533
540
|
// Undefined Expression
|
534
541
|
decl = factory_->NewDeclaration(name, factory_->NewUndefined());
|
535
542
|
}
|
536
|
-
|
537
|
-
scope_->AddUnresolved(name,
|
543
|
+
decls->push_back(decl);
|
544
|
+
scope_->AddUnresolved(name, is_const);
|
538
545
|
} while (token_ == Token::COMMA);
|
539
546
|
|
540
|
-
return
|
547
|
+
return decls;
|
541
548
|
}
|
542
549
|
|
543
550
|
// EmptyStatement
|
@@ -649,8 +656,11 @@ class Parser
|
|
649
656
|
|
650
657
|
if (token_ != Token::SEMICOLON) {
|
651
658
|
if (token_ == Token::VAR || token_ == Token::CONST) {
|
652
|
-
|
653
|
-
|
659
|
+
Declarations* const decls =
|
660
|
+
factory_->template NewVector<Declaration*>();
|
661
|
+
ParseVariableDeclarations(decls, token_ == Token::CONST, false, CHECK);
|
662
|
+
VariableStatement* const var =
|
663
|
+
factory_->NewVariableStatement(token_, decls);
|
654
664
|
init = var;
|
655
665
|
if (token_ == Token::IN) {
|
656
666
|
// for in loop
|
@@ -841,13 +851,13 @@ class Parser
|
|
841
851
|
// | '{' CaseClauses_opt DefaultClause CaseClauses_opt '}'
|
842
852
|
Statement* ParseSwitchStatement(bool *res) {
|
843
853
|
assert(token_ == Token::SWITCH);
|
844
|
-
CaseClause
|
854
|
+
CaseClause* case_clause;
|
845
855
|
Next();
|
846
856
|
|
847
857
|
EXPECT(Token::LPAREN);
|
848
858
|
|
849
|
-
Expression
|
850
|
-
|
859
|
+
Expression* expr = ParseExpression(true, CHECK);
|
860
|
+
CaseClauses* clauses = factory_->template NewVector<CaseClause*>();
|
851
861
|
Target target(this, Target::kSwitchStatement);
|
852
862
|
|
853
863
|
EXPECT(Token::RPAREN);
|
@@ -869,10 +879,12 @@ class Parser
|
|
869
879
|
default_found = true;
|
870
880
|
}
|
871
881
|
}
|
872
|
-
|
882
|
+
clauses->push_back(case_clause);
|
873
883
|
}
|
874
884
|
Next();
|
875
885
|
|
886
|
+
SwitchStatement* const switch_stmt =
|
887
|
+
factory_->NewSwitchStatement(expr, clauses);
|
876
888
|
target.set_node(switch_stmt);
|
877
889
|
return switch_stmt;
|
878
890
|
}
|
@@ -888,16 +900,14 @@ class Parser
|
|
888
900
|
// : DEFAULT ':' StatementList_opt
|
889
901
|
CaseClause* ParseCaseClause(bool *res) {
|
890
902
|
assert(token_ == Token::CASE || token_ == Token::DEFAULT);
|
891
|
-
|
892
|
-
|
903
|
+
Expression* expr = NULL;
|
904
|
+
Statements* const body = factory_->template NewVector<Statement*>();
|
893
905
|
|
894
906
|
if (token_ == Token::CASE) {
|
895
907
|
Next();
|
896
|
-
|
897
|
-
clause = factory_->NewCaseClause(false, expr);
|
908
|
+
expr = ParseExpression(true, CHECK);
|
898
909
|
} else {
|
899
910
|
EXPECT(Token::DEFAULT);
|
900
|
-
clause = factory_->NewCaseClause(true, NULL);
|
901
911
|
}
|
902
912
|
|
903
913
|
EXPECT(Token::COLON);
|
@@ -905,11 +915,11 @@ class Parser
|
|
905
915
|
while (token_ != Token::RBRACE &&
|
906
916
|
token_ != Token::CASE &&
|
907
917
|
token_ != Token::DEFAULT) {
|
908
|
-
stmt = ParseStatement(CHECK);
|
909
|
-
|
918
|
+
Statement* const stmt = ParseStatement(CHECK);
|
919
|
+
body->push_back(stmt);
|
910
920
|
}
|
911
921
|
|
912
|
-
return
|
922
|
+
return factory_->NewCaseClause(expr == NULL, expr, body);
|
913
923
|
}
|
914
924
|
|
915
925
|
// ThrowStatement
|
@@ -1023,7 +1033,7 @@ class Parser
|
|
1023
1033
|
Identifier* const label = expr->AsIdentifier();
|
1024
1034
|
const bool exist_labels = labels;
|
1025
1035
|
if (!exist_labels) {
|
1026
|
-
labels = factory_->
|
1036
|
+
labels = factory_->template NewVector<Identifier*>();
|
1027
1037
|
}
|
1028
1038
|
if (ContainsLabel(labels, label) || TargetsContainsLabel(label)) {
|
1029
1039
|
// duplicate label
|
@@ -1188,7 +1198,7 @@ class Parser
|
|
1188
1198
|
op = token_;
|
1189
1199
|
Next();
|
1190
1200
|
right = ParseUnaryExpression(CHECK);
|
1191
|
-
left = ReduceBinaryOperation(op, left, right);
|
1201
|
+
left = ReduceBinaryOperation<ReduceExpressions>(op, left, right);
|
1192
1202
|
}
|
1193
1203
|
if (prec < 1) return left;
|
1194
1204
|
|
@@ -1198,7 +1208,7 @@ class Parser
|
|
1198
1208
|
op = token_;
|
1199
1209
|
Next();
|
1200
1210
|
right = ParseBinaryExpression(contains_in, 0, CHECK);
|
1201
|
-
left = ReduceBinaryOperation(op, left, right);
|
1211
|
+
left = ReduceBinaryOperation<ReduceExpressions>(op, left, right);
|
1202
1212
|
}
|
1203
1213
|
if (prec < 2) return left;
|
1204
1214
|
|
@@ -1209,7 +1219,7 @@ class Parser
|
|
1209
1219
|
op = token_;
|
1210
1220
|
Next();
|
1211
1221
|
right = ParseBinaryExpression(contains_in, 1, CHECK);
|
1212
|
-
left = ReduceBinaryOperation(op, left, right);
|
1222
|
+
left = ReduceBinaryOperation<ReduceExpressions>(op, left, right);
|
1213
1223
|
}
|
1214
1224
|
if (prec < 3) return left;
|
1215
1225
|
|
@@ -1241,7 +1251,7 @@ class Parser
|
|
1241
1251
|
op = token_;
|
1242
1252
|
Next();
|
1243
1253
|
right = ParseBinaryExpression(contains_in, 4, CHECK);
|
1244
|
-
left = ReduceBinaryOperation(op, left, right);
|
1254
|
+
left = ReduceBinaryOperation<ReduceExpressions>(op, left, right);
|
1245
1255
|
}
|
1246
1256
|
if (prec < 6) return left;
|
1247
1257
|
|
@@ -1250,7 +1260,7 @@ class Parser
|
|
1250
1260
|
op = token_;
|
1251
1261
|
Next();
|
1252
1262
|
right = ParseBinaryExpression(contains_in, 5, CHECK);
|
1253
|
-
left = ReduceBinaryOperation(op, left, right);
|
1263
|
+
left = ReduceBinaryOperation<ReduceExpressions>(op, left, right);
|
1254
1264
|
}
|
1255
1265
|
if (prec < 7) return left;
|
1256
1266
|
|
@@ -1259,7 +1269,7 @@ class Parser
|
|
1259
1269
|
op = token_;
|
1260
1270
|
Next();
|
1261
1271
|
right = ParseBinaryExpression(contains_in, 6, CHECK);
|
1262
|
-
left = ReduceBinaryOperation(op, left, right);
|
1272
|
+
left = ReduceBinaryOperation<ReduceExpressions>(op, left, right);
|
1263
1273
|
}
|
1264
1274
|
if (prec < 8) return left;
|
1265
1275
|
|
@@ -1282,9 +1292,11 @@ class Parser
|
|
1282
1292
|
return left;
|
1283
1293
|
}
|
1284
1294
|
|
1295
|
+
template<bool Reduce>
|
1285
1296
|
Expression* ReduceBinaryOperation(Token::Type op,
|
1286
1297
|
Expression* left,
|
1287
|
-
Expression* right
|
1298
|
+
Expression* right,
|
1299
|
+
typename enable_if_c<Reduce>::type* = 0) {
|
1288
1300
|
if (left->AsNumberLiteral() &&
|
1289
1301
|
right->AsNumberLiteral()) {
|
1290
1302
|
const double l_val = left->AsNumberLiteral()->value();
|
@@ -1354,6 +1366,14 @@ class Parser
|
|
1354
1366
|
}
|
1355
1367
|
}
|
1356
1368
|
|
1369
|
+
template<bool Reduce>
|
1370
|
+
Expression* ReduceBinaryOperation(Token::Type op,
|
1371
|
+
Expression* left,
|
1372
|
+
Expression* right,
|
1373
|
+
typename enable_if_c<!Reduce>::type* = 0) {
|
1374
|
+
return factory_->NewBinaryOperation(op, left, right);
|
1375
|
+
}
|
1376
|
+
|
1357
1377
|
// UnaryExpression
|
1358
1378
|
// : PostfixExpression
|
1359
1379
|
// | DELETE UnaryExpression
|
@@ -1511,11 +1531,11 @@ class Parser
|
|
1511
1531
|
} else {
|
1512
1532
|
Next();
|
1513
1533
|
Expression* const target = ParseMemberExpression(false, CHECK);
|
1514
|
-
|
1534
|
+
Expressions* const args = factory_->template NewVector<Expression*>();
|
1515
1535
|
if (token_ == Token::LPAREN) {
|
1516
|
-
ParseArguments(
|
1536
|
+
ParseArguments(args, CHECK);
|
1517
1537
|
}
|
1518
|
-
expr =
|
1538
|
+
expr = factory_->NewConstructorCall(target, args);
|
1519
1539
|
}
|
1520
1540
|
while (true) {
|
1521
1541
|
switch (token_) {
|
@@ -1537,9 +1557,10 @@ class Parser
|
|
1537
1557
|
|
1538
1558
|
case Token::LPAREN:
|
1539
1559
|
if (allow_call) {
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1560
|
+
Expressions* const args =
|
1561
|
+
factory_->template NewVector<Expression*>();
|
1562
|
+
ParseArguments(args, CHECK);
|
1563
|
+
expr = factory_->NewFunctionCall(expr, args);
|
1543
1564
|
} else {
|
1544
1565
|
return expr;
|
1545
1566
|
}
|
@@ -1653,20 +1674,20 @@ class Parser
|
|
1653
1674
|
// ArgumentList
|
1654
1675
|
// : AssignmentExpression
|
1655
1676
|
// | ArgumentList ',' AssignmentExpression
|
1656
|
-
template<typename
|
1657
|
-
|
1677
|
+
template<typename Container>
|
1678
|
+
Container* ParseArguments(Container* container, bool *res) {
|
1658
1679
|
Next();
|
1659
1680
|
if (token_ != Token::RPAREN) {
|
1660
1681
|
Expression* const first = ParseAssignmentExpression(true, CHECK);
|
1661
|
-
|
1682
|
+
container->push_back(first);
|
1662
1683
|
while (token_ == Token::COMMA) {
|
1663
1684
|
Next();
|
1664
1685
|
Expression* const expr = ParseAssignmentExpression(true, CHECK);
|
1665
|
-
|
1686
|
+
container->push_back(expr);
|
1666
1687
|
}
|
1667
1688
|
}
|
1668
1689
|
EXPECT(Token::RPAREN);
|
1669
|
-
return
|
1690
|
+
return container;
|
1670
1691
|
}
|
1671
1692
|
|
1672
1693
|
Expression* ParseRegExpLiteral(bool contains_eq, bool *res) {
|
@@ -1700,23 +1721,22 @@ class Parser
|
|
1700
1721
|
// : ','
|
1701
1722
|
// | Elision ','
|
1702
1723
|
Expression* ParseArrayLiteral(bool *res) {
|
1703
|
-
|
1704
|
-
Expression* expr;
|
1724
|
+
Expressions* const items = factory_->template NewVector<Expression*>();
|
1705
1725
|
Next();
|
1706
1726
|
while (token_ != Token::RBRACK) {
|
1707
1727
|
if (token_ == Token::COMMA) {
|
1708
1728
|
// when Token::COMMA, only increment length
|
1709
|
-
|
1729
|
+
items->push_back(NULL);
|
1710
1730
|
} else {
|
1711
|
-
expr = ParseAssignmentExpression(true, CHECK);
|
1712
|
-
|
1731
|
+
Expression* const expr = ParseAssignmentExpression(true, CHECK);
|
1732
|
+
items->push_back(expr);
|
1713
1733
|
}
|
1714
1734
|
if (token_ != Token::RBRACK) {
|
1715
1735
|
EXPECT(Token::COMMA);
|
1716
1736
|
}
|
1717
1737
|
}
|
1718
1738
|
Next();
|
1719
|
-
return
|
1739
|
+
return factory_->NewArrayLiteral(items);
|
1720
1740
|
}
|
1721
1741
|
|
1722
1742
|
|
@@ -1746,7 +1766,9 @@ class Parser
|
|
1746
1766
|
// : IDENTIFIER
|
1747
1767
|
Expression* ParseObjectLiteral(bool *res) {
|
1748
1768
|
typedef std::tr1::unordered_map<IdentifierKey, int> ObjectMap;
|
1749
|
-
|
1769
|
+
typedef typename ObjectLiteral::Property Property;
|
1770
|
+
typedef typename ObjectLiteral::Properties Properties;
|
1771
|
+
Properties* const prop = factory_->template NewVector<Property>();
|
1750
1772
|
ObjectMap map;
|
1751
1773
|
Expression* expr;
|
1752
1774
|
Identifier* ident;
|
@@ -1763,7 +1785,7 @@ class Parser
|
|
1763
1785
|
ident = ParseIdentifier(
|
1764
1786
|
is_get ? ParserData::kGet : ParserData::kSet);
|
1765
1787
|
expr = ParseAssignmentExpression(true, CHECK);
|
1766
|
-
|
1788
|
+
ObjectLiteral::AddDataProperty(prop, ident, expr);
|
1767
1789
|
typename ObjectMap::iterator it = map.find(ident);
|
1768
1790
|
if (it == map.end()) {
|
1769
1791
|
map.insert(std::make_pair(ident, ObjectLiteral::DATA));
|
@@ -1794,7 +1816,7 @@ class Parser
|
|
1794
1816
|
FunctionLiteral::EXPRESSION,
|
1795
1817
|
(is_get) ? FunctionLiteral::GETTER : FunctionLiteral::SETTER,
|
1796
1818
|
CHECK);
|
1797
|
-
|
1819
|
+
ObjectLiteral::AddAccessor(prop, type, ident, expr);
|
1798
1820
|
typename ObjectMap::iterator it = map.find(ident);
|
1799
1821
|
if (it == map.end()) {
|
1800
1822
|
map.insert(std::make_pair(ident, type));
|
@@ -1823,7 +1845,7 @@ class Parser
|
|
1823
1845
|
}
|
1824
1846
|
EXPECT(Token::COLON);
|
1825
1847
|
expr = ParseAssignmentExpression(true, CHECK);
|
1826
|
-
|
1848
|
+
ObjectLiteral::AddDataProperty(prop, ident, expr);
|
1827
1849
|
typename ObjectMap::iterator it = map.find(ident);
|
1828
1850
|
if (it == map.end()) {
|
1829
1851
|
map.insert(std::make_pair(ident, ObjectLiteral::DATA));
|
@@ -1849,7 +1871,7 @@ class Parser
|
|
1849
1871
|
}
|
1850
1872
|
}
|
1851
1873
|
Next();
|
1852
|
-
return
|
1874
|
+
return factory_->NewObjectLiteral(prop);
|
1853
1875
|
}
|
1854
1876
|
|
1855
1877
|
FunctionLiteral* ParseFunctionLiteral(
|
@@ -1866,7 +1888,8 @@ class Parser
|
|
1866
1888
|
kDetectArgumentsName,
|
1867
1889
|
kDetectEvalParameter,
|
1868
1890
|
kDetectArgumentsParameter,
|
1869
|
-
kDetectDuplicateParameter
|
1891
|
+
kDetectDuplicateParameter,
|
1892
|
+
kDetectFutureReservedWords
|
1870
1893
|
} throw_error_if_strict_code = kDetectNone;
|
1871
1894
|
|
1872
1895
|
FunctionLiteral* const literal = factory_->NewFunctionLiteral(decl_type);
|
@@ -1874,15 +1897,23 @@ class Parser
|
|
1874
1897
|
|
1875
1898
|
if (arg_type == FunctionLiteral::GENERAL) {
|
1876
1899
|
assert(token_ == Token::FUNCTION);
|
1877
|
-
Next();
|
1878
|
-
|
1900
|
+
Next(true); // preparing for strict directive
|
1901
|
+
const Token::Type current = token_;
|
1902
|
+
if (current == Token::IDENTIFIER ||
|
1903
|
+
Token::IsAddedFutureReservedWordInStrictCode(current)) {
|
1879
1904
|
Identifier* const name = ParseIdentifier(lexer_.Buffer());
|
1880
1905
|
literal->SetName(name);
|
1881
|
-
|
1882
|
-
|
1883
|
-
throw_error_if_strict_code = (val == kEval) ?
|
1884
|
-
kDetectEvalName : kDetectArgumentsName;
|
1906
|
+
if (Token::IsAddedFutureReservedWordInStrictCode(current)) {
|
1907
|
+
throw_error_if_strict_code = kDetectFutureReservedWords;
|
1885
1908
|
throw_error_if_strict_code_line = lexer_.line_number();
|
1909
|
+
} else {
|
1910
|
+
assert(current == Token::IDENTIFIER);
|
1911
|
+
const EvalOrArguments val = IsEvalOrArguments(name);
|
1912
|
+
if (val) {
|
1913
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1914
|
+
kDetectEvalName : kDetectArgumentsName;
|
1915
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1916
|
+
}
|
1886
1917
|
}
|
1887
1918
|
} else if (decl_type == FunctionLiteral::DECLARATION ||
|
1888
1919
|
decl_type == FunctionLiteral::STATEMENT) {
|
@@ -1895,21 +1926,32 @@ class Parser
|
|
1895
1926
|
literal->set_start_position(lexer_.begin_position());
|
1896
1927
|
|
1897
1928
|
// '(' FormalParameterList_opt ')'
|
1898
|
-
|
1929
|
+
IS(Token::LPAREN);
|
1930
|
+
Next(true); // preparing for strict directive
|
1899
1931
|
|
1900
1932
|
if (arg_type == FunctionLiteral::GETTER) {
|
1901
1933
|
// if getter, parameter count is 0
|
1902
1934
|
EXPECT(Token::RPAREN);
|
1903
1935
|
} else if (arg_type == FunctionLiteral::SETTER) {
|
1904
1936
|
// if setter, parameter count is 1
|
1905
|
-
|
1937
|
+
const Token::Type current = token_;
|
1938
|
+
if (current != Token::IDENTIFIER &&
|
1939
|
+
!Token::IsAddedFutureReservedWordInStrictCode(current)) {
|
1940
|
+
IS(Token::IDENTIFIER);
|
1941
|
+
}
|
1906
1942
|
Identifier* const ident = ParseIdentifier(lexer_.Buffer());
|
1907
1943
|
if (!throw_error_if_strict_code) {
|
1908
|
-
|
1909
|
-
|
1910
|
-
throw_error_if_strict_code = (val == kEval) ?
|
1911
|
-
kDetectEvalParameter : kDetectArgumentsParameter;
|
1944
|
+
if (Token::IsAddedFutureReservedWordInStrictCode(current)) {
|
1945
|
+
throw_error_if_strict_code = kDetectFutureReservedWords;
|
1912
1946
|
throw_error_if_strict_code_line = lexer_.line_number();
|
1947
|
+
} else {
|
1948
|
+
assert(current == Token::IDENTIFIER);
|
1949
|
+
const EvalOrArguments val = IsEvalOrArguments(ident);
|
1950
|
+
if (val) {
|
1951
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1952
|
+
kDetectEvalName : kDetectArgumentsName;
|
1953
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1954
|
+
}
|
1913
1955
|
}
|
1914
1956
|
}
|
1915
1957
|
literal->AddParameter(ident);
|
@@ -1917,14 +1959,24 @@ class Parser
|
|
1917
1959
|
} else {
|
1918
1960
|
if (token_ != Token::RPAREN) {
|
1919
1961
|
do {
|
1920
|
-
|
1962
|
+
const Token::Type current = token_;
|
1963
|
+
if (current != Token::IDENTIFIER &&
|
1964
|
+
!Token::IsAddedFutureReservedWordInStrictCode(current)) {
|
1965
|
+
IS(Token::IDENTIFIER);
|
1966
|
+
}
|
1921
1967
|
Identifier* const ident = ParseIdentifier(lexer_.Buffer());
|
1922
1968
|
if (!throw_error_if_strict_code) {
|
1923
|
-
|
1924
|
-
|
1925
|
-
throw_error_if_strict_code = (val == kEval) ?
|
1926
|
-
kDetectEvalParameter : kDetectArgumentsParameter;
|
1969
|
+
if (Token::IsAddedFutureReservedWordInStrictCode(current)) {
|
1970
|
+
throw_error_if_strict_code = kDetectFutureReservedWords;
|
1927
1971
|
throw_error_if_strict_code_line = lexer_.line_number();
|
1972
|
+
} else {
|
1973
|
+
assert(current == Token::IDENTIFIER);
|
1974
|
+
const EvalOrArguments val = IsEvalOrArguments(ident);
|
1975
|
+
if (val) {
|
1976
|
+
throw_error_if_strict_code = (val == kEval) ?
|
1977
|
+
kDetectEvalName : kDetectArgumentsName;
|
1978
|
+
throw_error_if_strict_code_line = lexer_.line_number();
|
1979
|
+
}
|
1928
1980
|
}
|
1929
1981
|
if ((!throw_error_if_strict_code) &&
|
1930
1982
|
(param_set.find(ident) != param_set.end())) {
|
@@ -1935,7 +1987,7 @@ class Parser
|
|
1935
1987
|
literal->AddParameter(ident);
|
1936
1988
|
param_set.insert(ident);
|
1937
1989
|
if (token_ == Token::COMMA) {
|
1938
|
-
Next();
|
1990
|
+
Next(true);
|
1939
1991
|
} else {
|
1940
1992
|
break;
|
1941
1993
|
}
|
@@ -1983,6 +2035,11 @@ class Parser
|
|
1983
2035
|
"duplicate parameter not allowed in strict code",
|
1984
2036
|
throw_error_if_strict_code_line);
|
1985
2037
|
break;
|
2038
|
+
case kDetectFutureReservedWords:
|
2039
|
+
RAISE_WITH_NUMBER(
|
2040
|
+
"FutureReservedWords is found in strict code",
|
2041
|
+
throw_error_if_strict_code_line);
|
2042
|
+
break;
|
1986
2043
|
}
|
1987
2044
|
}
|
1988
2045
|
literal->set_end_position(lexer_.end_position());
|
@@ -2136,6 +2193,9 @@ class Parser
|
|
2136
2193
|
inline Token::Type Next() {
|
2137
2194
|
return token_ = lexer_.Next<IdentifyReservedWords>(strict_);
|
2138
2195
|
}
|
2196
|
+
inline Token::Type Next(bool strict) {
|
2197
|
+
return token_ = lexer_.Next<IdentifyReservedWords>(strict);
|
2198
|
+
}
|
2139
2199
|
inline Token::Type Peek() const {
|
2140
2200
|
return token_;
|
2141
2201
|
}
|
data/ext/include/iv/token.h
CHANGED
@@ -125,29 +125,32 @@ class Token {
|
|
125
125
|
FINAL, // final
|
126
126
|
FLOAT, // float
|
127
127
|
GOTO, // goto
|
128
|
-
IMPLEMENTS, // implements
|
129
128
|
IMPORT, // import
|
130
129
|
INT, // int
|
131
|
-
INTERFACE, // interface
|
132
130
|
LONG, // long
|
133
131
|
NATIVE, // native
|
134
|
-
PACKAGE, // package
|
135
|
-
PRIVATE, // private
|
136
|
-
PROTECTED, // protected
|
137
|
-
PUBLIC, // public
|
138
132
|
SHORT, // short
|
139
|
-
STATIC, // static
|
140
133
|
SUPER, // super
|
141
134
|
SYNCHRONIZED, // synchronized
|
142
135
|
THROWS, // throws
|
143
136
|
TRANSIENT, // transient
|
144
137
|
VOLATILE, // volatile
|
145
|
-
LET, // let
|
146
|
-
YIELD, // yield
|
147
138
|
|
148
139
|
GET, // get
|
149
140
|
SET, // set
|
150
141
|
|
142
|
+
STRICT_FIRST, // STRICT FIRST
|
143
|
+
IMPLEMENTS, // implements
|
144
|
+
LET, // let
|
145
|
+
PRIVATE, // private
|
146
|
+
PUBLIC, // public
|
147
|
+
YIELD, // yield
|
148
|
+
INTERFACE, // interface
|
149
|
+
PACKAGE, // package
|
150
|
+
PROTECTED, // protected
|
151
|
+
STATIC, // static
|
152
|
+
STRICT_LAST, // STRICT LAST
|
153
|
+
|
151
154
|
NULL_LITERAL, // NULL LITERAL
|
152
155
|
FALSE_LITERAL, // FALSE LITERAL
|
153
156
|
TRUE_LITERAL, // TRUE LITERAL
|
@@ -165,12 +168,19 @@ class Token {
|
|
165
168
|
static inline bool IsAssignOp(Token::Type type) {
|
166
169
|
return Token::ASSIGN_FIRST < type && type < Token::ASSIGN_LAST;
|
167
170
|
}
|
171
|
+
|
172
|
+
static inline bool IsAddedFutureReservedWordInStrictCode(Token::Type type) {
|
173
|
+
return Token::STRICT_FIRST < type && type < Token::STRICT_LAST;
|
174
|
+
}
|
175
|
+
|
168
176
|
static inline const char* ToString(Token::Type type) {
|
169
177
|
assert(0 <= type && type < NUM_TOKENS);
|
170
178
|
assert(type != Token::ASSIGN_FIRST &&
|
171
179
|
type != Token::ASSIGN_LAST &&
|
172
180
|
type != Token::REL_FIRST &&
|
173
181
|
type != Token::REL_LAST &&
|
182
|
+
type != Token::STRICT_FIRST &&
|
183
|
+
type != Token::STRICT_LAST &&
|
174
184
|
type != Token::STRING &&
|
175
185
|
type != Token::NUMBER &&
|
176
186
|
type != Token::IDENTIFIER &&
|
@@ -278,27 +288,29 @@ const char* TokenContents<T>::kContents[Token::NUM_TOKENS] = {
|
|
278
288
|
"final",
|
279
289
|
"float",
|
280
290
|
"goto",
|
281
|
-
"implements",
|
282
291
|
"import",
|
283
292
|
"int",
|
284
|
-
"interface",
|
285
293
|
"long",
|
286
294
|
"native",
|
287
|
-
"package",
|
288
|
-
"private",
|
289
|
-
"protected",
|
290
|
-
"public",
|
291
295
|
"short",
|
292
|
-
"static",
|
293
296
|
"super",
|
294
297
|
"synchronized",
|
295
298
|
"throws",
|
296
299
|
"transient",
|
297
300
|
"volatile",
|
298
|
-
"let",
|
299
|
-
"yield",
|
300
301
|
"get",
|
301
302
|
"set",
|
303
|
+
NULL,
|
304
|
+
"implements",
|
305
|
+
"let",
|
306
|
+
"private",
|
307
|
+
"public",
|
308
|
+
"yield",
|
309
|
+
"interface",
|
310
|
+
"package",
|
311
|
+
"protected",
|
312
|
+
"static",
|
313
|
+
NULL,
|
302
314
|
"null",
|
303
315
|
"false",
|
304
316
|
"true",
|