15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/***********************************************************************
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  A JavaScript tokenizer / parser / beautifier / compressor.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  This version is suitable for Node.js.  With minimal changes (the
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  exports stuff) it should work on any JS platform.
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  This file contains the tokenizer/parser.  It is a port to JavaScript
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  of parse-js [1], a JavaScript parser library written in Common Lisp
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  by Marijn Haverbeke.  Thank you Marijn!
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  [1] http://marijn.haverbeke.nl/parse-js/
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  Exported functions:
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    - tokenizer(code) -- returns a function.  Call the returned
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      function to fetch the next token.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    - parse(code) -- returns an AST of the given JavaScript code.
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  -------------------------------- (C) ---------------------------------
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                           Author: Mihai Bazon
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         <mihai.bazon@gmail.com>
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                       http://mihai.bazon.net/blog
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  Distributed under the BSD license:
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Based on parse-js (http://marijn.haverbeke.nl/parse-js/).
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Redistribution and use in source and binary forms, with or without
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    modification, are permitted provided that the following conditions
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    are met:
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        * Redistributions of source code must retain the above
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          copyright notice, this list of conditions and the following
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          disclaimer.
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        * Redistributions in binary form must reproduce the above
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          copyright notice, this list of conditions and the following
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          disclaimer in the documentation and/or other materials
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)          provided with the distribution.
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SUCH DAMAGE.
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ***********************************************************************/
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* -----[ Tokenizer (constants) ]----- */
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var KEYWORDS = array_to_hash([
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "break",
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "case",
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "catch",
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "const",
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "continue",
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "default",
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "delete",
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "do",
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "else",
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "finally",
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "for",
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "function",
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "if",
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "in",
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "instanceof",
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "new",
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "return",
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "switch",
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "throw",
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "try",
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "typeof",
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "var",
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "void",
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "while",
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "with"
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)]);
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var RESERVED_WORDS = array_to_hash([
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "abstract",
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "boolean",
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "byte",
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "char",
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "class",
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "debugger",
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "double",
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "enum",
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "export",
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "extends",
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "final",
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "float",
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "goto",
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "implements",
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "import",
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "int",
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "interface",
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "long",
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "native",
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "package",
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "private",
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "protected",
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "public",
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "short",
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "static",
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "super",
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "synchronized",
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "throws",
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "transient",
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "volatile"
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)]);
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var KEYWORDS_BEFORE_EXPRESSION = array_to_hash([
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "return",
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "new",
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "delete",
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "throw",
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "else",
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "case"
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)]);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var KEYWORDS_ATOM = array_to_hash([
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "false",
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "null",
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "true",
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "undefined"
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)]);
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var OPERATOR_CHARS = array_to_hash(characters("+-*&%=<>!?|~^"));
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var RE_OCT_NUMBER = /^0[0-7]+$/;
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var OPERATORS = array_to_hash([
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "in",
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "instanceof",
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "typeof",
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "new",
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "void",
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "delete",
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "++",
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "--",
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "+",
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "-",
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "!",
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "~",
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "&",
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "|",
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "^",
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "*",
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "/",
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "%",
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ">>",
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "<<",
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ">>>",
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "<",
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ">",
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "<=",
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ">=",
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "==",
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "===",
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "!=",
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "!==",
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "?",
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "=",
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "+=",
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "-=",
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "/=",
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "*=",
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "%=",
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ">>=",
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "<<=",
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ">>>=",
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "%=",
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "|=",
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "^=",
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "&=",
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "&&",
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "||"
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)]);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var WHITESPACE_CHARS = array_to_hash(characters(" \n\r\t"));
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var PUNC_BEFORE_EXPRESSION = array_to_hash(characters("[{}(,.;:"));
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var PUNC_CHARS = array_to_hash(characters("[]{}(),;:"));
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* -----[ Tokenizer ]----- */
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function is_alphanumeric_char(ch) {
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ch = ch.charCodeAt(0);
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return (ch >= 48 && ch <= 57) ||
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                (ch >= 65 && ch <= 90) ||
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                (ch >= 97 && ch <= 122);
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function is_identifier_char(ch) {
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return is_alphanumeric_char(ch) || ch == "$" || ch == "_";
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function is_digit(ch) {
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ch = ch.charCodeAt(0);
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ch >= 48 && ch <= 57;
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function parse_js_number(num) {
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (RE_HEX_NUMBER.test(num)) {
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return parseInt(num.substr(2), 16);
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (RE_OCT_NUMBER.test(num)) {
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return parseInt(num.substr(1), 8);
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else if (RE_DEC_NUMBER.test(num)) {
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return parseFloat(num);
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function JS_Parse_Error(message, line, col, pos) {
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.message = message;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.line = line;
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.col = col;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.pos = pos;
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        try {
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ({})();
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } catch(ex) {
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                this.stack = ex.stack;
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)JS_Parse_Error.prototype.toString = function() {
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function js_error(message, line, col, pos) {
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throw new JS_Parse_Error(message, line, col, pos);
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function is_token(token, type, val) {
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return token.type == type && (val == null || token.value == val);
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var EX_EOF = {};
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function tokenizer($TEXT) {
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var S = {
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                text            : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, ''),
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                pos             : 0,
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                tokpos          : 0,
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                line            : 0,
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                tokline         : 0,
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                col             : 0,
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                tokcol          : 0,
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                newline_before  : false,
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                regex_allowed   : false,
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                comments_before : []
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function peek() { return S.text.charAt(S.pos); };
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function next(signal_eof) {
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var ch = S.text.charAt(S.pos++);
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (signal_eof && !ch)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        throw EX_EOF;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (ch == "\n") {
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.newline_before = true;
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ++S.line;
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.col = 0;
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else {
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ++S.col;
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return ch;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function eof() {
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return !S.peek();
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function find(what, signal_eof) {
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var pos = S.text.indexOf(what, S.pos);
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (signal_eof && pos == -1) throw EX_EOF;
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return pos;
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function start_token() {
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.tokline = S.line;
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.tokcol = S.col;
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.tokpos = S.pos;
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function token(type, value, is_comment) {
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.regex_allowed = ((type == "operator" && !HOP(UNARY_POSTFIX, value)) ||
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                   (type == "keyword" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                   (type == "punc" && HOP(PUNC_BEFORE_EXPRESSION, value)));
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var ret = {
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        type  : type,
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        value : value,
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        line  : S.tokline,
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        col   : S.tokcol,
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        pos   : S.tokpos,
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        nlb   : S.newline_before
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                };
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!is_comment) {
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ret.comments_before = S.comments_before;
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.comments_before = [];
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.newline_before = false;
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return ret;
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function skip_whitespace() {
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (HOP(WHITESPACE_CHARS, peek()))
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_while(pred) {
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var ret = "", ch = peek(), i = 0;
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (ch && pred(ch, i++)) {
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ret += next();
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ch = peek();
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return ret;
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function parse_error(err) {
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                js_error(err, S.tokline, S.tokcol, S.tokpos);
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_num(prefix) {
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var num = read_while(function(ch, i){
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (ch == "x" || ch == "X") {
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                if (has_x) return false;
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return has_x = true;
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (!has_x && (ch == "E" || ch == "e")) {
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                if (has_e) return false;
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return has_e = after_e = true;
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (ch == "-") {
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                if (after_e || (i == 0 && !prefix)) return true;
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return false;
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (ch == "+") return after_e;
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        after_e = false;
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (ch == ".") {
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                if (!has_dot)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                        return has_dot = true;
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return false;
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return is_alphanumeric_char(ch);
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                });
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (prefix)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        num = prefix + num;
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var valid = parse_js_number(num);
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!isNaN(valid)) {
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return token("num", valid);
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else {
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        parse_error("Invalid syntax: " + num);
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_escaped_char() {
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var ch = next(true);
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                switch (ch) {
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "n" : return "\n";
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "r" : return "\r";
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "t" : return "\t";
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "b" : return "\b";
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "v" : return "\v";
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "f" : return "\f";
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "0" : return "\0";
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "x" : return String.fromCharCode(hex_bytes(2));
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "u" : return String.fromCharCode(hex_bytes(4));
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    default  : return ch;
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function hex_bytes(n) {
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var num = 0;
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (; n > 0; --n) {
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var digit = parseInt(next(true), 16);
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (isNaN(digit))
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                parse_error("Invalid hex-character pattern in string");
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        num = (num << 4) | digit;
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return num;
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_string() {
4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return with_eof_error("Unterminated string constant", function(){
4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var quote = next(), ret = "";
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        for (;;) {
4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                var ch = next(true);
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                if (ch == "\\") ch = read_escaped_char();
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                else if (ch == quote) break;
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                ret += ch;
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return token("string", ret);
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                });
4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_line_comment() {
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var i = find("\n"), ret;
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (i == -1) {
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ret = S.text.substr(S.pos);
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.pos = S.text.length;
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else {
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ret = S.text.substring(S.pos, i);
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.pos = i;
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return token("comment1", ret, true);
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_multiline_comment() {
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return with_eof_error("Unterminated multiline comment", function(){
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var i = find("*/", true),
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            text = S.text.substring(S.pos, i),
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            tok = token("comment2", text, true);
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.pos = i + 2;
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.line += text.split("\n").length - 1;
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.newline_before = text.indexOf("\n") >= 0;
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return tok;
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                });
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_regexp() {
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return with_eof_error("Unterminated regular expression", function(){
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var prev_backslash = false, regexp = "", ch, in_class = false;
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        while ((ch = next(true))) if (prev_backslash) {
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                regexp += "\\" + ch;
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                prev_backslash = false;
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else if (ch == "[") {
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                in_class = true;
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                regexp += ch;
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else if (ch == "]" && in_class) {
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                in_class = false;
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                regexp += ch;
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else if (ch == "/" && !in_class) {
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                break;
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else if (ch == "\\") {
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                prev_backslash = true;
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else {
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                regexp += ch;
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var mods = read_while(function(ch){
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return HOP(REGEXP_MODIFIERS, ch);
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        });
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return token("regexp", [ regexp, mods ]);
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                });
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_operator(prefix) {
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                function grow(op) {
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (!peek()) return op;
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var bigger = op + peek();
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (HOP(OPERATORS, bigger)) {
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return grow(bigger);
4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else {
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return op;
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                };
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return token("operator", grow(prefix || next()));
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function handle_slash() {
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var regex_allowed = S.regex_allowed;
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                switch (peek()) {
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "/":
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.comments_before.push(read_line_comment());
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.regex_allowed = regex_allowed;
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return next_token();
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "*":
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.comments_before.push(read_multiline_comment());
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.regex_allowed = regex_allowed;
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return next_token();
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return S.regex_allowed ? read_regexp() : read_operator("/");
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function handle_dot() {
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return is_digit(peek())
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ? read_num(".")
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        : token("punc", ".");
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function read_word() {
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var word = read_while(is_identifier_char);
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return !HOP(KEYWORDS, word)
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ? token("name", word)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        : HOP(OPERATORS, word)
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ? token("operator", word)
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        : HOP(KEYWORDS_ATOM, word)
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ? token("atom", word)
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        : token("keyword", word);
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function with_eof_error(eof_error, cont) {
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                try {
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return cont();
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } catch(ex) {
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (ex === EX_EOF) parse_error(eof_error);
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        else throw ex;
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function next_token(force_regexp) {
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (force_regexp)
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return read_regexp();
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                skip_whitespace();
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                start_token();
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var ch = peek();
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!ch) return token("eof");
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is_digit(ch)) return read_num();
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (ch == '"' || ch == "'") return read_string();
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (HOP(PUNC_CHARS, ch)) return token("punc", next());
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (ch == ".") return handle_dot();
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (ch == "/") return handle_slash();
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (HOP(OPERATOR_CHARS, ch)) return read_operator();
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is_identifier_char(ch)) return read_word();
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                parse_error("Unexpected character '" + ch + "'");
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        next_token.context = function(nc) {
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (nc) S = nc;
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return S;
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return next_token;
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* -----[ Parser (constants) ]----- */
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var UNARY_PREFIX = array_to_hash([
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "typeof",
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "void",
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "delete",
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "--",
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "++",
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "!",
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "~",
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "-",
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        "+"
5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)]);
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var UNARY_POSTFIX = array_to_hash([ "--", "++" ]);
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var ASSIGNMENT = (function(a, ret, i){
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while (i < a.length) {
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ret[a[i]] = a[i].substr(0, a[i].length - 1);
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                i++;
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ret;
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})(
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ["+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&="],
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        { "=": true },
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        0
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles));
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var PRECEDENCE = (function(a, ret){
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0, n = 1; i < a.length; ++i, ++n) {
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var b = a[i];
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (var j = 0; j < b.length; ++j) {
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ret[b[j]] = n;
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ret;
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)})(
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        [
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["||"],
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["&&"],
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["|"],
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["^"],
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["&"],
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["==", "===", "!=", "!=="],
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["<", ">", "<=", ">=", "in", "instanceof"],
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                [">>", "<<", ">>>"],
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["+", "-"],
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ["*", "/", "%"]
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ],
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {}
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles));
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* -----[ Parser ]----- */
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function NodeWithToken(str, start, end) {
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.name = str;
6095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.start = start;
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        this.end = end;
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)NodeWithToken.prototype.toString = function() { return this.name; };
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function parse($TEXT, strict_mode, embed_tokens) {
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var S = {
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                input       : typeof $TEXT == "string" ? tokenizer($TEXT, true) : $TEXT,
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                token       : null,
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                prev        : null,
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                peeked      : null,
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                in_function : 0,
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                in_loop     : 0,
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                labels      : []
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        S.token = next();
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function is(type, value) {
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return is_token(S.token, type, value);
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function peek() { return S.peeked || (S.peeked = S.input()); };
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function next() {
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.prev = S.token;
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (S.peeked) {
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.token = S.peeked;
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.peeked = null;
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else {
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.token = S.input();
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return S.token;
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function prev() {
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return S.prev;
6485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function croak(msg, line, col, pos) {
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var ctx = S.input.context();
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                js_error(msg,
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         line != null ? line : ctx.tokline,
6545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         col != null ? col : ctx.tokcol,
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         pos != null ? pos : ctx.tokpos);
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function token_error(token, msg) {
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                croak(msg, token.line, token.col);
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function unexpected(token) {
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (token == null)
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        token = S.token;
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function expect_token(type, val) {
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is(type, val)) {
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return next();
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                token_error(S.token, "Unexpected token " + S.token.type + ", expected " + type);
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function expect(punc) { return expect_token("punc", punc); };
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function can_insert_semicolon() {
6785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return !strict_mode && (
6795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.token.nlb || is("eof") || is("punc", "}")
6805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                );
6815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function semicolon() {
6845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("punc", ";")) next();
6855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else if (!can_insert_semicolon()) unexpected();
6865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function as() {
6895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return slice(arguments);
6905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function parenthesised() {
6935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expect("(");
6945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var ex = expression();
6955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expect(")");
6965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return ex;
6975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
6985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function add_tokens(str, start, end) {
7005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return new NodeWithToken(str, start, end);
7015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
7025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var statement = embed_tokens ? function() {
7045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var start = S.token;
7055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var stmt = $statement();
7065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                stmt[0] = add_tokens(stmt[0], start, prev());
7075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return stmt;
7085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } : $statement;
7095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function $statement() {
7115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("operator", "/")) {
7125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.peeked = null;
7135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        S.token = S.input(true); // force regexp
7145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
7155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                switch (S.token.type) {
7165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "num":
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "string":
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "regexp":
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "operator":
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "atom":
7215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return simple_statement();
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "name":
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return is_token(peek(), "punc", ":")
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                ? labeled_statement(prog1(S.token.value, next, next))
7265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                : simple_statement();
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "punc":
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        switch (S.token.value) {
7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "{":
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("block", block_());
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "[":
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "(":
7345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return simple_statement();
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case ";":
7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("block");
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            default:
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                unexpected();
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "keyword":
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        switch (prog1(S.token.value, next)) {
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "break":
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return break_cont("break");
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "continue":
7485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return break_cont("continue");
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "debugger":
7515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                semicolon();
7525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("debugger");
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "do":
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return (function(body){
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                        expect_token("keyword", "while");
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                        return as("do", prog1(parenthesised, semicolon), body);
7585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                })(in_loop(statement));
7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "for":
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return for_();
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "function":
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return function_(true);
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "if":
7675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return if_();
7685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "return":
7705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                if (S.in_function == 0)
7715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                        croak("'return' outside of function");
7725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("return",
7735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          is("punc", ";")
7745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          ? (next(), null)
7755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          : can_insert_semicolon()
7765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          ? null
7775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          : prog1(expression, semicolon));
7785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "switch":
7805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("switch", parenthesised(), switch_block_());
7815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "throw":
7835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("throw", prog1(expression, semicolon));
7845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "try":
7865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return try_();
7875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "var":
7895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return prog1(var_, semicolon);
7905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "const":
7925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return prog1(const_, semicolon);
7935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "while":
7955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("while", parenthesised(), in_loop(statement));
7965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "with":
7985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("with", parenthesised(), statement());
7995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            default:
8015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                unexpected();
8025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
8035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
8045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function labeled_statement(label) {
8075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.labels.push(label);
8085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var start = S.token, stat = statement();
8095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (strict_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
8105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        unexpected(start);
8115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                S.labels.pop();
8125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("label", label, stat);
8135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function simple_statement() {
8165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("stat", prog1(expression, semicolon));
8175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function break_cont(type) {
8205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var name = is("name") ? S.token.value : null;
8215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (name != null) {
8225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
8235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (!member(name, S.labels))
8245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                croak("Label " + name + " without matching loop or statement");
8255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
8265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else if (S.in_loop == 0)
8275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        croak(type + " not inside a loop or switch");
8285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                semicolon();
8295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as(type, name);
8305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function for_() {
8335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expect("(");
8345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var has_var = is("keyword", "var");
8355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (has_var)
8365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
8375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("name") && is_token(peek(), "operator", "in")) {
8385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // for (i in foo)
8395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var name = S.token.value;
8405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next(); next();
8415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var obj = expression();
8425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        expect(")");
8435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return as("for-in", has_var, name, obj, in_loop(statement));
8445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else {
8455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        // classic for
8465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var init = is("punc", ";") ? null : has_var ? var_() : expression();
8475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        expect(";");
8485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var test = is("punc", ";") ? null : expression();
8495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        expect(";");
8505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var step = is("punc", ")") ? null : expression();
8515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        expect(")");
8525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return as("for", init, test, step, in_loop(statement));
8535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
8545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function function_(in_statement) {
8575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var name = is("name") ? prog1(S.token.value, next) : null;
8585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (in_statement && !name)
8595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        unexpected();
8605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expect("(");
8615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as(in_statement ? "defun" : "function",
8625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          name,
8635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          // arguments
8645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          (function(first, a){
8655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  while (!is("punc", ")")) {
8665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          if (first) first = false; else expect(",");
8675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          if (!is("name")) unexpected();
8685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          a.push(S.token.value);
8695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          next();
8705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  }
8715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  next();
8725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  return a;
8735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          })(true, []),
8745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          // body
8755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          (function(){
8765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  ++S.in_function;
8775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  var loop = S.in_loop;
8785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  S.in_loop = 0;
8795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  var a = block_();
8805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  --S.in_function;
8815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  S.in_loop = loop;
8825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  return a;
8835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                          })());
8845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function if_() {
8875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var cond = parenthesised(), body = statement(), belse;
8885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("keyword", "else")) {
8895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
8905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        belse = statement();
8915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
8925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("if", cond, body, belse);
8935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
8945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function block_() {
8965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expect("{");
8975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var a = [];
8985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (!is("punc", "}")) {
8995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (is("eof")) unexpected();
9005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        a.push(statement());
9015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
9025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
9035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return a;
9045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
9055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var switch_block_ = curry(in_loop, function(){
9075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                expect("{");
9085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var a = [], cur = null;
9095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (!is("punc", "}")) {
9105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (is("eof")) unexpected();
9115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (is("keyword", "case")) {
9125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
9135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                cur = [];
9145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push([ expression(), cur ]);
9155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                expect(":");
9165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
9175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        else if (is("keyword", "default")) {
9185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
9195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                expect(":");
9205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                cur = [];
9215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push([ null, cur ]);
9225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
9235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        else {
9245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                if (!cur) unexpected();
9255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                cur.push(statement());
9265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
9275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
9285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
9295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return a;
9305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        });
9315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function try_() {
9335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var body = block_(), bcatch, bfinally;
9345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("keyword", "catch")) {
9355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
9365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        expect("(");
9375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (!is("name"))
9385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                croak("Name expected");
9395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var name = S.token.value;
9405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
9415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        expect(")");
9425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        bcatch = [ name, block_() ];
9435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
9445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("keyword", "finally")) {
9455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
9465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        bfinally = block_();
9475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
9485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (!bcatch && !bfinally)
9495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        croak("Missing catch/finally blocks");
9505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("try", body, bcatch, bfinally);
9515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
9525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function vardefs() {
9545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var a = [];
9555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                for (;;) {
9565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (!is("name"))
9575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                unexpected();
9585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var name = S.token.value;
9595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
9605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (is("operator", "=")) {
9615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
9625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push([ name, expression(false) ]);
9635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else {
9645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push([ name ]);
9655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
9665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (!is("punc", ","))
9675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                break;
9685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
9695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
9705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return a;
9715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
9725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function var_() {
9745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("var", vardefs());
9755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
9765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function const_() {
9785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("const", vardefs());
9795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
9805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function new_() {
9825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var newexp = expr_atom(false), args;
9835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("punc", "(")) {
9845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
9855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        args = expr_list(")");
9865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } else {
9875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        args = [];
9885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
9895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return subscripts(as("new", newexp, args), true);
9905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
9915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function expr_atom(allow_calls) {
9935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("operator", "new")) {
9945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
9955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return new_();
9965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
9975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("operator") && HOP(UNARY_PREFIX, S.token.value)) {
9985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return make_unary("unary-prefix",
9995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          prog1(S.token.value, next),
10005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                          expr_atom(allow_calls));
10015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("punc")) {
10035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        switch (S.token.value) {
10045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "(":
10055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
10065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return subscripts(prog1(expression, curry(expect, ")")), allow_calls);
10075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "[":
10085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
10095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return subscripts(array_(), allow_calls);
10105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            case "{":
10115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
10125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return subscripts(object_(), allow_calls);
10135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
10145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        unexpected();
10155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("keyword", "function")) {
10175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
10185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return subscripts(function_(false), allow_calls);
10195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (HOP(ATOMIC_START_TOKEN, S.token.type)) {
10215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var atom = S.token.type == "regexp"
10225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                ? as("regexp", S.token.value[0], S.token.value[1])
10235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                : as(S.token.type, S.token.value);
10245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return subscripts(prog1(atom, next), allow_calls);
10255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                unexpected();
10275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function expr_list(closing, allow_trailing_comma, allow_empty) {
10305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var first = true, a = [];
10315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (!is("punc", closing)) {
10325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (first) first = false; else expect(",");
10335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (allow_trailing_comma && is("punc", closing)) break;
10345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (is("punc", ",") && allow_empty) {
10355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push([ "atom", "undefined" ]);
10365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else {
10375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push(expression(false));
10385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
10395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
10415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return a;
10425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function array_() {
10455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("array", expr_list("]", !strict_mode, true));
10465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function object_() {
10495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var first = true, a = [];
10505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (!is("punc", "}")) {
10515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (first) first = false; else expect(",");
10525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (!strict_mode && is("punc", "}"))
10535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                // allow trailing comma
10545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                break;
10555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var type = S.token.type;
10565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var name = as_property_name();
10575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (type == "name" && (name == "get" || name == "set") && !is("punc", ":")) {
10585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push([ as_name(), function_(false), name ]);
10595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        } else {
10605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                expect(":");
10615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                a.push([ name, expression(false) ]);
10625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
10635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                next();
10655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as("object", a);
10665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function as_property_name() {
10695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                switch (S.token.type) {
10705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "num":
10715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "string":
10725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return prog1(S.token.value, next);
10735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as_name();
10755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function as_name() {
10785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                switch (S.token.type) {
10795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "name":
10805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "operator":
10815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "keyword":
10825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "atom":
10835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return prog1(S.token.value, next);
10845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    default:
10855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        unexpected();
10865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
10885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function subscripts(expr, allow_calls) {
10905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("punc", ".")) {
10915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
10925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return subscripts(as("dot", expr, as_name()), allow_calls);
10935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("punc", "[")) {
10955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
10965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return subscripts(as("sub", expr, prog1(expression, curry(expect, "]"))), allow_calls);
10975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
10985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (allow_calls && is("punc", "(")) {
10995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
11005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return subscripts(as("call", expr, expr_list(")")), true);
11015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (allow_calls && is("operator") && HOP(UNARY_POSTFIX, S.token.value)) {
11035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return prog1(curry(make_unary, "unary-postfix", S.token.value, expr),
11045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                     next);
11055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return expr;
11075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function make_unary(tag, op, expr) {
11105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if ((op == "++" || op == "--") && !is_assignable(expr))
11115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        croak("Invalid use of " + op + " operator");
11125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return as(tag, op, expr);
11135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function expr_op(left, min_prec) {
11165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var op = is("operator") ? S.token.value : null;
11175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var prec = op != null ? PRECEDENCE[op] : null;
11185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (prec != null && prec > min_prec) {
11195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
11205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var right = expr_op(expr_atom(true), prec);
11215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return expr_op(as("binary", op, left, right), min_prec);
11225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return left;
11245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function expr_ops() {
11275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return expr_op(expr_atom(true), 0);
11285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function maybe_conditional() {
11315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var expr = expr_ops();
11325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("operator", "?")) {
11335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
11345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        var yes = expression(false);
11355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        expect(":");
11365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return as("conditional", expr, yes, expression(false));
11375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return expr;
11395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function is_assignable(expr) {
11425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                switch (expr[0]) {
11435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "dot":
11445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "sub":
11455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return true;
11465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    case "name":
11475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return expr[1] != "this";
11485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function maybe_assign() {
11525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var left = maybe_conditional(), val = S.token.value;
11535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (is("operator") && HOP(ASSIGNMENT, val)) {
11545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        if (is_assignable(left)) {
11555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                next();
11565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                return as("assign", ASSIGNMENT[val], left, maybe_assign());
11575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        }
11585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        croak("Invalid assignment");
11595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return left;
11615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function expression(commas) {
11645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (arguments.length == 0)
11655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        commas = true;
11665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                var expr = maybe_assign();
11675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (commas && is("punc", ",")) {
11685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        next();
11695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return as("seq", expr, expression());
11705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return expr;
11725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        function in_loop(cont) {
11755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                try {
11765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        ++S.in_loop;
11775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return cont();
11785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                } finally {
11795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        --S.in_loop;
11805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
11815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
11825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return as("toplevel", (function(a){
11845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                while (!is("eof"))
11855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        a.push(statement());
11865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return a;
11875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        })([]));
11885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
11905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* -----[ Utilities ]----- */
11925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function curry(f) {
11945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var args = slice(arguments, 1);
11955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return function() { return f.apply(this, args.concat(slice(arguments))); };
11965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
11975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function prog1(ret) {
11995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (ret instanceof Function)
12005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ret = ret();
12015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 1, n = arguments.length; --n > 0; ++i)
12025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                arguments[i]();
12035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ret;
12045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function array_to_hash(a) {
12075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        var ret = {};
12085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = 0; i < a.length; ++i)
12095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                ret[a[i]] = true;
12105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return ret;
12115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function slice(a, start) {
12145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Array.prototype.slice.call(a, start == null ? 0 : start);
12155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function characters(str) {
12185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return str.split("");
12195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function member(name, array) {
12225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (var i = array.length; --i >= 0;)
12235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (array[i] === name)
12245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                        return true;
12255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
12265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function HOP(obj, prop) {
12295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Object.prototype.hasOwnProperty.call(obj, prop);
12305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
12315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* -----[ Exports ]----- */
12335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.tokenizer = tokenizer;
12355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.parse = parse;
12365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.slice = slice;
12375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.curry = curry;
12385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.member = member;
12395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.array_to_hash = array_to_hash;
12405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.PRECEDENCE = PRECEDENCE;
12415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.KEYWORDS_ATOM = KEYWORDS_ATOM;
12425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.RESERVED_WORDS = RESERVED_WORDS;
12435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.KEYWORDS = KEYWORDS;
12445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;
12455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.OPERATORS = OPERATORS;
12465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.is_alphanumeric_char = is_alphanumeric_char;
12475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)exports.is_identifier_char = is_identifier_char;
1248