violet 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.
@@ -0,0 +1,78 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Violet
4
+ # Public: A specialized `Hash` for storing and retrieving information about
5
+ # lexed JavaScript tokens.
6
+ class Token < Hash
7
+ # Public: A `Hash` that maps the 14 different token kinds to their
8
+ # corresponding numeric constants.
9
+ Types = {
10
+ :pattern => 1,
11
+ :identifier => 2,
12
+ :hexadecimal_number => 3,
13
+ :decimal_number => 4,
14
+ :single_quoted_string => 5,
15
+ :double_quoted_string => 6,
16
+ :line_comment => 7,
17
+ :block_comment => 8,
18
+ :whitespace => 9,
19
+ :line_terminator => 10,
20
+ :punctuator => 11,
21
+ :eof => 12,
22
+ :asi => 13,
23
+ :error => 14
24
+ }
25
+
26
+ # Public: Creates a new `Token`.
27
+ #
28
+ # lexer - The `Lexer` instance associated with this token.
29
+ # kind - The `Symbol`-ized token kind.
30
+ # position - A `Range` that specifies the initial and terminal positions of
31
+ # the token.
32
+ def initialize(lexer, kind, position)
33
+ super()
34
+ self.update({
35
+ :name => Types[kind],
36
+ :start => position.begin,
37
+ :stop => position.end,
38
+ :value => lexer.source[position],
39
+ :size => position.end - position.begin,
40
+ :line => lexer.line,
41
+ :column => lexer.column,
42
+ :lines => 0,
43
+ # The position of the token in the token stream.
44
+ :index => 0
45
+ })
46
+ end
47
+
48
+ # Public: Associates the `value` with the `key`.
49
+ #
50
+ # key - The hash key.
51
+ # value - The value to associate with the key.
52
+ #
53
+ # Returns the `Token` instance.
54
+ # Raises an `ArgumentError` if the `:pairs` key is set for a non-regular
55
+ # expression.
56
+ def store(key, value)
57
+ case key
58
+ when :pairs, "pairs"
59
+ # The `pairs` attribute may not be set for non-regular expressions.
60
+ raise ArgumentError, "This token is not a regular expression." unless self[:name] == Types[:pattern]
61
+ when :error, "error"
62
+ # Wrap the error message in a `LexerError` instance unless it is
63
+ # already a `Violet::Error`.
64
+ value = Violet::LexerError.new(value) unless value.kind_of?(Violet::Error)
65
+ end
66
+ super(key, value)
67
+ end
68
+
69
+ alias_method :[]=, :store
70
+
71
+ # Public: Returns a human-readable `String` representation of the token.
72
+ def inspect
73
+ name, start, size, line, column, value = values_at(:name, :start, :size, :line, :column, :value)
74
+ "#<Violet::Token(#{name}, position: #{start}, length: #{size}, line: #{line}, column: #{column}) #{value.inspect}>"
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,550 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ module Violet
4
+ # Internal: A list of code fragments and expected token counts used to test
5
+ # the lexer and parser. The test cases for each fragment are defined
6
+ # programmatically.
7
+ TEST_ASSERTIONS = [
8
+ # The structure of each test case is [A, B, C?, D].
9
+ # A - The JavaScript code fragment.
10
+ # B - The number of expected tokens. If B is an `Array`, the first value
11
+ # specifies the expected size of the lexer token stream, while the second
12
+ # specifies the size of the parser token stream. Otherwise, the two token
13
+ # streams are assumed to be the same size.
14
+ # C - An optional `Array` of boolean arguments that correspond to each lexed
15
+ # token and specify if the `/` and `/=` tokens may be interpreted as regular
16
+ # expressions or division operators. See `Lexer#tokens` for details.
17
+ # D - A description of the test.
18
+
19
+ # Variable Declarations.
20
+ # ----------------------
21
+ ["var abc;", 4, "Variable Declaration"],
22
+ ["var abc = 5;", 8, "Variable Declaration, Assignment"],
23
+ ["var varwithfunction;", 4, "Variable Declaration, Identifier Containing Reserved Word, `;`"],
24
+ ["var f = function(){;};", 13, "Assignment, Function Expression"],
25
+
26
+ # Comments.
27
+ # ---------
28
+ ["/* */", 1, "Block Comment"],
29
+ ["/** **/", 1, "JSDoc-style Comment"],
30
+ ["hi; // moo", 4, "Trailing Line Comment"],
31
+ ["hi; // moo\n;", 6, "Trailing Line Comment, Linefeed, `;`"],
32
+
33
+ # Single-Quoted Strings.
34
+ # ----------------------
35
+ ["'a'", [1, 2], "Single-Quoted String"],
36
+ ["'a\\n'", [1, 2], "Single-Quoted String With Escaped Linefeed"],
37
+ ["\"a\"", [1, 2], "Double-Quoted String"],
38
+ ["\"a\\n\"", [1, 2], "Double-Quoted String With Escaped Linefeed"],
39
+
40
+ # The following tests do not require automatic semicolon insertion.
41
+ ["'a';", 2, "Single-Quoted String, `;`"],
42
+ ["'a\\n';", 2, "Single-Quoted String With Escaped Linefeed, `;`"],
43
+ ["\"a\";", 2, "Double-Quoted String, `;`"],
44
+ ["\"a\\n\";", 2, "Double-Quoted String With Escaped Linefeed, `;`"],
45
+
46
+ # Numbers.
47
+ # --------
48
+ ["500", [1, 2], "Integer"],
49
+ ["500.", [1, 2], "Double With Trailing Decimal Point"],
50
+ ["500.432", [1, 2], "Double With Decimal Component"],
51
+ [".432432", [1, 2], "Number, 0 < Double < 1"],
52
+
53
+ # Violet-specific unit tests for large numeric values.
54
+ ["3#{"0" * 305};", 2, "Big Integer, `;`"],
55
+ ["3#{"0" * 305}.5;", 2, "Big Double with Decimal Component, `;`"],
56
+ [".1#{"0" * 305};", 2, "Number, 0 < Big Decimal < 1, `;`"],
57
+ ["3#{"0" * 305}e500;", 2, "Big Double with Exponential Component, `;`"],
58
+
59
+ # The following tests do not require automatic semicolon insertion.
60
+ ["500;", 2, "Integer, `;`"],
61
+ ["500.;", 2, "Double With Trailing Decimal Point"],
62
+ ["500.432;", 2, "Double With Decimal Component, `;`"],
63
+ [".432432;", 2, "Number, 0 < Double < 1, `;`"],
64
+
65
+ # Expressions.
66
+ # ------------
67
+ ["(a,b,c)", [7, 8], "Parentheses, Comma-separated identifiers"],
68
+ ["[1,2,abc]", [7, 8], "Array literal"],
69
+ ["{a:1,\"b\":2,c:c}", [13, 19], "Malformed Block"],
70
+
71
+ # The following tests do not require automatic semicolon insertion.
72
+ ["(a,b,c);", 8, "Parentheses, Comma-separated identifiers, `;`"],
73
+ ["[1,2,abc];", 8, "Array literal, `;`"],
74
+ ["var o = {a:1,\"b\":2,c:c};", 20, "Assignment, Object Literal, `;`"],
75
+
76
+ ["var x;\nvar y;", 9, "2 Variable Declarations, Multiple lines"],
77
+ ["var x;\nfunction n(){ }", 13, "Variable, Linefeed, Function Declaration"],
78
+ ["var x;\nfunction n(abc){ }", 14, "Variable, Linefeed, Function Declaration With One Argument"],
79
+ ["var x;\nfunction n(abc, def){ }", 17, "Variable, Linefeed, Function Declaration With Multiple Arguments"],
80
+ ["function n(){ \"hello\"; }", 11, "Function Declaration, Body"],
81
+
82
+ ["/a/;", 2, [true, false], "RegExp Literal, `;`"],
83
+ ["/a/b;", 2, [true, true], "RegExp Literal, Flags, `;`"],
84
+ ["++x;", 3, "Unary Increment, Prefix, `;`"],
85
+ [" / /;", 3, [true, true, false], "RegExp, Leading Whitespace, `;`"],
86
+ ["/ / / / /", [5, 6], [true, false, false, false, true], "RegExp Containing One Space, Space, Division, Space, RegExp Containing One Space"],
87
+
88
+ # Ambiguities.
89
+ # ------------
90
+ ["\"var\";", 2, "Keyword String, `;`"],
91
+ ["\"variable\";", 2, "String Beginning With Keyword, `;`"],
92
+ ["\"somevariable\";", 2, "String Containing Keyword, `;`"],
93
+ ["\"somevar\";", 2, "String Ending With Keyword, `;`"],
94
+
95
+ ["var varwithfunction;", 4, "Keywords should not be matched in identifiers"],
96
+
97
+ ["var o = {a:1};", 12, "Object Literal With Unquoted Property"],
98
+ ["var o = {\"b\":2};", 12, "Object Literal With Quoted Property"],
99
+ ["var o = {c:c};", 12, "Object Literal With Equivalent Property Name and Identifier"],
100
+
101
+ ["/a/ / /b/;", 6, [true, true, false, false, true, false], "RegExp, Division, RegExp, `;`"],
102
+ ["a/b/c;", 6, "Triple Division (Identifier / Identifier / Identifier)"],
103
+
104
+ ["+function(){/regex/;};", 9, [false, false, false, false, false, true, false, false, false], "Unary `+` Operator, Function Expression Containing RegExp and Semicolon, `;`"],
105
+
106
+ # Line Terminators.
107
+ # -----------------
108
+ ["\r\n", 1, "CRLF Line Ending = 1 Linefeed"],
109
+ ["\r", 1, "CR Line Ending = 1 Linefeed"],
110
+ ["\n", 1, "LF Line Ending = 1 Linefeed"],
111
+ ["\r\n\n\u2028\u2029\r", 5, "Various Line Terminators"],
112
+
113
+ # Whitespace.
114
+ # -----------
115
+ ["a \t\u000b\u000c\u00a0\uffffb", [8, 10], "Whitespace"],
116
+
117
+ # Comments.
118
+ # ---------
119
+ ["//foo!@#^&$1234\nbar;", 4, "Line Comment, Linefeed, Identifier, `;`"],
120
+ ["/* abcd!@\#@$* { } && null*/;", 2, "Single-Line Block Comment, `;`"],
121
+ ["/*foo\nbar*/;", 2, "Multi-Line Block Comment, `;`"],
122
+ ["/*x*x*/;", 2, "Block Comment With Asterisks, `;`"],
123
+ ["/**/;", 2, "Empty Comment, `;`"],
124
+
125
+ # Identifiers.
126
+ # ------------
127
+ ["a + b;", 6, "Addition/Concatenation"],
128
+ ["x;", 2, "Single-Character Identifier, `;`"],
129
+ ["_x;", 2, "Identifier With Leading `_`, `;`"],
130
+ ["xyz;", 2, "Identifier With Letters Only, `;`"],
131
+ ["$x;", 2, "Identifier With Leading `$`, `;`"],
132
+ ["x5;", 2, "Identifier With Number As Second Character, `;`"],
133
+ ["x_y;", 2, "Identifier Containing `_`, `;`"],
134
+ ["x+5;", 4, "Identifier, Binary `+` Operator, Identifier, `;`"],
135
+ ["xyz123;", 2, "Alphanumeric Identifier, `;`"],
136
+ ["x1y1z1;", 2, "Alternating Alphanumeric Identifier, `;`"],
137
+ ["foo\\u00d8bar;", 2, "Identifier With Unicode Escape Sequence (`\\uXXXX`), `;`"],
138
+ ["f\u00d8\u00d8bar;", 2, "Identifier With Embedded Unicode Character"],
139
+
140
+ # Numbers.
141
+ # --------
142
+ ["5;", 2, "Integer, `;`"],
143
+ ["5.5;", 2, "Double, `;`"],
144
+ ["0;", 2, "Integer Zero, `;`"],
145
+ ["0.0;", 2, "Double Zero, `;`"],
146
+ ["0.001;", 2, "0 < Decimaliviolet Double < 1, `;`"],
147
+ ["1.e2;", 2, "Integer With Decimal and Exponential Component (`e`), `;`"],
148
+ ["1.e-2;", 2, "Integer With Decimal and Negative Exponential Component, `;`"],
149
+ ["1.E2;", 2, "Integer With Decimal and Uppercase Exponential Component (`E`), `;`"],
150
+ ["1.E-2;", 2, "Integer With Decimal and Uppercase Negative Exponential Component, `;`"],
151
+ [".5;", 2, "0 < Double < 1, `;`"],
152
+ [".5e3;", 2, "(0 < Double < 1) With Exponential Component"],
153
+ [".5e-3;", 2, "(0 < Double < 1) With Negative Exponential Component"],
154
+ ["0.5e3;", 2, "(0 < Decimaliviolet Double < 1) With Exponential Component"],
155
+ ["55;", 2, "Two-Digit Integer, `;`"],
156
+ ["123;", 2, "Three-Digit Integer, `;`"],
157
+ ["55.55;", 2, "Two-Digit Double, `;`"],
158
+ ["55.55e10;", 2, "Two-Digit Double With Exponential Component, `;`"],
159
+ ["123.456;", 2, "Three-Digit Double, `;`"],
160
+ ["1+e;", 4, "Additive Expression, `;`"],
161
+ ["0x01;", 2, "Hexadecimal `1` With 1 Leading Zero, `;`"],
162
+ ["0xcafe;", 2, "Hexadecimal `51966`, `;`"],
163
+ ["0x12345678;", 2, "Hexadecimal `305419896`, `;`"],
164
+ ["0x1234ABCD;", 2, "Hexadecimal `305441741` With Uppercase Letters, `;`"],
165
+ ["0x0001;", 2, "Hexadecimal `1` with 3 Leading Zeros, `;`"],
166
+
167
+ # Strings.
168
+ # --------
169
+ ["\"foo\";", 2, "Multi-Character Double-Quoted String, `;`"],
170
+ ["\"a\\n\";", 2, "Double-Quoted String Containing Linefeed, `;`"],
171
+ ["\'foo\';", 2, "Single-Quoted String, `;`"],
172
+ ["'a\\n';", 2, "Single-Quoted String Containing Linefeed, `;`"],
173
+ ["\"x\";", 2, "Single-Character Double-Quoted String, `;`"],
174
+ ["'';", 2, "Empty Single-Quoted String, `;`"],
175
+ ["\"foo\\tbar\";", 2, "Double-Quoted String With Tab Character, `;`"],
176
+ ["\"!@\#$%^&*()_+{}[]\";", 2, "Double-Quoted String Containing Punctuators, `;`"],
177
+ ["\"/*test*/\";", 2, "Double-Quoted String Containing Block Comment, `;`"],
178
+ ["\"//test\";", 2, "Double-Quoted String Containing Line Comment, `;`"],
179
+ ["\"\\\\\";", 2, "Double-Quoted String Containing Reverse Solidus, `;`"],
180
+ ["\"\\u0001\";", 2, "Double-Quoted String Containing Numeric Unicode Escape Sequence, `;`"],
181
+ ["\"\\uFEFF\";", 2, "Double-Quoted String Containing Alphanumeric Unicode Escape Sequence, `;`"],
182
+ ["\"\\u10002\";", 2, "Double-Quoted String Containing 5-Digit Unicode Escape Sequence, `;`"],
183
+ ["\"\\x55\";", 2, "Double-Quoted String Containing Hex Escape Sequence, `;`"],
184
+ ["\"\\x55a\";", 2, "Double-Quoted String Containing Hex Escape Sequence and Additional Character, `;`"],
185
+ ["\"a\\\\nb\";", 2, "Double-Quoted String Containing Escaped Linefeed, `;`"],
186
+ ["\";\"", [1, 2], "Double-Quoted String Containing `;`"],
187
+ ["\"a\\\nb\";", 2, "Double-Quoted String Containing Reverse Solidus and Linefeed, `;`"],
188
+ ["'\\\\'+ ''", [4, 5], "Single-Quoted String Containing Reverse Solidus, `+`, Empty Single-Quoted String"],
189
+
190
+ # `null`, `true`, and `false`.
191
+ # ----------------------------
192
+ ["null;", 2, "`null`, `;`"],
193
+ ["true;", 2, "`true`, `;`"],
194
+ ["false;", 2, "`false`, `;`"],
195
+
196
+ # Regular expressions.
197
+ # -------------------
198
+ ["/a/;", 2, [true, true], "Single-Character RegExp, `;`"],
199
+ ["/abc/;", 2, [true, true], "Multi-Character RegExp, `;`"],
200
+ ["/abc[a-z]*def/g;", 2, [true, true], "RegExp Containing Character Range and Quantifier, `;`"],
201
+ ["/\\b/;", 2, [true, true], "RegExp Containing Control Character, `;`"],
202
+ ["/[a-zA-Z]/;", 2, [true, true], "RegExp Containing Extended Character Range, `;`"],
203
+ ["/foo(.*)/g;", 2, [true, false], "RegExp Containing Capturing Group and Quantifier, `;`"],
204
+
205
+ # Array Literals.
206
+ # ---------------
207
+ ["[];", 3, "Empty Array, `;`"],
208
+ ["[\b\n\f\r\t\u0020];", [9, 10], "Array Containing Whitespace, `;`"],
209
+ ["[1];", 4, "Array Containing 1 Element, `;`"],
210
+ ["[1,2];", 6, "Array Containing 2 Elements, `;`"],
211
+ ["[1,2,,];", 8, "Array Containing 2 Elisions, `;`"],
212
+ ["[1,2,3];", 8, "Array Containing 3 Elements, `;`"],
213
+ ["[1,2,3,,,];", 11, "Array Containing 3 Elisions, `;`"],
214
+
215
+ # Object Literals.
216
+ # ----------------
217
+ ["({x:5});", 8, "Object Literal Containing 1 Member; `;`"],
218
+ ["({x:5,y:6});", 12, "Object Literal Containing 2 Members, `;`"],
219
+ ["({x:5,});", 9, "Object Literal Containing 1 Member and Trailing Comma, `;`"],
220
+ ["({if:5});", 8, "Object Literal Containing Reserved Word Property Name, `;`"],
221
+ ["({ get x() {42;} });", 17, "Object Literal Containing Getter, `;`"],
222
+ ["({ set y(a) {1;} });", 18, "Object Literal Containing Setter, `;`"],
223
+
224
+ # Member Expressions.
225
+ # -------------------
226
+ ["o.m;", 4, "Dot Member Accessor, `;`"],
227
+ ["o['m'];", 5, "Square Bracket Member Accessor, `;`"],
228
+ ["o['n']['m'];", 8, "Nested Square Bracket Member Accessor, `;`"],
229
+ ["o.n.m;", 6, "Nested Dot Member Accessor, `;`"],
230
+ ["o.if;", 4, "Dot Reserved Property Name Accessor, `;`"],
231
+
232
+ # Function Calls.
233
+ # ---------------
234
+ ["f();", 4, "Function Call Operator, `;`"],
235
+ ["f(x);", 5, "Function Call Operator With 1 Argument, `;`"],
236
+ ["f(x,y);", 7, "Function Call Operator With Multiple Arguments, `;`"],
237
+ ["o.m();", 6, "Dot Member Accessor, Function Call, `;`"],
238
+ ["o['m']();", 7, "Square Bracket Member Accessor, Function Call, `;`"],
239
+ ["o.m(x);", 7, "Dot Member Accessor, Function Call With 1 Argument, `;`"],
240
+ ["o['m'](x);", 8, "Square Bracket Member Accessor, Function Call With 1 Argument, `;`"],
241
+ ["o.m(x,y);", 9, "Dot Member Accessor, Function Call With 2 Arguments, `;`"],
242
+ ["o['m'](x,y);", 10, "Square Bracket Member Accessor, Function Call With 2 Arguments, `;`"],
243
+ ["f(x)(y);", 8, "Nested Function Call With 1 Argument Each, `;`"],
244
+ ["f().x;", 6, "Function Call, Dot Member Accessor, `;`"],
245
+
246
+ # `eval`.
247
+ # -------
248
+ ["eval('x');", 5, "`eval` Invocation With 1 Argument, `;`"],
249
+ ["(eval)('x');", 7, "Direct `eval` Call Example, `;`"],
250
+ ["(1,eval)('x');", 9, "Indirect `eval` Call Example, `;`"],
251
+ ["eval(x,y);", 7, "`eval` Invocation With 2 Arguments, `;`"],
252
+
253
+ # `new` Operator.
254
+ # ---------------
255
+ ["new f();", 6, "`new` Operator, Function Call, `;`"],
256
+ ["new o;", 4, "`new` Operator, Identifier, `;`"],
257
+ ["new o.m;", 6, "`new` Operator, Dot Member Accessor, `;`"],
258
+ ["new o.m(x);", 9, "`new` Operator, Dot Member Accessor, Function Call With 1 Argument, `;`"],
259
+ ["new o.m(x,y);", 11, "``new` Operator, Dot Member Accessor, Function Call With 2 Arguments , `;`"],
260
+
261
+ # Unary Prefix and Postfix Increment Operators.
262
+ # ---------------------------------------------
263
+ ["++x;", 3, "Prefix Increment, Identifier, `;`"],
264
+ ["x++;", 3, "Identifier, Postfix Increment, `;`"],
265
+ ["--x;", 3, "Prefix Decrement, Identifier, `;`"],
266
+ ["x--;", 3, "Postfix Decrement, Identifier, `;`"],
267
+ ["x ++;", 4, "Identifier, Space, Postfix Increment, `;`"],
268
+ ["x /* comment */ ++;", 6, "Identifier, Block Comment, Postfix Increment, `;`"],
269
+ ["++ /* comment */ x;", 6, "Prefix Increment, Block Comment, Identifier, `;`"],
270
+ ["new Date++;", 5, "`new` Operator, Identifier, Postfix Increment, `;`"],
271
+ ["+x++;", 4, "Unary `+`, Identifier, Postfix Increment, `;`"],
272
+
273
+ # Unary Operators.
274
+ # ----------------
275
+ ["delete x;", 4, "`delete` Operator, Space, Identifier, `;`"],
276
+ ["void x;", 4, "`void` Operator, Space, Identifier, `;`"],
277
+ ["typeof x;", 4, "`typeof` Operator, Space, Identifier, `;`"],
278
+ ["+x;", 3, "Unary `+` Operator, Identifier, `;`"],
279
+ ["-x;", 3, "Unary Negation Operator, Identifier, `;`"],
280
+ ["~x;", 3, "Bitwise NOT Operator, Identifier, `;`"],
281
+ ["!x;", 3, "Logical NOT Operator, Identifier, `;`"],
282
+
283
+ # Comma Operator.
284
+ # ---------------
285
+ ["x, y;", 5, "Comma Operator"],
286
+
287
+ # Expressions.
288
+ # ------------
289
+ ["1 * 2;", 6, "Integer, Multiplication, Integer, `;`"],
290
+ ["1 / 2;", 6, "Integer, Division, Integer, `;`"],
291
+ ["1 % 2;", 6, "Integer, Modulus, Integer, `;`"],
292
+ ["1 + 2;", 6, "Integer, Addition, Integer, `;`"],
293
+ ["1 - 2;", 6, "Integer, Subtraction, Integer, `;`"],
294
+ ["1 << 2;", 6, "Integer, Bitwise Left Shift, Integer, `;`"],
295
+ ["1 >>> 2;", 6, "Integer, Bitwise Zero-fill Right Shift, Integer, `;`"],
296
+ ["1 >> 2;", 6, "Integer, Bitwise Sign-Propagating Right Shift, Integer, `;`"],
297
+ ["1 * 2 + 3;", 10, "Order-of-Operations Expression, `;`"],
298
+ ["(1+2)*3;", 8, "Parenthesiviolet Additive Expression, Multiplication, `;`"],
299
+ ["1*(2+3);", 8, "Multiplication, Parenthesiviolet Additive Expression, `;`"],
300
+ ["x<y;", 4, "Less-Than Relational Operator, `;`"],
301
+ ["x>y;", 4, "Greater-Than Relational Operator, `;`"],
302
+ ["x<=y;", 4, "Less-Than-or-Equal-To Relational Operator, `;`"],
303
+ ["x>=y;", 4, "Greater-Than-or-Equal-To Relational Operator, `;`"],
304
+ ["x instanceof y;", 6, "`instanceof` Operator, `;`"],
305
+ ["x in y;", 6, "`in` Operator, `;`"],
306
+ ["x&y;", 4, "Bitwise AND Operator, `;`"],
307
+ ["x^y;", 4, "Bitwise XOR Operator, `;`"],
308
+ ["x|y;", 4, "Bitwise OR Operator, `;`"],
309
+ ["x+y<z;", 6, "Addition, Less-Than Relational, `;`"],
310
+ ["x<y+z;", 6, "Less-Than Relational, Addition, `;`"],
311
+ ["x+y+z;", 6, "Additive Expression With Three Identifiers, `;`"],
312
+ ["x&y|z;", 6, "Bitwise AND-OR Expression With Three Identifiers, `;`"],
313
+ ["x&&y;", 4, "Logical AND Operator, `;`"],
314
+ ["x||y;", 4, "Logical OR Operator, `;`"],
315
+ ["x&&y||z;", 6, "Logical AND-OR Expression With Three Identifiers, `;`"],
316
+ ["x||y&&z;", 6, "Logical OR-AND Expression With Three Identifiers, `;`"],
317
+ ["x<y?z:w;", 8, "Ternary Operator Expression With Four Identifiers, `;`"],
318
+ ["x;", 2, "Identifier, `;`"],
319
+ ["5;", 2, "Integer, `;`"],
320
+ ["1+2;", 4, "Additive Expression, `;`"],
321
+
322
+ # Assignment Operators.
323
+ # ---------------------
324
+ ["x = y;", 6, "Assignment, `;`"],
325
+ ["x >>>= y;", 6, "Bitwise Zero-Fill Right Shift Assignment, `;`"],
326
+ ["x <<= y;", 6, "Bitwise Left Shift Assignment, `;`"],
327
+ ["x += y;", 6, "Additive Assignment, `;`"],
328
+ ["x -= y;", 6, "Subtractive Assignment, `;`"],
329
+ ["x *= y;", 6, "Multiplicative Assignment, `;`"],
330
+ ["x /= y;", 6, "Divisive Assignment, `;`"],
331
+ ["x %= y;", 6, "Modulus Assignment, `;`"],
332
+ ["x >>= y;", 6, "Bitwise Sign-Propagating Right Shift Assignment, `;`"],
333
+ ["x &= y;", 6, "Bitwise AND Assignment, `;`"],
334
+ ["x ^= y;", 6, "Bitwise XOR Assignment, `;`"],
335
+ ["x |= y;", 6, "Bitwise OR Assignment, `;`"],
336
+
337
+ # Blocks.
338
+ # -------
339
+ ["{};", 3, "Empty Block, `;`"],
340
+ ["{x;};", 5, "Block Containing 1 Identifier, `;`"],
341
+ ["{x;y;};", 7, "Block Containing 2 Identifiers, `;`"],
342
+
343
+ # Variable Declarations.
344
+ # ----------------------
345
+ ["var abc;", 4, "Variable Declaration"],
346
+ ["var x,y;", 6, "Comma-Separated Variable Declarations, `;`"],
347
+ ["var x=1,y=2;", 10, "Comma-Separated Variable Initializations, `;`"],
348
+ ["var x,y=2;", 8, "Variable Declaration, Variable Initialization, `;`"],
349
+
350
+ # Empty Statements.
351
+ # -----------------
352
+ [";", 1, "Empty Statement"],
353
+ ["\n;", 2, "Linefeed, `;`"],
354
+
355
+ # `if...else` Statements.
356
+ # -----------------------
357
+ ["if (c) x; else y;", 13, "Space-Delimited `if...else` Statement"],
358
+ ["if (c) x;", 8, "Space-Delimited `if` Statement, `;`"],
359
+ ["if (c) {} else {};", 14, "Empty Block-Delimited `if...else` Statement"],
360
+ ["if (c1) if (c2) s1; else s2;", 19, "Nested `if...else` Statement Without Dangling `else`"],
361
+
362
+ # `while` and `do...while` Loops.
363
+ # -------------------------------
364
+ ["do s; while (e);", 11, "Space-Delimited `do...while` Loop"],
365
+ ["do { s; } while (e);", 15, "Block-Delimited `do...while` Loop"],
366
+ ["while (e) s;", 8, "Space-Delimited `while` Loop"],
367
+ ["while (e) { s; };", 13, "Block-Delimited `while` Loop"],
368
+
369
+ # `for` and `for...in` Loops.
370
+ # ---------------------------
371
+ ["for (;;) ;", 8, "Infinite Space-Delimited `for` Loop"],
372
+ ["for (;c;x++) x;", 12, "`for` Loop: Empty Initialization Condition; Space-Delimited Body"],
373
+ ["for (i;i<len;++i){};", 15, "Empty `for` Loop: Empty; Initialization, Test, and Increment Conditions Specified"],
374
+ ["for (var i=0;i<len;++i) {};", 20, "Empty `for` Loop: Variable Declaration in Initialization Condition"],
375
+ ["for (var i=0,j=0;;){};", 18, "`Empty for` Loop: Empty Test and Increment Conditions"],
376
+ ["for ((x in b); c; u) {};", 21, "Empty `for` Loop: `in` Expression in Initialization Condition"],
377
+ ["for (x in a);", 10, "Empty `for...in` Loop"],
378
+ ["for (var x in a){};", 14, "Empty `for...in` Loop: Variable Declaration in Loop Header"],
379
+ ["for (var x=5 in a) {};", 17, "Empty `for...in` Loop: Variable Initialization in Assignment Header"],
380
+ ["for (var x = a in b in c) {};", 23, "Empty `for...in` Loop: Multiple `in` Expressions in Header"],
381
+ ["for (var x=function(){a+b;}; a<b; ++i) some;", 29, "`for` Loop: Function Expression in Initialization Condition"],
382
+ ["for (var x=function(){for (x=0; x<15; ++x) alert(foo); }; a<b; ++i) some;", 48, "for.in` Loop: Function Expression in Initialization Condition Containing `for` Loop"],
383
+ ["for (x in a, b, c);", 16, "`for...in` With Multiple Comma-Separated Object References"],
384
+
385
+ # `continue`, `break`, and `return` Statements.
386
+ # ---------------------------------------------
387
+ ["continue;", 2, "`continue` Statement"],
388
+ ["continue label;", 4, "`continue` Statement With Identifier Label"],
389
+ ["break;", 2, "`break` Statement"],
390
+ ["break somewhere;", 4, "`break` Statement With Identifier Label"],
391
+ ["continue /* comment */ ;", 5, "`continue` Statement, Block Comment, `;`"],
392
+ ["continue \n;", 4, "`continue` Statement, Space, Linefeed, `;`"],
393
+ ["return;", 2, "`return` Statement"],
394
+ ["return 0;", 4, "`return` Statement, Integer, `;`"],
395
+ ["return 0 + \n 1;", 10, "`return` Statement, Additive Expression Containing Linefeed, `;`"],
396
+
397
+ # `with` Statement.
398
+ # -----------------
399
+ ["with (e) s;", 8, "`with` Statement, `;`"],
400
+
401
+ # `switch` Statement.
402
+ # -------------------
403
+ ["switch (e) { case x: s; };", 18, "`switch` Statement With 1 `case`"],
404
+ ["switch (e) { case x: s1;s2; default: s3; case y: s4; };", 34, "`switch` Statement: `case`, `default`, `case`"],
405
+ ["switch (e) { default: s1; case x: s2; case y: s3; };", 32, "`switch` Statement: `default`, `case`, `case`"],
406
+ ["switch (e) { default: s; };", 16, "`switch` Statement With `default` Case Only"],
407
+ ["switch (e) { case x: s1; case y: s2; };", 26, "`switch` Statement With 2 `case`s"],
408
+
409
+ # Labels.
410
+ # -------
411
+ ["foo : x;", 6, "Label (Identifier, Colon, Reference), `;`"],
412
+
413
+ # `throw` Statement.
414
+ # ------------------
415
+ ["throw x;", 4, "Throw Statement, `;`"],
416
+ ["throw x\n;", 5, "Throw Statement, Linefeed, `;`"],
417
+ ["throw x", [3, 4], "Throw Statement, No `;` (Safari 2 Case)"],
418
+
419
+ # `try...catch...finally` Blocks.
420
+ # -------------------------------
421
+ ["try { s1; } catch (e) { s2; };", 22, "`try...catch` Statement"],
422
+ ["try { s1; } finally { s2; };", 18, "`try...finally` Statement"],
423
+ ["try { s1; } catch (e) { s2; } finally { s3; };", 31, "`try...catch...finally` Statement"],
424
+
425
+ # `debugger` Statement.
426
+ # ---------------------
427
+ ["debugger;", 2, "`debugger` Statement"],
428
+
429
+ # Function Declarations.
430
+ # ----------------------
431
+ ["function f() { x; y; };", 16, "Named Function Declaration With Body"],
432
+ ["function f(x) { e; return x; };", 19, "Named Function Declaration With Argument and `return`"],
433
+ ["function f(x,y) { var z; return x; };", 23, "Named Function Declaration With 2 Arguments, Variable Declaration, and `return`"],
434
+
435
+ # Function Expressions.
436
+ # ---------------------
437
+ ["(function empty() {;});", 12, "Parenthesiviolet Empty Named Function Expression"],
438
+ ["(function (x) {; });", 13, "Parenthesiviolet Empty Function Expression"],
439
+ ["(function f(x) { return x; });", 18, "Named Function Expression"],
440
+
441
+ # Programs.
442
+ # ---------
443
+ ["var x; function f(){;}; null;", 17, "Variable Declaration, Function Declaration, `null`, `;`"],
444
+ [";;", 2, "Program: 2 Empty Statements"],
445
+ ["{ x; y; z; }", 12, "Program: Block Comprising Semicolon-Delimited Identifiers"],
446
+ ["function f(){ function g(){;}};", 17, "Program: Nested Function Declaration"],
447
+ ["x;\n/*foo*/\n\t;", 7, "Program: Identifier, Linefeed, Block Comment, Linefeed"],
448
+
449
+ # Automatic Semicolon Insertion Productions.
450
+ # ------------------------------------------
451
+ ["continue \n foo;", [6, 7], "Restricted Production: `continue` Statement"],
452
+ ["break \n foo;", [6, 7], "Restricted Production: `break` Statement"],
453
+ ["return\nfoo;", [4, 5], "Restricted Production: `return` Statement"],
454
+ ["throw\nfoo;", [4, 6], "Restricted Production: `throw` Statement"],
455
+ ["var x; { 1 \n 2 } 3", [16, 19], "Classic Automatic Semicolon Insertion Case"],
456
+ ["ab \t /* hi */\ncd", [7, 9], "Automatic Semicolon Insertion: Block Comment"],
457
+ ["ab/*\n*/cd", [3, 5], "Automatic Semicolon Insertion Triggered by Multi-Line Block Comment"],
458
+ ["continue /* wtf \n busta */ foo;", [6, 7], "Automatic Semicolon Insertion: `continue` Statement Preceding Multi-Line Block Comment"],
459
+ ["function f() { s }", [11, 12], "Automatic Semicolon Insertion: Statement Within Function Declaration"],
460
+ ["function f() { return }", [11, 12], "Automatic Semicolon Insertion: `return` Statement Within Function Declaration"],
461
+
462
+ # Strict Mode.
463
+ # ------------
464
+ ["\"use strict\"; 'bla'\n; foo;", 9, "Double-Quoted Strict Mode Directive, Program"],
465
+ ["'use strict'; \"bla\"\n; foo;", 9, "Single-Quoted Strict Mode Directive, Program"],
466
+ ["(function() { \"use strict\"; 'bla';\n foo; });", 20, "Strict Mode Directive Within Function"],
467
+ ["\"use\\n strict\";", 2, "Invalid Strict Mode Directive Containing Linefeed"],
468
+ ["foo; \"use strict\";", 5, "Invalid Strict Mode Directive Within Program"],
469
+ ["\"use strict\"; var o = { eval: 42};", 17, "Section 8.7.2: `eval` object property name is permitted in strict mode"],
470
+ ["({foo:0,foo:1});", 12, "Duplicate object property name is permitted in non-strict mode"],
471
+ ["function foo(a,a){}", 10, "Duplicate argument name is permitted in non-strict mode"],
472
+ ["(function foo(eval){})", [10, 11], "`eval` argument name is permitted in non-strict mode"],
473
+ ["(function foo(arguments){})", [10, 11], "`arguments` argument name is permitted in non-strict mode"],
474
+
475
+ # Empty Programs.
476
+ # ---------------
477
+ ["", 0, "Empty Program"],
478
+ ["// test", 1, "Line Comment"],
479
+ ["//test\n", 2, "Line Comment, Linefeed"],
480
+ ["\n// test", 2, "Linefeed, Line Comment"],
481
+ ["\n// test\n", 3, "Linefeed, Line Comment, Linefeed"],
482
+ ["/* */", 1, "Single-Line Block Comment"],
483
+ ["/*\ns,fd\n*/", 1, "Multi-Line Block Comment"],
484
+ ["/*\ns,fd\n*/\n", 2, "Block Comment Containing Linefeeds, Linefeed"],
485
+ [" \t", 3, "Spaces and Tabs"],
486
+ [" /*\nsmeh*/\t\n ", 8, "Spaces, Block Comment, Linefeeds, and Tabs"],
487
+
488
+ # Trailing Whitespace.
489
+ # --------------------
490
+ ["a ", [3, 4], "Trailing Space Characters"],
491
+ ["a /* something */", [3, 4], "Trailing Block Comment"],
492
+ ["a\n\t// hah", [4, 5], "Trailing Linefeed, Tab, and Line Comment"],
493
+ ["/abc/de//f", [2, 3], [true, true], "RegExp With Flags, Trailing Line Comment"],
494
+ ["/abc/de/*f*/\n\t", [4, 5], [true, true, true, true], "RegExp With Flags, Trailing Block Comment, Newline, Tab"],
495
+
496
+ # Regression Tests.
497
+ # -----------------
498
+ ["for (x;function(){ a\nb };z) x;", [21, 23], "`for` Loop: Test Condition Contains Function Body With No Terminating `;`"],
499
+ ["c=function(){return;return};", [11, 12], "Function Body: Two `return` Statements; No Terminating `;`"],
500
+ ["d\nd()", [5, 7], "Identifier, Newline, Function Call"],
501
+ ["for(;;){x=function(){}}", [14, 15], "Function Expression in `for` Loop Body"],
502
+ ["for(var k;;){}", 10, "`for` Loop Header: Variable Declaration, Empty Test and Increment Conditions"],
503
+ ["({get foo(){ }})", [12, 13], "Empty Getter"],
504
+ ["\nreturnr", [2, 3], "Linefeed, Identifier Beginning With `return`"],
505
+ ["/ // / /", [4, 5], [true, false, false, true], "RegExp Containing One Space, Division Operator, Space, RegExp Containing One Space"],
506
+
507
+ # Lexer Regression Tests.
508
+ # -----------------------
509
+ ["trimRight = /\\s+$/;", 6, [false, false, false, false, true, false], "Typical `trimRight` RegExp"],
510
+ ["trimLeft = /^\\s+/;\n\ttrimRight = /\\s+$/;", 14,
511
+ [false, false, false, false, true, false, false, false, false, false, false, false, true, false],
512
+ "`trimLeft` and `trimRight` RegExps"],
513
+ ["this.charsX = Gui.getSize(this.textarea).w / this.fontSize.w;", 25, "Complex Division Not Treated as RegExp"],
514
+ ["(x)/ (y);", 9, "Parenthesiviolet Dividend, Division Operator, Space, Parenthesiviolet Divisor"],
515
+ ["/^(?:\\/(?![*\\n\\/])(?:\\[(?:\\\\.|[^\\]\\\\\\n])*\\]|\\\\.|[^\\[\\/\\\\\\n])+\\/[gim]*)$/", [1, 2], [true], "Complex RegExp for Matching RegExps"],
516
+ ["({a:b}[ohi].iets()++);", 16, "Object Literal With 1 Member, Square Bracket Member Accessor, Dot Member Accessor, Function Call, Postfix Increment"],
517
+
518
+ # Parser Regression Tests.
519
+ # ------------------------
520
+ ["\n\t// Used for trimming whitespace\n\ttrimLeft = /^\\s+/;\n\ttrimRight = /\\s+$/;\t\n", 21,
521
+ [false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false],
522
+ "Annotated `trimLeft` and `trimRight` RegExps"],
523
+ ["/[\\/]/;", 2, [true, false], "RegExp: Escaped `/` Within Character Class"],
524
+ ["/[/]/;", 2, [true, false], "RegExp: Escaped Trailing Character Class End (Valid in ES 5; Invalid in ES 3)"],
525
+ ["({get:5});", 8, "`get` Used As Standard Property Name"],
526
+ ["({set:5});", 8, "`get` Used As Standard Property Name"],
527
+ ["l !== \"px\" && (d.style(h, c, (k || 1) + l), j = (k || 1) / f.cur() * j, d.style(h, c, j + l)), i[1] && (k = (i[1] === \"-=\" ? -1 : 1) * k + j), f.custom(j, k, l)",
528
+ [131, 132], "Regression Test: RegExp/Division"],
529
+ ["(/\'/g, \'\\\\\\\'\') + \"'\";'", 14, "Regression Test: Confusing Escape Character Sequence"],
530
+ ["/abc\//no_comment", [3, 4], [true, false, false], "RegExp Followed By Line Comment"],
531
+ ["a: b; c;", 8, "ASI Regression Test: Labeled Identifier, `;`, Identifier, `;`"],
532
+ ["var x; function f(){ x; function g(){}}", 23, "Function Declaration Within Function Body"],
533
+ ["if (x) { break }", [11, 12], "ASI: `if` Statement, `break`"],
534
+ ["x.hasOwnProperty()", [5, 6], "Regression Test: Object Property Named `hasOwnProperty`"],
535
+ ["(x) = 5", [7, 8], "LHS of Expression Contains Grouping Operator"],
536
+ ["(x,x) = 5", [9, 10], "Syntactically Valid LHS Grouping Operator (Expression Will Produce A `ReferenceError` When Interpreted)"],
537
+ ["switch(x){case 1:}", 10, "Single-`case` `switch` Statement Without Body"],
538
+ ["while (x) { ++a\t}", [12, 13], "Prefix Increment Operator, Tab Character Within `while` Loop"],
539
+ ["{break}", [3, 4], "ASI: `break`"],
540
+ ["{continue}", [3, 4], "ASI: `continue`"],
541
+ ["{return}", [3, 4], "ASI: `return`"],
542
+ ["{continue a}", [5, 6], "ASI: `continue`, Identifier"],
543
+ ["{break b}", [5, 6], "ASI: `break`, Identifier"],
544
+ ["{return c}", [5, 6], "ASI: `return`, Identifier"],
545
+
546
+ ["switch(x){ default: foo; break; case x: break; default: fail; }", [30, 34], "Duplicate `default` Clause. @qfox/ZeParser#6"],
547
+ ["switch(x){ default: foo; break; case x: break; } switch(x){ default: foo; break; case x: break; }", 49, "State Leakage: Sequential Valid `switch` Statements. @qfox/ZeParser#8"],
548
+ ["try { foo(); } catch (e) {} try { bar(); }", [30, 31], "State Leakage: `try...catch` Block Followed By Invalid `try` Block. @qfox/ZeParser#8"]
549
+ ]
550
+ end