function () {
                var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;

                function match(x) {
                    var r = x.exec(s), r1;
                    if (r) {
                        l = r[0].length;
                        r1 = r[1];
                        c = r1.charAt(0);
                        s = s.substr(l);
                        from = character + l - r1.length;
                        character += l;
                        return r1;
                    }
                }

                function string(x) {
                    var c, j, r = '', allowNewLine = false;

                    if (jsonmode && x !== '"') {
                        warningAt("Strings must use doublequote.",
                                line, character);
                    }

                    function esc(n) {
                        var i = parseInt(s.substr(j + 1, n), 16);
                        j += n;
                        if (i >= 32 && i <= 126 &&
                                i !== 34 && i !== 92 && i !== 39) {
                            warningAt("Unnecessary escapement.", line, character);
                        }
                        character += n;
                        c = String.fromCharCode(i);
                    }
                    j = 0;
unclosedString:     for (;;) {
                        while (j >= s.length) {
                            j = 0;

                            var cl = line, cf = from;
                            if (!nextLine()) {
                                errorAt("Unclosed string.", cl, cf);
                                break unclosedString;
                            }

                            if (allowNewLine) {
                                allowNewLine = false;
                            } else {
                                warningAt("Unclosed string.", cl, cf);
                            }
                        }
                        c = s.charAt(j);
                        if (c === x) {
                            character += 1;
                            s = s.substr(j + 1);
                            return it('(string)', r, x);
                        }
                        if (c < ' ') {
                            if (c === '\n' || c === '\r') {
                                break;
                            }
                            warningAt("Control character in string: {a}.",
                                    line, character + j, s.slice(0, j));
                        } else if (c === '\\') {
                            j += 1;
                            character += 1;
                            c = s.charAt(j);
                            n = s.charAt(j + 1);
                            switch (c) {
                            case '\\':
                            case '"':
                            case '/':
                                break;
                            case '\'':
                                if (jsonmode) {
                                    warningAt("Avoid \\'.", line, character);
                                }
                                break;
                            case 'b':
                                c = '\b';
                                break;
                            case 'f':
                                c = '\f';
                                break;
                            case 'n':
                                c = '\n';
                                break;
                            case 'r':
                                c = '\r';
                                break;
                            case 't':
                                c = '\t';
                                break;
                            case '0':
                                c = '\0';
                                // Octal literals fail in strict mode
                                // check if the number is between 00 and 07
                                // where 'n' is the token next to 'c'
                                if (n >= 0 && n <= 7 && directive["use strict"]) {
                                    warningAt(
                                    "Octal literals are not allowed in strict mode.",
                                    line, character);
                                }
                                break;
                            case 'u':
                                esc(4);
                                break;
                            case 'v':
                                if (jsonmode) {
                                    warningAt("Avoid \\v.", line, character);
                                }
                                c = '\v';
                                break;
                            case 'x':
                                if (jsonmode) {
                                    warningAt("Avoid \\x-.", line, character);
                                }
                                esc(2);
                                break;
                            case '':
                                // last character is escape character
                                // always allow new line if escaped, but show
                                // warning if option is not set
                                allowNewLine = true;
                                if (option.multistr) {
                                    if (jsonmode) {
                                        warningAt("Avoid EOL escapement.", line, character);
                                    }
                                    c = '';
                                    character -= 1;
                                    break;
                                }
                                warningAt("Bad escapement of EOL. Use option multistr if needed.",
                                    line, character);
                                break;
                            default:
                                warningAt("Bad escapement.", line, character);
                            }
                        }
                        r += c;
                        character += 1;
                        j += 1;
                    }
                }

                for (;;) {
                    if (!s) {
                        return it(nextLine() ? '(endline)' : '(end)', '');
                    }
                    t = match(tx);
                    if (!t) {
                        t = '';
                        c = '';
                        while (s && s < '!') {
                            s = s.substr(1);
                        }
                        if (s) {
                            errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1));
                            s = '';
                        }
                    } else {

    //      identifier

                        if (c.isAlpha() || c === '_' || c === '$') {
                            return it('(identifier)', t);
                        }

    //      number

                        if (c.isDigit()) {
                            if (!isFinite(Number(t))) {
                                warningAt("Bad number '{a}'.",
                                    line, character, t);
                            }
                            if (s.substr(0, 1).isAlpha()) {
                                warningAt("Missing space after '{a}'.",
                                        line, character, t);
                            }
                            if (c === '0') {
                                d = t.substr(1, 1);
                                if (d.isDigit()) {
                                    if (token.id !== '.') {
                                        warningAt("Don't use extra leading zeros '{a}'.",
                                            line, character, t);
                                    }
                                } else if (jsonmode && (d === 'x' || d === 'X')) {
                                    warningAt("Avoid 0x-. '{a}'.",
                                            line, character, t);
                                }
                            }
                            if (t.substr(t.length - 1) === '.') {
                                warningAt(
"A trailing decimal point can be confused with a dot '{a}'.", line, character, t);
                            }
                            return it('(number)', t);
                        }
                        switch (t) {

    //      string

                        case '"':
                        case "'":
                            return string(t);

    //      // comment

                        case '//':
                            s = '';
                            token.comment = true;
                            break;

    //      /* comment

                        case '/*':
                            for (;;) {
                                i = s.search(lx);
                                if (i >= 0) {
                                    break;
                                }
                                if (!nextLine()) {
                                    errorAt("Unclosed comment.", line, character);
                                }
                            }
                            character += i + 2;
                            if (s.substr(i, 1) === '/') {
                                errorAt("Nested comment.", line, character);
                            }
                            s = s.substr(i + 2);
                            token.comment = true;
                            break;

    //      /*members /*jshint /*global

                        case '/*members':
                        case '/*member':
                        case '/*jshint':
                        case '/*jslint':
                        case '/*global':
                        case '*/':
                            return {
                                value: t,
                                type: 'special',
                                line: line,
                                character: character,
                                from: from
                            };

                        case '':
                            break;
    //      /
                        case '/':
                            if (token.id === '/=') {
                                errorAt("A regular expression literal can be confused with '/='.",
                                    line, from);
                            }
                            if (prereg) {
                                depth = 0;
                                captures = 0;
                                l = 0;
                                for (;;) {
                                    b = true;
                                    c = s.charAt(l);
                                    l += 1;
                                    switch (c) {
                                    case '':
                                        errorAt("Unclosed regular expression.", line, from);
                                        return quit('Stopping.', line, from);
                                    case '/':
                                        if (depth > 0) {
                                            warningAt("{a} unterminated regular expression " +
                                                "group(s).", line, from + l, depth);
                                        }
                                        c = s.substr(0, l - 1);
                                        q = {
                                            g: true,
                                            i: true,
                                            m: true
                                        };
                                        while (q[s.charAt(l)] === true) {
                                            q[s.charAt(l)] = false;
                                            l += 1;
                                        }
                                        character += l;
                                        s = s.substr(l);
                                        q = s.charAt(0);
                                        if (q === '/' || q === '*') {
                                            errorAt("Confusing regular expression.",
                                                    line, from);
                                        }
                                        return it('(regexp)', c);
                                    case '\\':
                                        c = s.charAt(l);
                                        if (c < ' ') {
                                            warningAt(
"Unexpected control character in regular expression.", line, from + l);
                                        } else if (c === '<') {
                                            warningAt(
"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
                                        }
                                        l += 1;
                                        break;
                                    case '(':
                                        depth += 1;
                                        b = false;
                                        if (s.charAt(l) === '?') {
                                            l += 1;
                                            switch (s.charAt(l)) {
                                            case ':':
                                            case '=':
                                            case '!':
                                                l += 1;
                                                break;
                                            default:
                                                warningAt(
"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l));
                                            }
                                        } else {
                                            captures += 1;
                                        }
                                        break;
                                    case '|':
                                        b = false;
                                        break;
                                    case ')':
                                        if (depth === 0) {
                                            warningAt("Unescaped '{a}'.",
                                                    line, from + l, ')');
                                        } else {
                                            depth -= 1;
                                        }
                                        break;
                                    case ' ':
                                        q = 1;
                                        while (s.charAt(l) === ' ') {
                                            l += 1;
                                            q += 1;
                                        }
                                        if (q > 1) {
                                            warningAt(
"Spaces are hard to count. Use {{a}}.", line, from + l, q);
                                        }
                                        break;
                                    case '[':
                                        c = s.charAt(l);
                                        if (c === '^') {
                                            l += 1;
                                            if (option.regexp) {
                                                warningAt("Insecure '{a}'.",
                                                        line, from + l, c);
                                            } else if (s.charAt(l) === ']') {
                                                errorAt("Unescaped '{a}'.",
                                                    line, from + l, '^');
                                            }
                                        }
                                        if (c === ']') {
                                            warningAt("Empty class.", line,
                                                    from + l - 1);
                                        }
                                        isLiteral = false;
                                        isInRange = false;
klass:                                  do {
                                            c = s.charAt(l);
                                            l += 1;
                                            switch (c) {
                                            case '[':
                                            case '^':
                                                warningAt("Unescaped '{a}'.",
                                                        line, from + l, c);
                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            case '-':
                                                if (isLiteral && !isInRange) {
                                                    isLiteral = false;
                                                    isInRange = true;
                                                } else if (isInRange) {
                                                    isInRange = false;
                                                } else if (s.charAt(l) === ']') {
                                                    isInRange = true;
                                                } else {
                                                    if (option.regexdash !== (l === 2 || (l === 3 &&
                                                        s.charAt(1) === '^'))) {
                                                        warningAt("Unescaped '{a}'.",
                                                            line, from + l - 1, '-');
                                                    }
                                                    isLiteral = true;
                                                }
                                                break;
                                            case ']':
                                                if (isInRange && !option.regexdash) {
                                                    warningAt("Unescaped '{a}'.",
                                                            line, from + l - 1, '-');
                                                }
                                                break klass;
                                            case '\\':
                                                c = s.charAt(l);
                                                if (c < ' ') {
                                                    warningAt(
"Unexpected control character in regular expression.", line, from + l);
                                                } else if (c === '<') {
                                                    warningAt(
"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
                                                }
                                                l += 1;

                                                // \w, \s and \d are never part of a character range
                                                if (/[wsd]/i.test(c)) {
                                                    if (isInRange) {
                                                        warningAt("Unescaped '{a}'.",
                                                            line, from + l, '-');
                                                        isInRange = false;
                                                    }
                                                    isLiteral = false;
                                                } else if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            case '/':
                                                warningAt("Unescaped '{a}'.",
                                                        line, from + l - 1, '/');

                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            case '<':
                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            default:
                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                            }
                                        } while (c);
                                        break;
                                    case '.':
                                        if (option.regexp) {
                                            warningAt("Insecure '{a}'.", line,
                                                    from + l, c);
                                        }
                                        break;
                                    case ']':
                                    case '?':
                                    case '{':
                                    case '}':
                                    case '+':
                                    case '*':
                                        warningAt("Unescaped '{a}'.", line,
                                                from + l, c);
                                    }
                                    if (b) {
                                        switch (s.charAt(l)) {
                                        case '?':
                                        case '+':
                                        case '*':
                                            l += 1;
                                            if (s.charAt(l) === '?') {
                                                l += 1;
                                            }
                                            break;
                                        case '{':
                                            l += 1;
                                            c = s.charAt(l);
                                            if (c < '0' || c > '9') {
                                                warningAt(
"Expected a number and instead saw '{a}'.", line, from + l, c);
                                            }
                                            l += 1;
                                            low = +c;
                                            for (;;) {
                                                c = s.charAt(l);
                                                if (c < '0' || c > '9') {
                                                    break;
                                                }
                                                l += 1;
                                                low = +c + (low * 10);
                                            }
                                            high = low;
                                            if (c === ',') {
                                                l += 1;
                                                high = Infinity;
                                                c = s.charAt(l);
                                                if (c >= '0' && c <= '9') {
                                                    l += 1;
                                                    high = +c;
                                                    for (;;) {
                                                        c = s.charAt(l);
                                                        if (c < '0' || c > '9') {
                                                            break;
                                                        }
                                                        l += 1;
                                                        high = +c + (high * 10);
                                                    }
                                                }
                                            }
                                            if (s.charAt(l) !== '}') {
                                                warningAt(
"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c);
                                            } else {
                                                l += 1;
                                            }
                                            if (s.charAt(l) === '?') {
                                                l += 1;
                                            }
                                            if (low > high) {
                                                warningAt(
"'{a}' should not be greater than '{b}'.", line, from + l, low, high);
                                            }
                                        }
                                    }
                                }
                                c = s.substr(0, l - 1);
                                character += l;
                                s = s.substr(l);
                                return it('(regexp)', c);
                            }
                            return it('(punctuator)', t);

    //      punctuator

                        case '#':
                            return it('(punctuator)', t);
                        default:
                            return it('(punctuator)', t);
                        }
                    }
                }
            }
function () {
                var b, c, captures, d, depth, high, i, l, low, q, t, isLiteral, isInRange, n;

                function match(x) {
                    var r = x.exec(s), r1;
                    if (r) {
                        l = r[0].length;
                        r1 = r[1];
                        c = r1.charAt(0);
                        s = s.substr(l);
                        from = character + l - r1.length;
                        character += l;
                        return r1;
                    }
                }

                function string(x) {
                    var c, j, r = '', allowNewLine = false;

                    if (jsonmode && x !== '"') {
                        warningAt("Strings must use doublequote.",
                                line, character);
                    }

                    function esc(n) {
                        var i = parseInt(s.substr(j + 1, n), 16);
                        j += n;
                        if (i >= 32 && i <= 126 &&
                                i !== 34 && i !== 92 && i !== 39) {
                            warningAt("Unnecessary escapement.", line, character);
                        }
                        character += n;
                        c = String.fromCharCode(i);
                    }
                    j = 0;
unclosedString:     for (;;) {
                        while (j >= s.length) {
                            j = 0;

                            var cl = line, cf = from;
                            if (!nextLine()) {
                                errorAt("Unclosed string.", cl, cf);
                                break unclosedString;
                            }

                            if (allowNewLine) {
                                allowNewLine = false;
                            } else {
                                warningAt("Unclosed string.", cl, cf);
                            }
                        }
                        c = s.charAt(j);
                        if (c === x) {
                            character += 1;
                            s = s.substr(j + 1);
                            return it('(string)', r, x);
                        }
                        if (c < ' ') {
                            if (c === '\n' || c === '\r') {
                                break;
                            }
                            warningAt("Control character in string: {a}.",
                                    line, character + j, s.slice(0, j));
                        } else if (c === '\\') {
                            j += 1;
                            character += 1;
                            c = s.charAt(j);
                            n = s.charAt(j + 1);
                            switch (c) {
                            case '\\':
                            case '"':
                            case '/':
                                break;
                            case '\'':
                                if (jsonmode) {
                                    warningAt("Avoid \\'.", line, character);
                                }
                                break;
                            case 'b':
                                c = '\b';
                                break;
                            case 'f':
                                c = '\f';
                                break;
                            case 'n':
                                c = '\n';
                                break;
                            case 'r':
                                c = '\r';
                                break;
                            case 't':
                                c = '\t';
                                break;
                            case '0':
                                c = '\0';
                                
                                
                                
                                if (n >= 0 && n <= 7 && directive["use strict"]) {
                                    warningAt(
                                    "Octal literals are not allowed in strict mode.",
                                    line, character);
                                }
                                break;
                            case 'u':
                                esc(4);
                                break;
                            case 'v':
                                if (jsonmode) {
                                    warningAt("Avoid \\v.", line, character);
                                }
                                c = '\v';
                                break;
                            case 'x':
                                if (jsonmode) {
                                    warningAt("Avoid \\x-.", line, character);
                                }
                                esc(2);
                                break;
                            case '':
                                
                                
                                
                                allowNewLine = true;
                                if (option.multistr) {
                                    if (jsonmode) {
                                        warningAt("Avoid EOL escapement.", line, character);
                                    }
                                    c = '';
                                    character -= 1;
                                    break;
                                }
                                warningAt("Bad escapement of EOL. Use option multistr if needed.",
                                    line, character);
                                break;
                            default:
                                warningAt("Bad escapement.", line, character);
                            }
                        }
                        r += c;
                        character += 1;
                        j += 1;
                    }
                }

                for (;;) {
                    if (!s) {
                        return it(nextLine() ? '(endline)' : '(end)', '');
                    }
                    t = match(tx);
                    if (!t) {
                        t = '';
                        c = '';
                        while (s && s < '!') {
                            s = s.substr(1);
                        }
                        if (s) {
                            errorAt("Unexpected '{a}'.", line, character, s.substr(0, 1));
                            s = '';
                        }
                    } else {

    

                        if (c.isAlpha() || c === '_' || c === '$') {
                            return it('(identifier)', t);
                        }

    

                        if (c.isDigit()) {
                            if (!isFinite(Number(t))) {
                                warningAt("Bad number '{a}'.",
                                    line, character, t);
                            }
                            if (s.substr(0, 1).isAlpha()) {
                                warningAt("Missing space after '{a}'.",
                                        line, character, t);
                            }
                            if (c === '0') {
                                d = t.substr(1, 1);
                                if (d.isDigit()) {
                                    if (token.id !== '.') {
                                        warningAt("Don't use extra leading zeros '{a}'.",
                                            line, character, t);
                                    }
                                } else if (jsonmode && (d === 'x' || d === 'X')) {
                                    warningAt("Avoid 0x-. '{a}'.",
                                            line, character, t);
                                }
                            }
                            if (t.substr(t.length - 1) === '.') {
                                warningAt(
"A trailing decimal point can be confused with a dot '{a}'.", line, character, t);
                            }
                            return it('(number)', t);
                        }
                        switch (t) {

    

                        case '"':
                        case "'":
                            return string(t);

    

                        case '
                            s = '';
                            token.comment = true;
                            break;

    
                            return {
                                value: t,
                                type: 'special',
                                line: line,
                                character: character,
                                from: from
                            };

                        case '':
                            break;
    
                        case '/':
                            if (token.id === '/=') {
                                errorAt("A regular expression literal can be confused with '/='.",
                                    line, from);
                            }
                            if (prereg) {
                                depth = 0;
                                captures = 0;
                                l = 0;
                                for (;;) {
                                    b = true;
                                    c = s.charAt(l);
                                    l += 1;
                                    switch (c) {
                                    case '':
                                        errorAt("Unclosed regular expression.", line, from);
                                        return quit('Stopping.', line, from);
                                    case '/':
                                        if (depth > 0) {
                                            warningAt("{a} unterminated regular expression " +
                                                "group(s).", line, from + l, depth);
                                        }
                                        c = s.substr(0, l - 1);
                                        q = {
                                            g: true,
                                            i: true,
                                            m: true
                                        };
                                        while (q[s.charAt(l)] === true) {
                                            q[s.charAt(l)] = false;
                                            l += 1;
                                        }
                                        character += l;
                                        s = s.substr(l);
                                        q = s.charAt(0);
                                        if (q === '/' || q === '*') {
                                            errorAt("Confusing regular expression.",
                                                    line, from);
                                        }
                                        return it('(regexp)', c);
                                    case '\\':
                                        c = s.charAt(l);
                                        if (c < ' ') {
                                            warningAt(
"Unexpected control character in regular expression.", line, from + l);
                                        } else if (c === '<') {
                                            warningAt(
"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
                                        }
                                        l += 1;
                                        break;
                                    case '(':
                                        depth += 1;
                                        b = false;
                                        if (s.charAt(l) === '?') {
                                            l += 1;
                                            switch (s.charAt(l)) {
                                            case ':':
                                            case '=':
                                            case '!':
                                                l += 1;
                                                break;
                                            default:
                                                warningAt(
"Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l));
                                            }
                                        } else {
                                            captures += 1;
                                        }
                                        break;
                                    case '|':
                                        b = false;
                                        break;
                                    case ')':
                                        if (depth === 0) {
                                            warningAt("Unescaped '{a}'.",
                                                    line, from + l, ')');
                                        } else {
                                            depth -= 1;
                                        }
                                        break;
                                    case ' ':
                                        q = 1;
                                        while (s.charAt(l) === ' ') {
                                            l += 1;
                                            q += 1;
                                        }
                                        if (q > 1) {
                                            warningAt(
"Spaces are hard to count. Use {{a}}.", line, from + l, q);
                                        }
                                        break;
                                    case '[':
                                        c = s.charAt(l);
                                        if (c === '^') {
                                            l += 1;
                                            if (option.regexp) {
                                                warningAt("Insecure '{a}'.",
                                                        line, from + l, c);
                                            } else if (s.charAt(l) === ']') {
                                                errorAt("Unescaped '{a}'.",
                                                    line, from + l, '^');
                                            }
                                        }
                                        if (c === ']') {
                                            warningAt("Empty class.", line,
                                                    from + l - 1);
                                        }
                                        isLiteral = false;
                                        isInRange = false;
klass:                                  do {
                                            c = s.charAt(l);
                                            l += 1;
                                            switch (c) {
                                            case '[':
                                            case '^':
                                                warningAt("Unescaped '{a}'.",
                                                        line, from + l, c);
                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            case '-':
                                                if (isLiteral && !isInRange) {
                                                    isLiteral = false;
                                                    isInRange = true;
                                                } else if (isInRange) {
                                                    isInRange = false;
                                                } else if (s.charAt(l) === ']') {
                                                    isInRange = true;
                                                } else {
                                                    if (option.regexdash !== (l === 2 || (l === 3 &&
                                                        s.charAt(1) === '^'))) {
                                                        warningAt("Unescaped '{a}'.",
                                                            line, from + l - 1, '-');
                                                    }
                                                    isLiteral = true;
                                                }
                                                break;
                                            case ']':
                                                if (isInRange && !option.regexdash) {
                                                    warningAt("Unescaped '{a}'.",
                                                            line, from + l - 1, '-');
                                                }
                                                break klass;
                                            case '\\':
                                                c = s.charAt(l);
                                                if (c < ' ') {
                                                    warningAt(
"Unexpected control character in regular expression.", line, from + l);
                                                } else if (c === '<') {
                                                    warningAt(
"Unexpected escaped character '{a}' in regular expression.", line, from + l, c);
                                                }
                                                l += 1;

                                                
                                                if (/[wsd]/i.test(c)) {
                                                    if (isInRange) {
                                                        warningAt("Unescaped '{a}'.",
                                                            line, from + l, '-');
                                                        isInRange = false;
                                                    }
                                                    isLiteral = false;
                                                } else if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            case '/':
                                                warningAt("Unescaped '{a}'.",
                                                        line, from + l - 1, '/');

                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            case '<':
                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                                break;
                                            default:
                                                if (isInRange) {
                                                    isInRange = false;
                                                } else {
                                                    isLiteral = true;
                                                }
                                            }
                                        } while (c);
                                        break;
                                    case '.':
                                        if (option.regexp) {
                                            warningAt("Insecure '{a}'.", line,
                                                    from + l, c);
                                        }
                                        break;
                                    case ']':
                                    case '?':
                                    case '{':
                                    case '}':
                                    case '+':
                                    case '*':
                                        warningAt("Unescaped '{a}'.", line,
                                                from + l, c);
                                    }
                                    if (b) {
                                        switch (s.charAt(l)) {
                                        case '?':
                                        case '+':
                                        case '*':
                                            l += 1;
                                            if (s.charAt(l) === '?') {
                                                l += 1;
                                            }
                                            break;
                                        case '{':
                                            l += 1;
                                            c = s.charAt(l);
                                            if (c < '0' || c > '9') {
                                                warningAt(
"Expected a number and instead saw '{a}'.", line, from + l, c);
                                            }
                                            l += 1;
                                            low = +c;
                                            for (;;) {
                                                c = s.charAt(l);
                                                if (c < '0' || c > '9') {
                                                    break;
                                                }
                                                l += 1;
                                                low = +c + (low * 10);
                                            }
                                            high = low;
                                            if (c === ',') {
                                                l += 1;
                                                high = Infinity;
                                                c = s.charAt(l);
                                                if (c >= '0' && c <= '9') {
                                                    l += 1;
                                                    high = +c;
                                                    for (;;) {
                                                        c = s.charAt(l);
                                                        if (c < '0' || c > '9') {
                                                            break;
                                                        }
                                                        l += 1;
                                                        high = +c + (high * 10);
                                                    }
                                                }
                                            }
                                            if (s.charAt(l) !== '}') {
                                                warningAt(
"Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c);
                                            } else {
                                                l += 1;
                                            }
                                            if (s.charAt(l) === '?') {
                                                l += 1;
                                            }
                                            if (low > high) {
                                                warningAt(
"'{a}' should not be greater than '{b}'.", line, from + l, low, high);
                                            }
                                        }
                                    }
                                }
                                c = s.substr(0, l - 1);
                                character += l;
                                s = s.substr(l);
                                return it('(regexp)', c);
                            }
                            return it('(punctuator)', t);

    

                        case '#':
                            return it('(punctuator)', t);
                        default:
                            return it('(punctuator)', t);
                        }
                    }
                }
            }
function ( ) { var b , c , captures , d , depth , high , i , l , low , q , t , isLiteral , isInRange , n ; function match ( x ) { var r = x . exec ( s ) , r1 ; if ( r ) { l = r [ 0 ] . length ; r1 = r [ 1 ] ; c = r1 . charAt ( 0 ) ; s = s . substr ( l ) ; from = character + l - r1 . length ; character += l ; return r1 ; } } function string ( x ) { var c , j , r = '' , allowNewLine = false ; if ( jsonmode && x !== '"' ) { warningAt ( "Strings must use doublequote." , line , character ) ; } function esc ( n ) { var i = parseInt ( s . substr ( j + 1 , n ) , 16 ) ; j += n ; if ( i >= 32 && i <= 126 && i !== 34 && i !== 92 && i !== 39 ) { warningAt ( "Unnecessary escapement." , line , character ) ; } character += n ; c = String . fromCharCode ( i ) ; } j = 0 ; unclosedString : for ( ; ; ) { while ( j >= s . length ) { j = 0 ; var cl = line , cf = from ; if ( ! nextLine ( ) ) { errorAt ( "Unclosed string." , cl , cf ) ; break unclosedString ; } if ( allowNewLine ) { allowNewLine = false ; } else { warningAt ( "Unclosed string." , cl , cf ) ; } } c = s . charAt ( j ) ; if ( c === x ) { character += 1 ; s = s . substr ( j + 1 ) ; return it ( '(string)' , r , x ) ; } if ( c < ' ' ) { if ( c === '\n' || c === '\r' ) { break ; } warningAt ( "Control character in string: {a}." , line , character + j , s . slice ( 0 , j ) ) ; } else if ( c === '\\' ) { j += 1 ; character += 1 ; c = s . charAt ( j ) ; n = s . charAt ( j + 1 ) ; switch ( c ) { case '\\' : case '"' : case '/' : break ; case '\'' : if ( jsonmode ) { warningAt ( "Avoid \\'." , line , character ) ; } break ; case 'b' : c = '\b' ; break ; case 'f' : c = '\f' ; break ; case 'n' : c = '\n' ; break ; case 'r' : c = '\r' ; break ; case 't' : c = '\t' ; break ; case '0' : c = '\0' ; // Octal literals fail in strict mode // check if the number is between 00 and 07 // where 'n' is the token next to 'c' if ( n >= 0 && n <= 7 && directive [ "use strict" ] ) { warningAt ( "Octal literals are not allowed in strict mode." , line , character ) ; } break ; case 'u' : esc ( 4 ) ; break ; case 'v' : if ( jsonmode ) { warningAt ( "Avoid \\v." , line , character ) ; } c = '\v' ; break ; case 'x' : if ( jsonmode ) { warningAt ( "Avoid \\x-." , line , character ) ; } esc ( 2 ) ; break ; case '' : // last character is escape character // always allow new line if escaped, but show // warning if option is not set allowNewLine = true ; if ( option . multistr ) { if ( jsonmode ) { warningAt ( "Avoid EOL escapement." , line , character ) ; } c = '' ; character -= 1 ; break ; } warningAt ( "Bad escapement of EOL. Use option multistr if needed." , line , character ) ; break ; default : warningAt ( "Bad escapement." , line , character ) ; } } r += c ; character += 1 ; j += 1 ; } } for ( ; ; ) { if ( ! s ) { return it ( nextLine ( ) ? '(endline)' : '(end)' , '' ) ; } t = match ( tx ) ; if ( ! t ) { t = '' ; c = '' ; while ( s && s < '!' ) { s = s . substr ( 1 ) ; } if ( s ) { errorAt ( "Unexpected '{a}'." , line , character , s . substr ( 0 , 1 ) ) ; s = '' ; } } else { //      identifier if ( c . isAlpha ( ) || c === '_' || c === '$' ) { return it ( '(identifier)' , t ) ; } //      number if ( c . isDigit ( ) ) { if ( ! isFinite ( Number ( t ) ) ) { warningAt ( "Bad number '{a}'." , line , character , t ) ; } if ( s . substr ( 0 , 1 ) . isAlpha ( ) ) { warningAt ( "Missing space after '{a}'." , line , character , t ) ; } if ( c === '0' ) { d = t . substr ( 1 , 1 ) ; if ( d . isDigit ( ) ) { if ( token . id !== '.' ) { warningAt ( "Don't use extra leading zeros '{a}'." , line , character , t ) ; } } else if ( jsonmode && ( d === 'x' || d === 'X' ) ) { warningAt ( "Avoid 0x-. '{a}'." , line , character , t ) ; } } if ( t . substr ( t . length - 1 ) === '.' ) { warningAt ( "A trailing decimal point can be confused with a dot '{a}'." , line , character , t ) ; } return it ( '(number)' , t ) ; } switch ( t ) { //      string case '"' : case "'" : return string ( t ) ; //      // comment case '//' : s = '' ; token . comment = true ; break ; //      /* comment case '/*' : for ( ; ; ) { i = s . search ( lx ) ; if ( i >= 0 ) { break ; } if ( ! nextLine ( ) ) { errorAt ( "Unclosed comment." , line , character ) ; } } character += i + 2 ; if ( s . substr ( i , 1 ) === '/' ) { errorAt ( "Nested comment." , line , character ) ; } s = s . substr ( i + 2 ) ; token . comment = true ; break ; //      /*members /*jshint /*global case '/*members' : case '/*member' : case '/*jshint' : case '/*jslint' : case '/*global' : case '*/' : return { value : t , type : 'special' , line : line , character : character , from : from } ; case '' : break ; //      / case '/' : if ( token . id === '/=' ) { errorAt ( "A regular expression literal can be confused with '/='." , line , from ) ; } if ( prereg ) { depth = 0 ; captures = 0 ; l = 0 ; for ( ; ; ) { b = true ; c = s . charAt ( l ) ; l += 1 ; switch ( c ) { case '' : errorAt ( "Unclosed regular expression." , line , from ) ; return quit ( 'Stopping.' , line , from ) ; case '/' : if ( depth > 0 ) { warningAt ( "{a} unterminated regular expression " + "group(s)." , line , from + l , depth ) ; } c = s . substr ( 0 , l - 1 ) ; q = { g : true , i : true , m : true } ; while ( q [ s . charAt ( l ) ] === true ) { q [ s . charAt ( l ) ] = false ; l += 1 ; } character += l ; s = s . substr ( l ) ; q = s . charAt ( 0 ) ; if ( q === '/' || q === '*' ) { errorAt ( "Confusing regular expression." , line , from ) ; } return it ( '(regexp)' , c ) ; case '\\' : c = s . charAt ( l ) ; if ( c < ' ' ) { warningAt ( "Unexpected control character in regular expression." , line , from + l ) ; } else if ( c === '<' ) { warningAt ( "Unexpected escaped character '{a}' in regular expression." , line , from + l , c ) ; } l += 1 ; break ; case '(' : depth += 1 ; b = false ; if ( s . charAt ( l ) === '?' ) { l += 1 ; switch ( s . charAt ( l ) ) { case ':' : case '=' : case '!' : l += 1 ; break ; default : warningAt ( "Expected '{a}' and instead saw '{b}'." , line , from + l , ':' , s . charAt ( l ) ) ; } } else { captures += 1 ; } break ; case '|' : b = false ; break ; case ')' : if ( depth === 0 ) { warningAt ( "Unescaped '{a}'." , line , from + l , ')' ) ; } else { depth -= 1 ; } break ; case ' ' : q = 1 ; while ( s . charAt ( l ) === ' ' ) { l += 1 ; q += 1 ; } if ( q > 1 ) { warningAt ( "Spaces are hard to count. Use {{a}}." , line , from + l , q ) ; } break ; case '[' : c = s . charAt ( l ) ; if ( c === '^' ) { l += 1 ; if ( option . regexp ) { warningAt ( "Insecure '{a}'." , line , from + l , c ) ; } else if ( s . charAt ( l ) === ']' ) { errorAt ( "Unescaped '{a}'." , line , from + l , '^' ) ; } } if ( c === ']' ) { warningAt ( "Empty class." , line , from + l - 1 ) ; } isLiteral = false ; isInRange = false ; klass : do { c = s . charAt ( l ) ; l += 1 ; switch ( c ) { case '[' : case '^' : warningAt ( "Unescaped '{a}'." , line , from + l , c ) ; if ( isInRange ) { isInRange = false ; } else { isLiteral = true ; } break ; case '-' : if ( isLiteral && ! isInRange ) { isLiteral = false ; isInRange = true ; } else if ( isInRange ) { isInRange = false ; } else if ( s . charAt ( l ) === ']' ) { isInRange = true ; } else { if ( option . regexdash !== ( l === 2 || ( l === 3 && s . charAt ( 1 ) === '^' ) ) ) { warningAt ( "Unescaped '{a}'." , line , from + l - 1 , '-' ) ; } isLiteral = true ; } break ; case ']' : if ( isInRange && ! option . regexdash ) { warningAt ( "Unescaped '{a}'." , line , from + l - 1 , '-' ) ; } break klass ; case '\\' : c = s . charAt ( l ) ; if ( c < ' ' ) { warningAt ( "Unexpected control character in regular expression." , line , from + l ) ; } else if ( c === '<' ) { warningAt ( "Unexpected escaped character '{a}' in regular expression." , line , from + l , c ) ; } l += 1 ; // \w, \s and \d are never part of a character range if ( / [wsd] / i . test ( c ) ) { if ( isInRange ) { warningAt ( "Unescaped '{a}'." , line , from + l , '-' ) ; isInRange = false ; } isLiteral = false ; } else if ( isInRange ) { isInRange = false ; } else { isLiteral = true ; } break ; case '/' : warningAt ( "Unescaped '{a}'." , line , from + l - 1 , '/' ) ; if ( isInRange ) { isInRange = false ; } else { isLiteral = true ; } break ; case '<' : if ( isInRange ) { isInRange = false ; } else { isLiteral = true ; } break ; default : if ( isInRange ) { isInRange = false ; } else { isLiteral = true ; } } } while ( c ) ; break ; case '.' : if ( option . regexp ) { warningAt ( "Insecure '{a}'." , line , from + l , c ) ; } break ; case ']' : case '?' : case '{' : case '}' : case '+' : case '*' : warningAt ( "Unescaped '{a}'." , line , from + l , c ) ; } if ( b ) { switch ( s . charAt ( l ) ) { case '?' : case '+' : case '*' : l += 1 ; if ( s . charAt ( l ) === '?' ) { l += 1 ; } break ; case '{' : l += 1 ; c = s . charAt ( l ) ; if ( c < '0' || c > '9' ) { warningAt ( "Expected a number and instead saw '{a}'." , line , from + l , c ) ; } l += 1 ; low = + c ; for ( ; ; ) { c = s . charAt ( l ) ; if ( c < '0' || c > '9' ) { break ; } l += 1 ; low = + c + ( low * 10 ) ; } high = low ; if ( c === ',' ) { l += 1 ; high = Infinity ; c = s . charAt ( l ) ; if ( c >= '0' && c <= '9' ) { l += 1 ; high = + c ; for ( ; ; ) { c = s . charAt ( l ) ; if ( c < '0' || c > '9' ) { break ; } l += 1 ; high = + c + ( high * 10 ) ; } } } if ( s . charAt ( l ) !== '}' ) { warningAt ( "Expected '{a}' and instead saw '{b}'." , line , from + l , '}' , c ) ; } else { l += 1 ; } if ( s . charAt ( l ) === '?' ) { l += 1 ; } if ( low > high ) { warningAt ( "'{a}' should not be greater than '{b}'." , line , from + l , low , high ) ; } } } } c = s . substr ( 0 , l - 1 ) ; character += l ; s = s . substr ( l ) ; return it ( '(regexp)' , c ) ; } return it ( '(punctuator)' , t ) ; //      punctuator case '#' : return it ( '(punctuator)' , t ) ; default : return it ( '(punctuator)' , t ) ; } } } }
token -- this is called by advance to get the next token
token -- this is called by advance to get the next token