// tests for both the tokenizer and parser. Parser test results could be checked tighter. // api: [input, token-output-count, ?regex-hints, desc] // regex-hints are for tokenizer, will tell for each token whether it might parse regex or not (parser's job) var Tests = [ ["var abc;", 4, "Variable Declaration"], ["var abc = 5;", 8, "Variable Declaration, Assignment"], ["/* */", 1, "Block Comment"], ["/** **/", 1, "JSDoc-style Comment"], ["var f = function(){;};", 13, "Assignment, Function Expression"], ["hi; // moo", 4, "Trailing Line Comment"], ["hi; // moo\n;", 6, "Trailing Line Comment, Linefeed, `;`"], ["var varwithfunction;", 4, "Variable Declaration, Identifier Containing Reserved Words, `;`"], ["a + b;", 6, "Addition/Concatenation"], ["'a'", 1, "Single-Quoted String"], ["'a';", 2, "Single-Quoted String, `;`"], // Taken from the parser test suite. ["'a\\n'", 1, "Single-Quoted String With Escaped Linefeed"], ["'a\\n';", 2, "Single-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. ["\"a\"", 1, "Double-Quoted String"], ["\"a\";", 2, "Double-Quoted String, `;`"], // Taken from the parser test suite. ["\"a\\n\"", 1, "Double-Quoted String With Escaped Linefeed"], ["\"a\\n\";", 2, "Double-Quoted String With Escaped Linefeed, `;`"], // Taken from the parser test suite. ["500", 1, "Integer"], ["500;", 2, "Integer, `;`"], // Taken from the parser test suite. ["500.", 1, "Double With Trailing Decimal Point"], ["500.;", 2, "Double With Trailing Decimal Point"], // Taken from the parser test suite. ["500.432", 1, "Double With Decimal Component"], ["500.432;", 2, "Double With Decimal Component, `;`"], // Taken from the parser test suite. [".432432", 1, "Number, 0 < Double < 1"], [".432432;", 2, "Number, 0 < Double < 1, `;`"], // Taken from the parser test suite. ["(a,b,c)", 7, "Parentheses, Comma-separated identifiers"], ["(a,b,c);", 8, "Parentheses, Comma-separated identifiers, `;`"], // Taken from the parser test suite. ["[1,2,abc]", 7, "Array literal"], ["[1,2,abc];", 8, "Array literal, `;`"], // Taken from the parser test suite. ["{a:1,\"b\":2,c:c}", 13, "Object literal"], ["var o = {a:1,\"b\":2,c:c};", 20, "Assignment, Object Literal, `;`"], // Taken from the parser test suite. ["var x;\nvar y;", 9, "2 Variable Declarations, Multiple lines"], ["var x;\nfunction n(){ }", 13, "Variable, Linefeed, Function Declaration"], ["var x;\nfunction n(abc){ }", 14, "Variable, Linefeed, Function Declaration With One Argument"], ["var x;\nfunction n(abc, def){ }", 17, "Variable, Linefeed, Function Declaration With Multiple Arguments"], ["function n(){ \"hello\"; }", 11, "Function Declaration, Body"], ["/a/;", 2, [true, false], "RegExp Literal, `;`"], ["/a/b;", 2, [true, true], "RegExp Literal, Flags, `;`"], ["++x;", 3, "Unary Increment, Prefix, `;`"], [" / /;", 3, [true, true, false], "RegExp, Leading Whitespace, `;`"], ["/ / / / /", 5, [true, false, false, false, true], "RegExp Containing One Space, Space, Division, Space, RegExp Containing One Space"], // Taken from the parser test suite. ["\"var\";", 2, "Keyword String, `;`"], ["\"variable\";", 2, "String Beginning With Keyword, `;`"], ["\"somevariable\";", 2, "String Containing Keyword, `;`"], ["\"somevar\";", 2, "String Ending With Keyword, `;`"], ["var varwithfunction;", 4, "Keywords should not be matched in identifiers"], ["var o = {a:1};", 12, "Object Literal With Unquoted Property"], ["var o = {\"b\":2};", 12, "Object Literal With Quoted Property"], ["var o = {c:c};", 12, "Object Literal With Equivalent Property Name and Identifier"], ["/a/ / /b/;", 6, [true, true, false, false, true, false], "RegExp, Division, RegExp, `;`"], ["a/b/c;", 6, "Triple Division (Identifier / Identifier / Identifier)"], ["+function(){/regex/;};", 9, [false, false, false, false, false, true, false, false, false], "Unary `+` Operator, Function Expression Containing RegExp and Semicolon, `;`"], // Line Terminators. ["\r\n", 1, "CRLF Line Ending = 1 Linefeed"], ["\r", 1, "CR Line Ending = 1 Linefeed"], ["\n", 1, "LF Line Ending = 1 Linefeed"], ["\r\n\n\u2028\u2029\r", 5, "Various Line Terminators"], // Whitespace. ["a \t\u000b\u000c\u00a0\uFFFFb", 8, "Whitespace"], // Comments. ["//foo!@#^&$1234\nbar;", 4, "Line Comment, Linefeed, Identifier, `;`"], ["/* abcd!@#@$* { } && null*/;", 2, "Single-Line Block Comment, `;`"], ["/*foo\nbar*/;", 2, "Multi-Line Block Comment, `;`"], ["/*x*x*/;", 2, "Block Comment With Asterisks, `;`"], ["/**/;", 2, "Empty Comment, `;`"], // Identifiers. ["x;", 2, "Single-Character Identifier, `;`"], ["_x;", 2, "Identifier With Leading `_`, `;`"], ["xyz;", 2, "Identifier With Letters Only, `;`"], ["$x;", 2, "Identifier With Leading `$`, `;`"], ["x5;", 2, "Identifier With Number As Second Character, `;`"], ["x_y;", 2, "Identifier Containing `_`, `;`"], ["x+5;", 4, "Identifier, Binary `+` Operator, Identifier, `;`"], ["xyz123;", 2, "Alphanumeric Identifier, `;`"], ["x1y1z1;", 2, "Alternating Alphanumeric Identifier, `;`"], ["foo\\u00d8bar;", 2, "Identifier With Unicode Escape Sequence (`\\uXXXX`), `;`"], ["f\u00d8\u00d8bar;", 2, "Identifier With Embedded Unicode Character"], // Numbers. ["5;", 2, "Integer, `;`"], ["5.5;", 2, "Double, `;`"], ["0;", 2, "Integer Zero, `;`"], ["0.0;", 2, "Double Zero, `;`"], ["0.001;", 2, "0 < Decimalized Double < 1, `;`"], ["1.e2;", 2, "Integer With Decimal and Exponential Component (`e`), `;`"], ["1.e-2;", 2, "Integer With Decimal and Negative Exponential Component, `;`"], ["1.E2;", 2, "Integer With Decimal and Uppercase Exponential Component (`E`), `;`"], ["1.E-2;", 2, "Integer With Decimal and Uppercase Negative Exponential Component, `;`"], [".5;", 2, "0 < Double < 1, `;`"], [".5e3;", 2, "(0 < Double < 1) With Exponential Component"], [".5e-3;", 2, "(0 < Double < 1) With Negative Exponential Component"], ["0.5e3;", 2, "(0 < Decimalized Double < 1) With Exponential Component"], ["55;", 2, "Two-Digit Integer, `;`"], ["123;", 2, "Three-Digit Integer, `;`"], ["55.55;", 2, "Two-Digit Double, `;`"], ["55.55e10;", 2, "Two-Digit Double With Exponential Component, `;`"], ["123.456;", 2, "Three-Digit Double, `;`"], ["1+e;", 4, "Additive Expression, `;`"], ["0x01;", 2, "Hexadecimal `1` With 1 Leading Zero, `;`"], ["0xcafe;", 2, "Hexadecimal `51966`, `;`"], ["0x12345678;", 2, "Hexadecimal `305419896`, `;`"], ["0x1234ABCD;", 2, "Hexadecimal `305441741` With Uppercase Letters, `;`"], ["0x0001;", 2, "Hexadecimal `1` with 3 Leading Zeros, `;`"], // Strings. ["\"foo\";", 2, "Multi-Character Double-Quoted String, `;`"], ["\"a\\n\";", 2, "Double-Quoted String Containing Linefeed, `;`"], ["\'foo\';", 2, "Single-Quoted String, `;`"], ["'a\\n';", 2, "Single-Quoted String Containing Linefeed, `;`"], ["\"x\";", 2, "Single-Character Double-Quoted String, `;`"], ["'';", 2, "Empty Single-Quoted String, `;`"], ["\"foo\\tbar\";", 2, "Double-Quoted String With Tab Character, `;`"], ["\"!@#$%^&*()_+{}[]\";", 2, "Double-Quoted String Containing Punctuators, `;`"], ["\"/*test*/\";", 2, "Double-Quoted String Containing Block Comment, `;`"], ["\"//test\";", 2, "Double-Quoted String Containing Line Comment, `;`"], ["\"\\\\\";", 2, "Double-Quoted String Containing Reverse Solidus, `;`"], ["\"\\u0001\";", 2, "Double-Quoted String Containing Numeric Unicode Escape Sequence, `;`"], ["\"\\uFEFF\";", 2, "Double-Quoted String Containing Alphanumeric Unicode Escape Sequence, `;`"], ["\"\\u10002\";", 2, "Double-Quoted String Containing 5-Digit Unicode Escape Sequence, `;`"], ["\"\\x55\";", 2, "Double-Quoted String Containing Hex Escape Sequence, `;`"], ["\"\\x55a\";", 2, "Double-Quoted String Containing Hex Escape Sequence and Additional Character, `;`"], ["\"a\\\\nb\";", 2, "Double-Quoted String Containing Escaped Linefeed, `;`"], ["\";\"", 1, "Double-Quoted String Containing `;`"], ["\"a\\\nb\";", 2, "Double-Quoted String Containing Reverse Solidus and Linefeed, `;`"], ["'\\\\'+ ''", 4, "Single-Quoted String Containing Reverse Solidus, `+`, Empty Single-Quoted String"], // `null`, `true`, and `false`. ["null;", 2, "`null`, `;`"], ["true;", 2, "`true`, `;`"], ["false;", 2, "`false`, `;`"], // RegExps ["/a/;", 2, [true, true], "Single-Character RegExp, `;`"], ["/abc/;", 2, [true, true], "Multi-Character RegExp, `;`"], ["/abc[a-z]*def/g;", 2, [true, true], "RegExp Containing Character Range and Quantifier, `;`"], ["/\\b/;", 2, [true, true], "RegExp Containing Control Character, `;`"], ["/[a-zA-Z]/;", 2, [true, true], "RegExp Containing Extended Character Range, `;`"], ["/foo(.*)/g;", 2, [true, false], "RegExp Containing Capturing Group and Quantifier, `;`"], // Array Literals. ["[];", 3, "Empty Array, `;`"], ["[\b\n\f\r\t\x20];", 9, "Array Containing Whitespace, `;`"], ["[1];", 4, "Array Containing 1 Element, `;`"], ["[1,2];", 6, "Array Containing 2 Elements, `;`"], ["[1,2,,];", 8, "Array Containing 2 Elisions, `;`"], ["[1,2,3];", 8, "Array Containing 3 Elements, `;`"], ["[1,2,3,,,];", 11, "Array Containing 3 Elisions, `;`"], // Object Literals. ["({x:5});", 8, "Object Literal Containing 1 Member; `;`"], ["({x:5,y:6});", 12, "Object Literal Containing 2 Members, `;`"], ["({x:5,});", 9, "Object Literal Containing 1 Member and Trailing Comma, `;`"], ["({if:5});", 8, "Object Literal Containing Reserved Word Property Name, `;`"], ["({ get x() {42;} });", 17, "Object Literal Containing Getter, `;`"], ["({ set y(a) {1;} });", 18, "Object Literal Containing Setter, `;`"], // Member Expressions. ["o.m;", 4, "Dot Member Accessor, `;`"], ["o['m'];", 5, "Square Bracket Member Accessor, `;`"], ["o['n']['m'];", 8, "Nested Square Bracket Member Accessor, `;`"], ["o.n.m;", 6, "Nested Dot Member Accessor, `;`"], ["o.if;", 4, "Dot Reserved Property Name Accessor, `;`"], // Function Calls. ["f();", 4, "Function Call Operator, `;`"], ["f(x);", 5, "Function Call Operator With 1 Argument, `;`"], ["f(x,y);", 7, "Function Call Operator With Multiple Arguments, `;`"], ["o.m();", 6, "Dot Member Accessor, Function Call, `;`"], ["o['m']();", 7, "Square Bracket Member Accessor, Function Call, `;`"], ["o.m(x);", 7, "Dot Member Accessor, Function Call With 1 Argument, `;`"], ["o['m'](x);", 8, "Square Bracket Member Accessor, Function Call With 1 Argument, `;`"], ["o.m(x,y);", 9, "Dot Member Accessor, Function Call With 2 Arguments, `;`"], ["o['m'](x,y);", 10, "Square Bracket Member Accessor, Function Call With 2 Arguments, `;`"], ["f(x)(y);", 8, "Nested Function Call With 1 Argument Each, `;`"], ["f().x;", 6, "Function Call, Dot Member Accessor, `;`"], // `eval` Function. ["eval('x');", 5, "`eval` Invocation With 1 Argument, `;`"], ["(eval)('x');", 7, "Direct `eval` Call Example, `;`"], ["(1,eval)('x');", 9, "Indirect `eval` Call Example, `;`"], ["eval(x,y);", 7, "`eval` Invocation With 2 Arguments, `;`"], // `new` Operator. ["new f();", 6, "`new` Operator, Function Call, `;`"], ["new o;", 4, "`new` Operator, Identifier, `;`"], ["new o.m;", 6, "`new` Operator, Dot Member Accessor, `;`"], ["new o.m(x);", 9, "`new` Operator, Dot Member Accessor, Function Call With 1 Argument, `;`"], ["new o.m(x,y);", 11, "``new` Operator, Dot Member Accessor, Function Call With 2 Arguments , `;`"], // Prefix and Postfix Increment. ["++x;", 3, "Prefix Increment, Identifier, `;`"], ["x++;", 3, "Identifier, Postfix Increment, `;`"], ["--x;", 3, "Prefix Decrement, Identifier, `;`"], ["x--;", 3, "Postfix Decrement, Identifier, `;`"], ["x ++;", 4, "Identifier, Space, Postfix Increment, `;`"], ["x /* comment */ ++;", 6, "Identifier, Block Comment, Postfix Increment, `;`"], ["++ /* comment */ x;", 6, "Prefix Increment, Block Comment, Identifier, `;`"], // Unary Operators. ["delete x;", 4, "`delete` Operator, Space, Identifier, `;`"], ["void x;", 4, "`void` Operator, Space, Identifier, `;`"], ["typeof x;", 4, "`typeof` Operator, Space, Identifier, `;`"], ["+x;", 3, "Unary `+` Operator, Identifier, `;`"], ["-x;", 3, "Unary Negation Operator, Identifier, `;`"], ["~x;", 3, "Bitwise NOT Operator, Identifier, `;`"], ["!x;", 3, "Logical NOT Operator, Identifier, `;`"], // Comma Operator. ["x, y;", 5, "Comma Operator"], // Miscellaneous. ["new Date++;", 5, "`new` Operator, Identifier, Postfix Increment, `;`"], ["+x++;", 4, "Unary `+`, Identifier, Postfix Increment, `;`"], // Expressions. ["1 * 2;", 6, "Integer, Multiplication, Integer, `;`"], ["1 / 2;", 6, "Integer, Division, Integer, `;`"], ["1 % 2;", 6, "Integer, Modulus, Integer, `;`"], ["1 + 2;", 6, "Integer, Addition, Integer, `;`"], ["1 - 2;", 6, "Integer, Subtraction, Integer, `;`"], ["1 << 2;", 6, "Integer, Bitwise Left Shift, Integer, `;`"], ["1 >>> 2;", 6, "Integer, Bitwise Zero-fill Right Shift, Integer, `;`"], ["1 >> 2;", 6, "Integer, Bitwise Sign-Propagating Right Shift, Integer, `;`"], ["1 * 2 + 3;", 10, "Order-of-Operations Expression, `;`"], ["(1+2)*3;", 8, "Parenthesized Additive Expression, Multiplication, `;`"], ["1*(2+3);", 8, "Multiplication, Parenthesized Additive Expression, `;`"], ["xy;", 4, "Greater-Than Relational Operator, `;`"], ["x<=y;", 4, "Less-Than-or-Equal-To Relational Operator, `;`"], ["x>=y;", 4, "Greater-Than-or-Equal-To Relational Operator, `;`"], ["x instanceof y;", 6, "`instanceof` Operator, `;`"], ["x in y;", 6, "`in` Operator, `;`"], ["x&y;", 4, "Bitwise AND Operator, `;`"], ["x^y;", 4, "Bitwise XOR Operator, `;`"], ["x|y;", 4, "Bitwise OR Operator, `;`"], ["x+y>>= y;", 6, "Bitwise Zero-Fill Right Shift Assignment, `;`"], ["x <<= y;", 6, "Bitwise Left Shift Assignment, `;`"], ["x += y;", 6, "Additive Assignment, `;`"], ["x -= y;", 6, "Subtractive Assignment, `;`"], ["x *= y;", 6, "Multiplicative Assignment, `;`"], ["x /= y;", 6, "Divisive Assignment, `;`"], ["x %= y;", 6, "Modulus Assignment, `;`"], ["x >>= y;", 6, "Bitwise Sign-Propagating Right Shift Assignment, `;`"], ["x &= y;", 6, "Bitwise AND Assignment, `;`"], ["x ^= y;", 6, "Bitwise XOR Assignment, `;`"], ["x |= y;", 6, "Bitwise OR Assignment, `;`"], // Blocks. ["{};", 3, "Empty Block, `;`"], ["{x;};", 5, "Block Containing 1 Identifier, `;`"], ["{x;y;};", 7, "Block Containing 2 Identifiers, `;`"], // Variable Declarations. ["var abc;", 4, "Variable Declaration"], ["var x,y;", 6, "Comma-Separated Variable Declarations, `;`"], ["var x=1,y=2;", 10, "Comma-Separated Variable Initializations, `;`"], ["var x,y=2;", 8, "Variable Declaration, Variable Initialization, `;`"], // Empty Statements. [";", 1, "Empty Statement"], ["\n;", 2, "Linefeed, `;`"], // Expression Statements. ["x;", 2, "Identifier, `;`"], ["5;", 2, "Integer, `;`"], ["1+2;", 4, "Additive Statement, `;`"], // `if...else` Statements. ["if (c) x; else y;", 13, "Space-Delimited `if...else` Statement"], ["if (c) x;", 8, "Space-Delimited `if` Statement, `;`"], ["if (c) {} else {};", 14, "Empty Block-Delimited `if...else` Statement"], ["if (c1) if (c2) s1; else s2;", 19, "Nested `if...else` Statement Without Dangling `else`"], // `while` and `do...while` Loops. ["do s; while (e);", 11, "Space-Delimited `do...while` Loop"], ["do { s; } while (e);", 15, "Block-Delimited `do...while` Loop"], ["while (e) s;", 8, "Space-Delimited `while` Loop"], ["while (e) { s; };", 13, "Block-Delimited `while` Loop"], // `for` and `for...in` Loops. ["for (;;) ;", 8, "Infinite Space-Delimited `for` Loop"], ["for (;c;x++) x;", 12, "`for` Loop: Empty Initialization Condition; Space-Delimited Body"], ["for (i;i