UNPKG

livescript

Version:

LiveScript is a language which compiles to JavaScript. It has a straightforward mapping to JavaScript and allows you to write expressive code devoid of repetitive boilerplate. While LiveScript adds many features to assist in functional style programming,

1,739 lines 55.5 kB
// Generated by LiveScript 1.6.0 var string, TABS, unlines, enlines, enslash, reslash, camelize, deheregex, character, KEYWORDS_SHARED, KEYWORDS_UNUSED, JS_KEYWORDS, LS_KEYWORDS, ID, SYMBOL, SPACE, MULTIDENT, SIMPLESTR, JSTOKEN, BSTOKEN, NUMBER, NUMBER_OMIT, REGEX, HEREGEX_OMIT, LASTDENT, INLINEDENT, NONASCII, OPENERS, CLOSERS, INVERSES, i, o, c, CHAIN, ARG, BLOCK_USERS, slice$ = [].slice, arrayFrom$ = Array.from || function(x){return slice$.call(x);}; exports.lex = function(code, options){ return clone$(exports).tokenize(code || '', options || {}); }; exports.rewrite = function(it){ var ref$; it || (it = this.tokens); firstPass(it); addImplicitIndentation(it); rewriteBlockless(it); addImplicitParentheses(it); addImplicitBraces(it); expandLiterals(it); if (((ref$ = it[0]) != null ? ref$[0] : void 8) === 'NEWLINE') { it.shift(); } return it; }; exports.tokenize = function(code, o){ var i, prevIndex, c, charsConsumed, that; this.inter || (code = code.replace(/[\r\u2028\u2029\uFEFF]/g, '')); code = '\n' + code; this.tokens = [this.last = ['NEWLINE', '\n', 0, 0]]; this.line = ~-o.line; this.column = o.column || 0; this.dents = []; this.closes = []; this.parens = []; this.flags = []; i = 0; prevIndex = i; this.charsCounted = 0; this.isAtPrefix = true; while (c = code.charAt(i)) { charsConsumed = i - prevIndex; prevIndex = i; if (this.charsCounted > charsConsumed) { throw new Error('Location information out-of-sync in lexer'); } this.column += charsConsumed - this.charsCounted; this.charsCounted = 0; switch (c) { case ' ': i += this.doSpace(code, i); break; case '\n': i += this.doLine(code, i); break; case '\\': i += this.doBackslash(code, i); break; case '\'': case '"': i += this.doString(code, i, c); break; case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": i += this.doNumber(code, i); break; case '/': switch (code.charAt(i + 1)) { case '*': i += this.doComment(code, i); break; case '/': i += this.doHeregex(code, i); break; default: i += this.doRegex(code, i) || this.doLiteral(code, i); } break; case '`': if ('`' === code.charAt(i + 1)) { i += this.doJS(code, i); } else { i += this.doLiteral(code, i); } break; default: i += this.doID(code, i) || this.doLiteral(code, i) || this.doSpace(code, i); } } this.dedent(this.dent); if (that = this.closes.pop()) { this.carp("missing `" + that + "`"); } if (this.inter) { this.rest == null && this.carp('unterminated interpolation'); } else { this.last.spaced = true; this.newline(); } o.raw || this.rewrite(); return this.tokens; }; exports.dent = 0; exports.identifiers = {}; exports.reset = function(){ this.dent = 0; this.identifiers = {}; }; exports.hasOwn = Object.prototype.hasOwnProperty; exports.checkConsistency = function(camel, id){ if (this.hasOwn.call(this.identifiers, camel) && this.identifiers[camel] !== id) { throw new ReferenceError("Inconsistent use of " + camel + " as " + id + " on line " + (-~this.line)); } else { return this.identifiers[camel] = id; } }; exports.doID = function(code, index){ var regexMatch, input, id, e, last, ref$, tag, ref1$, that; input = (regexMatch = (ID.lastIndex = index, ID).exec(code))[0]; if (!input) { return 0; } id = camelize(regexMatch[1]); if (/-/.test(regexMatch[1])) { this.checkConsistency(id, regexMatch[1]); } if (NONASCII.test(id)) { try { Function("var " + id); } catch (e$) { e = e$; this.carp("invalid identifier '" + id + "'"); } } last = this.last; if (regexMatch[2] || last[0] === 'DOT' || this.adi()) { this.token('ID', in$(id, JS_KEYWORDS) ? (ref$ = Object(id), ref$.reserved = true, ref$) : id); if (regexMatch[2]) { this.token(':', ':'); } return input.length; } switch (id) { case 'true': case 'false': case 'on': case 'off': case 'yes': case 'no': case 'null': case 'void': case 'arguments': case 'debugger': tag = 'LITERAL'; break; case 'new': case 'do': case 'typeof': case 'delete': tag = 'UNARY'; break; case 'yield': case 'await': tag = 'YIELD'; break; case 'return': case 'throw': tag = 'HURL'; break; case 'break': case 'continue': tag = 'JUMP'; break; case 'this': case 'eval': case 'super': return this.token('LITERAL', id, true).length; case 'for': id = []; this.fset('for', true); this.fset('to', false); this.fset('by', true); break; case 'then': this.fset('for', false); this.fset('to', false); break; case 'catch': case 'function': id = ''; break; case 'in': case 'of': if (this.fget('for')) { this.fset('for', false); if (id === 'in') { this.fset('by', true); id = ''; if (last[0] === 'ID' && ((ref$ = (ref1$ = this.tokens)[ref1$.length - 2][0]) === ',' || ref$ === ']' || ref$ === '}')) { id = this.tokens.pop()[1]; if ((ref$ = this.tokens)[ref$.length - 1][0] === ',') { this.tokens.pop(); } } } break; } // fallthrough case 'instanceof': if (last[1] === '!') { id = this.tokens.pop()[1] + id; } tag = (ref$ = this.tokens)[ref$.length - 1][0] === '(' ? 'BIOPR' : 'RELATION'; break; case 'not': if (last.alias && last[1] === '===') { return last[1] = '!==', 3; } tag = 'UNARY'; id = '!'; break; case 'and': case 'or': case 'xor': case 'is': case 'isnt': this.unline(); tag = id === 'is' || id === 'isnt' ? 'COMPARE' : 'LOGIC'; if (last[0] === '(') { tag = 'BIOP'; } this.token(tag, (function(){ switch (id) { case 'is': return '==='; case 'isnt': return '!=='; case 'or': return '||'; case 'and': return '&&'; case 'xor': return 'xor'; } }())); this.last.alias = true; return id.length; case 'unless': tag = 'IF'; break; case 'until': tag = 'WHILE'; break; case 'import': if (last[0] === '(') { id = '<<<'; tag = 'BIOP'; } else { if (able(this.tokens)) { id = '<<<'; } else { tag = 'DECL'; } } break; case 'export': case 'const': case 'var': tag = 'DECL'; break; case 'with': tag = (function(){ switch (false) { case !able(this.tokens): return 'CLONEPORT'; case last[0] !== '(': return 'BIOP'; default: return 'WITH'; } }.call(this)); break; case 'when': tag = 'CASE'; // fallthrough case 'case': if (this.doCase()) { return input.length; } break; case 'match': tag = 'SWITCH'; break; case 'loop': this.token('WHILE', id); this.token('LITERAL', 'true'); return input.length; case 'let': case 'own': if (last[0] === 'FOR' && !in$(id, last[1])) { last[1].push(id); return 3; } // fallthrough default: if (in$(id, KEYWORDS_SHARED)) { break; } if (in$(id, KEYWORDS_UNUSED)) { this.carp("reserved word '" + id + "'"); } if (!last[1] && ((ref$ = last[0]) === 'FUNCTION' || ref$ === 'GENERATOR' || ref$ === 'LABEL')) { last[1] = id; last.spaced = false; return input.length; } tag = 'ID'; switch (id) { case 'otherwise': if ((ref$ = last[0]) === 'CASE' || ref$ === '|') { last[0] = 'DEFAULT'; return id.length; } break; case 'all': if (that = last[1] === '<<<' && '<' || last[1] === 'import' && 'All') { last[1] += that; return 3; } break; case 'from': if (last[1] === 'yield') { last[1] += 'from'; return 4; } this.forange() && (tag = 'FROM'); break; case 'to': case 'til': this.forange() && this.tokens.push(['FROM', '', this.line, this.column], ['STRNUM', '0', this.line, this.column]); if (this.fget('from')) { this.fset('from', false); this.fset('by', true); tag = 'TO'; } else if (!last.callable && last[0] === 'STRNUM' && (ref$ = this.tokens)[ref$.length - 2][0] === '[') { last[0] = 'RANGE'; last.op = id; return id.length; } else if (in$(']', this.closes)) { this.token('TO', id); return id.length; } break; case 'by': if (last[0] === 'STRNUM' && (ref$ = this.tokens)[ref$.length - 2][0] === 'RANGE' && (ref$ = this.tokens)[ref$.length - 3][0] === '[') { tag = 'RANGE_BY'; } else if (in$(']', this.closes)) { tag = 'BY'; } else if (this.fget('by') && last[0] !== 'FOR') { tag = 'BY'; this.fset('by', false); } break; case 'ever': if (last[0] === 'FOR') { this.fset('for', false); last[0] = 'WHILE'; tag = 'LITERAL'; id = 'true'; } } } tag || (tag = regexMatch[1].toUpperCase()); if ((tag === 'COMPARE' || tag === 'LOGIC' || tag === 'RELATION') && last[0] === '(') { tag = tag === 'RELATION' ? 'BIOPR' : 'BIOP'; } if (tag === 'THEN' || tag === 'IF' || tag === 'WHILE') { this.fset('for', false); this.fset('by', false); } if (tag === 'RELATION' || tag === 'THEN' || tag === 'ELSE' || tag === 'CASE' || tag === 'DEFAULT' || tag === 'CATCH' || tag === 'FINALLY' || tag === 'IN' || tag === 'OF' || tag === 'FROM' || tag === 'TO' || tag === 'BY' || tag === 'EXTENDS' || tag === 'IMPLEMENTS' || tag === 'WHERE') { this.unline(); } this.token(tag, id); return input.length; }; exports.doNumber = function(code, lastIndex){ var input, regexMatch, last, radix, num, rnum, bound, ref$; NUMBER.lastIndex = lastIndex; if (!(input = (regexMatch = NUMBER.exec(code))[0])) { return 0; } last = this.last; if (regexMatch[5] && (last[0] === 'DOT' || this.adi())) { this.token('STRNUM', regexMatch[4].replace(NUMBER_OMIT, '')); return regexMatch[4].length; } if (radix = regexMatch[1]) { num = parseInt(rnum = regexMatch[2].replace(NUMBER_OMIT, ''), radix); bound = false; if (radix > 36 || radix < 2) { if (/[0-9]/.exec(rnum)) { this.carp("invalid number base " + radix + " (with number " + rnum + "),base must be from 2 to 36"); } else { bound = true; } } if (isNaN(num) || num === parseInt(rnum.slice(0, -1), radix)) { this.strnum(regexMatch[1]); this.token('DOT', '.~'); this.token('ID', regexMatch[2]); return input.length; } num += ''; } else { num = (regexMatch[3] || input).replace(NUMBER_OMIT, ''); if (regexMatch[3] && num.charAt() === '0' && ((ref$ = num.charAt(1)) !== '' && ref$ !== '.')) { this.carp("deprecated octal literal " + regexMatch[4]); } } if (!last.spaced && last[0] === '+-') { last[0] = 'STRNUM'; last[1] += num; return input.length; } this.strnum(num); return input.length; }; exports.doString = function(code, index, q){ var parts, str; if (q === code.charAt(index + 1)) { return q === code.charAt(index + 2) ? this.doHeredoc(code, index, q) : (this.strnum(q + q), 2); } if (q === '"') { parts = this.interpolate(code, index, q); this.addInterpolated(parts, unlines); return parts.size; } str = (SIMPLESTR.lastIndex = index, SIMPLESTR).exec(code)[0] || this.carp('unterminated string'); this.strnum(unlines(this.string(q, str.slice(1, -1)))); return this.countLines(str).length; }; exports.doHeredoc = function(code, index, q){ var end, raw, doc, parts, tabs, i$, len$, i, t; if (q === '\'') { ~(end = code.indexOf(q + q + q, index + 3)) || this.carp('unterminated heredoc'); raw = code.slice(index + 3, end); doc = raw.replace(LASTDENT, ''); this.strnum(enlines(this.string(q, lchomp(detab(doc, heretabs(doc)))))); return this.countLines(raw).length + 6; } parts = this.interpolate(code, index, q + q + q); tabs = heretabs(code.slice(index + 3, index + parts.size - 3).replace(LASTDENT, '')); for (i$ = 0, len$ = parts.length; i$ < len$; ++i$) { i = i$; t = parts[i$]; if (t[0] === 'S') { if (i + 1 === parts.length) { t[1] = t[1].replace(LASTDENT, ''); } t[1] = detab(t[1], tabs); if (i === 0) { t[1] = lchomp(t[1]); } } } this.addInterpolated(parts, enlines); return parts.size; }; exports.doComment = function(code, index){ var comment, end, ref$; comment = ~(end = code.indexOf('*/', index + 2)) ? code.slice(index, end + 2) : code.slice(index) + '*/'; if ((ref$ = this.last[0]) === 'NEWLINE' || ref$ === 'INDENT' || ref$ === 'THEN') { this.token('COMMENT', detab(comment, this.dent)); this.token('NEWLINE', '\n'); } return this.countLines(comment).length; }; exports.doJS = function(code, lastIndex){ var js, ref$; JSTOKEN.lastIndex = lastIndex; js = JSTOKEN.exec(code)[0] || this.carp('unterminated JS literal'); this.token('LITERAL', (ref$ = Object(detab(js.slice(2, -2), this.dent)), ref$.js = true, ref$), true); return this.countLines(js).length; }; exports.doRegex = function(code, index){ var divisible, ref$, input, body, flag; if (divisible = able(this.tokens) || this.last[0] === 'CREMENT') { if (!this.last.spaced || ((ref$ = code.charAt(index + 1)) === ' ' || ref$ === '=')) { return 0; } } ref$ = (REGEX.lastIndex = index, REGEX).exec(code), input = ref$[0], body = ref$[1], flag = ref$[2]; if (input) { this.regex(body, flag); } else if (!divisible && this.last[0] !== '(') { this.carp('unterminated regex'); } return input.length; }; exports.doHeregex = function(code, index){ var tokens, last, parts, rest, flag, i$, i, t, dynaflag, len$, val, one; tokens = this.tokens, last = this.last; parts = this.interpolate(code, index, '//'); rest = code.slice(index + parts.size); flag = this.validate(/^(?:[gimy]{1,4}|[?$]?)/.exec(rest)[0]); if (parts[1]) { if (flag === '$') { this.adi(); this.token('(', '"'); } else { tokens.push(['ID', 'RegExp', last[2], last[3]], ['CALL(', '', last[2], last[3]]); if (flag === '?') { for (i$ = parts.length - 1; i$ >= 0; --i$) { i = i$; t = parts[i$]; if (t[0] === 'TOKENS') { dynaflag = parts.splice(i, 1)[0][1]; break; } } } } for (i$ = 0, len$ = parts.length; i$ < len$; ++i$) { i = i$; t = parts[i$]; if (t[0] === 'TOKENS') { tokens.push.apply(tokens, t[1]); } else { val = deheregex(t[1]); if (one && !val) { continue; } one = tokens.push((t[0] = 'STRNUM', t[1] = this.string('\'', enslash(val)), t)); } tokens.push(['+-', '+', tokens[tokens.length - 1][2], tokens[tokens.length - 1][3]]); } --tokens.length; if (dynaflag || flag >= 'g') { this.token(',', ','); if (dynaflag) { tokens.push.apply(tokens, dynaflag); } else { this.token('STRNUM', "'" + flag + "'"); } } this.token(flag === '$' ? ')' : ')CALL', ''); } else { this.regex(reslash(deheregex(parts[0][1])), flag); } return parts.size + flag.length; }; exports.doBackslash = function(code, lastIndex){ var ref$, input, word; BSTOKEN.lastIndex = lastIndex; ref$ = BSTOKEN.exec(code), input = ref$[0], word = ref$[1]; if (word) { this.strnum(this.string('\'', word)); } else { this.countLines(input); } return input.length; }; exports.doLine = function(code, index){ var ref$, input, tabs, length, last, that, delta, tag, val; ref$ = (MULTIDENT.lastIndex = index, MULTIDENT).exec(code), input = ref$[0], tabs = ref$[1]; length = this.countLines(input).length; last = this.last; last.eol = true; last.spaced = true; if (index + length >= code.length) { return length; } if (that = tabs && (this.emender || (this.emender = RegExp('[^' + tabs.charAt() + ']'))).exec(tabs)) { this.carp("contaminated indent " + escape(that)); } if (0 > (delta = tabs.length - this.dent)) { this.dedent(-delta); this.newline(); } else { tag = last[0], val = last[1]; if (tag === 'ASSIGN' && ((ref$ = val + '') !== '=' && ref$ !== ':=' && ref$ !== '+=') || tag === 'CREMENT' && val === '++' && (ref$ = this.tokens)[ref$.length - 2].spaced || (tag === '+-' || tag === 'PIPE' || tag === 'BACKPIPE' || tag === 'COMPOSE' || tag === 'DOT' || tag === 'LOGIC' || tag === 'MATH' || tag === 'COMPARE' || tag === 'RELATION' || tag === 'SHIFT' || tag === 'IN' || tag === 'OF' || tag === 'TO' || tag === 'BY' || tag === 'FROM' || tag === 'EXTENDS' || tag === 'IMPLEMENTS')) { return length; } if (delta) { this.indent(delta); } else { this.newline(); } } this.fset('for', false); this.fset('by', false); return length; }; exports.doSpace = function(code, lastIndex){ var input; SPACE.lastIndex = lastIndex; if (input = SPACE.exec(code)[0]) { this.last.spaced = true; } return input.length; }; exports.doCase = function(){ var ref$, ref1$; this.fset('for', false); if (((ref$ = this.last[0]) === 'ASSIGN' || ref$ === '->' || ref$ === ':') || (this.last[0] === 'INDENT' && ((ref$ = (ref1$ = this.tokens)[ref1$.length - 2][0]) === 'ASSIGN' || ref$ === '->' || ref$ === ':'))) { this.token('SWITCH', 'switch'); return this.token('CASE', 'case'); } }; exports.doLiteral = function(code, index){ var sym, tag, val, ref$, that; if (!(sym = (SYMBOL.lastIndex = index, SYMBOL).exec(code)[0])) { return 0; } switch (tag = val = sym) { case '|': tag = 'CASE'; if (this.doCase()) { return sym.length; } break; case '|>': tag = 'PIPE'; break; case '`': tag = 'BACKTICK'; break; case '<<': case '>>': tag = 'COMPOSE'; break; case '<|': tag = 'BACKPIPE'; break; case '+': case '-': tag = '+-'; break; case '&&': case '||': tag = 'LOGIC'; break; case '.&.': case '.|.': case '.^.': tag = 'BITWISE'; break; case '^^': tag = 'CLONE'; break; case '**': case '^': tag = 'POWER'; break; case '?': if (this.last[0] === '(') { this.token('PARAM(', '('); this.token(')PARAM', ')'); this.token('->', '->'); this.token('ID', 'it'); } else { if (this.last.spaced) { tag = 'LOGIC'; } } break; case '/': case '%': case '%%': tag = 'MATH'; break; case '++': case '--': tag = 'CREMENT'; break; case '<<<': case '<<<<': tag = 'IMPORT'; break; case ';': tag = 'NEWLINE'; this.fset('by', false); break; case '..': this.token('LITERAL', '..', true); return 2; case '.': if (this.last[1] === '?') { this.last[0] = '?'; } tag = 'DOT'; break; case ',': switch (this.last[0]) { case ',': case '[': case '(': case 'CALL(': this.token('LITERAL', 'void'); break; case 'FOR': case 'OWN': this.token('ID', ''); } break; case '!=': case '~=': if (!(able(this.tokens) || ((ref$ = this.last[0]) === '(' || ref$ === 'CREMENT'))) { this.tokens.push(val === '!=' ? ['UNARY', '!', this.line, this.column] : ['UNARY', '~', this.line, this.column], ['ASSIGN', '=', this.line, this.column]); return 2; } // fallthrough case '!~=': case '==': val = (function(){ switch (val) { case '~=': return '=='; case '!~=': return '!='; case '==': return '==='; case '!=': return '!=='; } }()); tag = 'COMPARE'; break; case '===': case '!==': val += '='; // fallthrough case '<': case '>': case '<=': case '>=': case '<==': case '>==': case '>>=': case '<<=': tag = 'COMPARE'; break; case '.<<.': case '.>>.': case '.>>>.': case '<?': case '>?': tag = 'SHIFT'; break; case '(': if (!(((ref$ = this.last[0]) === 'FUNCTION' || ref$ === 'GENERATOR' || ref$ === 'LET') || this.able(true) || this.last[1] === '.@')) { this.token('(', '('); this.closes.push(')'); this.parens.push(this.last); return 1; } tag = 'CALL('; this.closes.push(')CALL'); break; case '[': case '{': this.adi(); this.closes.push(']}'.charAt(val === '{')); break; case '}': if (this.inter && val !== (ref$ = this.closes)[ref$.length - 1]) { this.rest = code.slice(index + 1); return 9e9; } // fallthrough case ']': case ')': if (tag === ')' && ((ref$ = this.last[0]) === '+-' || ref$ === 'COMPARE' || ref$ === 'LOGIC' || ref$ === 'MATH' || ref$ === 'POWER' || ref$ === 'SHIFT' || ref$ === 'BITWISE' || ref$ === 'CONCAT' || ref$ === 'COMPOSE' || ref$ === 'RELATION' || ref$ === 'PIPE' || ref$ === 'BACKPIPE' || ref$ === 'IMPORT' || ref$ === 'CLONEPORT' || ref$ === 'ASSIGN')) { (ref$ = this.tokens)[ref$.length - 1][0] = (function(){ switch (this.last[0]) { case 'RELATION': return 'BIOPR'; case 'PIPE': this.parameters(false, -1); return 'BIOPP'; default: return 'BIOP'; } }.call(this)); } if (')' === (tag = val = this.pair(val))) { this.lpar = this.parens.pop(); } break; case '=': case ':': if (val === ':') { switch (this.last[0]) { case 'ID': case 'STRNUM': case ')': break; case '...': this.last[0] = 'STRNUM'; break; default: tag = 'LABEL'; val = ''; } this.token(tag, val); return sym.length; } // fallthrough case ':=': case '+=': case '-=': case '*=': case '/=': case '%=': case '%%=': case '<?=': case '>?=': case '**=': case '^=': case '.&.=': case '.|.=': case '.^.=': case '.<<.=': case '.>>.=': case '.>>>.=': case '++=': case '|>=': if (this.last[1] === '.' || this.last[0] === '?' && this.adi()) { this.last[1] += val; return val.length; } if (this.last[0] === 'LOGIC') { (val = Object(val)).logic = this.tokens.pop()[1]; } else if ((val === '+=' || val === '-=') && !able(this.tokens) && ((ref$ = this.last[0]) !== '+-' && ref$ !== 'UNARY' && ref$ !== 'LABEL')) { this.token('UNARY', val.charAt()); val = '='; } tag = 'ASSIGN'; break; case '::=': this.token('DOT', '.'); this.token('ID', 'prototype'); this.token('IMPORT', '<<'); return sym.length; case '*': if (this.last[0] === 'FUNCTION') { this.last[0] = 'GENERATOR'; return sym.length; } if (that = ((ref$ = this.last[0]) === 'NEWLINE' || ref$ === 'INDENT' || ref$ === 'THEN' || ref$ === '=>') && (INLINEDENT.lastIndex = index + 1, INLINEDENT).exec(code)[0].length) { this.tokens.push(['LITERAL', 'void', this.line, this.column], ['ASSIGN', '=', this.line, this.column]); this.indent(index + that - 1 - this.dent - code.lastIndexOf('\n', index - 1)); return that; } tag = able(this.tokens) || this.last[0] === 'CREMENT' && able(this.tokens, this.tokens.length - 1) || this.last[0] === '(' ? 'MATH' : 'STRNUM'; break; case '@': this.adi(); if (this.last[0] === 'DOT' && this.last[1] === '.' && (ref$ = this.tokens)[ref$.length - 2][0] === 'ID' && (ref$ = this.tokens)[ref$.length - 2][1] === 'constructor') { this.tokens.pop(); this.tokens.pop(); this.token('LITERAL', 'this', true); this.adi(); this.token('ID', 'constructor', true); } else { this.token('LITERAL', 'this', true); } return 1; case '@@': this.adi(); this.token('ID', 'constructor', true); return 2; case '&': this.token('LITERAL', 'arguments'); return 1; case '!': switch (false) { default: if (!this.last.spaced) { if (this.last[1] === 'require') { this.last[0] = 'REQUIRE'; this.last[1] = 'require!'; } else if (able(this.tokens, null, true)) { this.token('CALL(', '!'); this.token(')CALL', ')'); } else if (this.last[1] === 'typeof') { this.last[1] = 'classof'; } else if (this.last[1] === 'delete') { this.last[1] = 'jsdelete'; } else { break; } return 1; } } tag = 'UNARY'; break; case '|': tag = 'BITWISE'; break; case '~': if (this.dotcat(val)) { return 1; } tag = 'UNARY'; break; case '::': this.adi(); val = 'prototype'; tag = 'ID'; break; case '=>': this.unline(); this.fset('for', false); tag = 'THEN'; break; default: if (/^!?(?:--?|~~?)>>?\*?$/.test(val)) { this.parameters(tag = '->'); } else if (/^\*?<(?:--?|~~?)!?$/.test(val)) { this.parameters(tag = '<-'); } else { switch (val.charAt(0)) { case '(': this.token('CALL(', '('); tag = ')CALL'; val = ')'; break; case '<': if (val.length < 4) { this.carp('unterminated words'); } this.token('WORDS', val.slice(2, -2), this.adi()); return this.countLines(val).length; } } } if ((tag === '+-' || tag === 'COMPARE' || tag === 'LOGIC' || tag === 'MATH' || tag === 'POWER' || tag === 'SHIFT' || tag === 'BITWISE' || tag === 'CONCAT' || tag === 'RELATION' || tag === 'PIPE' || tag === 'BACKPIPE' || tag === 'COMPOSE' || tag === 'IMPORT') && this.last[0] === '(') { tag = tag === 'BACKPIPE' ? 'BIOPBP' : 'BIOP'; } if (tag === ',' || tag === 'CASE' || tag === 'PIPE' || tag === 'BACKPIPE' || tag === 'COMPOSE' || tag === 'DOT' || tag === 'LOGIC' || tag === 'COMPARE' || tag === 'MATH' || tag === 'POWER' || tag === 'IMPORT' || tag === 'SHIFT' || tag === 'BITWISE') { this.unline(); } this.token(tag, val); return sym.length; }; exports.token = function(tag, value, callable){ this.tokens.push(this.last = [tag, value, this.line, this.column]); if (callable) { this.last.callable = true; } return value; }; exports.indent = function(delta){ this.dent += delta; this.dents.push(this.token('INDENT', delta)); this.closes.push('DEDENT'); }; exports.dedent = function(debt){ var dent; this.dent -= debt; while (debt > 0 && (dent = this.dents.pop())) { if (debt < dent && !this.inter) { this.carp("unmatched dedent (" + debt + " for " + dent + ")"); } this.pair('DEDENT'); debt -= typeof dent === 'number' ? this.token('DEDENT', dent) : dent; } }; exports.newline = function(){ var ref$; if (!(this.last[0] === 'NEWLINE' && this.last[1] === '\n')) { this.tokens.push(this.last = (ref$ = ['NEWLINE', '\n', this.line, this.column], ref$.spaced = true, ref$)); } }; exports.unline = function(){ var ref$; if (!this.tokens[1]) { return; } switch (this.last[0]) { case 'INDENT': (ref$ = this.dents)[ref$.length - 1] += ''; // fallthrough case 'NEWLINE': this.tokens.length--; } }; exports.parameters = function(arrow, offset){ var i$, ref$, i, t, ref1$; if (this.last[0] === ')' && ')' === this.last[1]) { this.lpar[0] = 'PARAM('; this.last[0] = ')PARAM'; return; } if (arrow === '->') { this.token('PARAM(', ''); } else { for (i$ = (ref$ = this.tokens).length - 1; i$ >= 0; --i$) { i = i$; t = ref$[i$]; if ((ref1$ = t[0]) === 'NEWLINE' || ref1$ === 'INDENT' || ref1$ === 'THEN' || ref1$ === '=>' || ref1$ === '(') { break; } } this.tokens.splice(i + 1, 0, ['PARAM(', '', t[2], t[3]]); } if (offset) { this.tokens.splice(this.tokens.length + offset, 0, [')PARAM', '', t[2], t[3]]); } else { this.token(')PARAM', ''); } }; exports.interpolate = function(str, idx, end){ var parts, end0, pos, i, ref$, oldLine, oldColumn, ch, c1, id, stringified, length, tag, e, delta, nested, clone, ref1$; parts = []; end0 = end.charAt(0); pos = 0; i = -1; str = str.slice(idx + end.length); ref$ = [this.line, this.column], oldLine = ref$[0], oldColumn = ref$[1]; this.countLines(end); while (ch = str.charAt(++i)) { switch (ch) { case end0: if (end !== str.slice(i, i + end.length)) { continue; } parts.push(['S', this.countLines(str.slice(0, i)), oldLine, oldColumn]); this.countLines(end); return parts.size = pos + i + end.length * 2, parts; case '#': c1 = str.charAt(i + 1); id = c1 === '@' && c1 || (ID.lastIndex = i + 1, ID).exec(str)[1]; if (!(id || c1 === '{')) { continue; } break; case '\\': ++i; // fallthrough default: continue; } if (i || nested && !stringified) { stringified = parts.push(['S', this.countLines(str.slice(0, i)), oldLine, oldColumn]); ref$ = [this.line, this.column], oldLine = ref$[0], oldColumn = ref$[1]; } if (id) { length = id.length; if (id === '@') { id = 'this'; } if (id === 'this') { tag = 'LITERAL'; } else { id = camelize(id); try { Function("'use strict'; var " + id); } catch (e$) { e = e$; this.carp("invalid variable interpolation '" + id + "'"); } tag = 'ID'; } str = str.slice(delta = i + 1 + length); parts.push(['TOKENS', nested = [[tag, id, this.line, this.column]]]); } else { clone = (ref$ = clone$(exports), ref$.inter = true, ref$.emender = this.emender, ref$); nested = clone.tokenize(str.slice(i + 2), { line: this.line, column: this.column + 2, raw: true }); delta = str.length - clone.rest.length; this.countLines(str.slice(i, delta)); str = clone.rest; while (((ref$ = nested[0]) != null ? ref$[0] : void 8) === 'NEWLINE') { nested.shift(); } if (nested.length) { nested.unshift(['(', '(', oldLine, oldColumn]); nested.push([')', ')', this.line, this.column - 1]); parts.push(['TOKENS', nested]); } ref1$ = [this.line, this.column], oldLine = ref1$[0], oldColumn = ref1$[1]; } pos += delta; i = -1; } this.carp("missing `" + end + "`"); }; exports.addInterpolated = function(parts, nlines){ var tokens, last, ref$, left, right, joint, callable, i$, len$, i, t; if (!parts[1]) { return this.strnum(nlines(this.string('"', parts[0][1]))); } tokens = this.tokens, last = this.last; ref$ = !last.spaced && last[1] === '%' ? (--tokens.length, this.last = last = tokens[tokens.length - 1], ['[', ']', [',', ',']]) : ['(', ')', ['+-', '+']], left = ref$[0], right = ref$[1], joint = ref$[2]; callable = this.adi(); tokens.push([left, '"', last[2], last[3]]); for (i$ = 0, len$ = parts.length; i$ < len$; ++i$) { i = i$; t = parts[i$]; if (t[0] === 'TOKENS') { tokens.push.apply(tokens, t[1]); } else { if (i > 1 && !t[1]) { continue; } tokens.push(['STRNUM', nlines(this.string('"', t[1])), t[2], t[3]]); } tokens.push(joint.concat(tokens[tokens.length - 1][2], tokens[tokens.length - 1][3])); } --tokens.length; this.token(right, '', callable); }; exports.strnum = function(it){ this.token('STRNUM', it, this.adi() || this.last[0] === 'DOT'); }; exports.regex = function(body, flag){ var e; try { RegExp(body); } catch (e$) { e = e$; this.carp(e.message); } if (flag === '$') { return this.strnum(this.string('\'', enslash(body))); } return this.token('LITERAL', "/" + (body || '(?:)') + "/" + this.validate(flag)); }; exports.adi = function(){ if (this.last.spaced) { return; } if (!able(this.tokens)) { return; } return this.token('DOT', '.'); }; exports.dotcat = function(it){ if (this.last[1] === '.' || this.adi()) { return this.last[1] += it; } }; exports.pair = function(it){ var wanted, ref$; if (!(it === (wanted = (ref$ = this.closes)[ref$.length - 1]) || ')CALL' === wanted && it === ')')) { if ('DEDENT' !== wanted) { this.carp("unmatched `" + it + "`"); } this.dedent((ref$ = this.dents)[ref$.length - 1]); return this.pair(it); } this.unline(); this.fclear(); return this.closes.pop(); }; exports.able = function(call){ return !this.last.spaced && able(this.tokens, null, call); }; exports.countLines = function(it){ var pos; if (!this.isAtPrefix) { this.column += it.length; } while (pos = 1 + it.indexOf('\n', pos)) { if (!this.isAtPrefix) { this.column = 0; } this.column += it.length - pos; ++this.line; this.isAtPrefix = false; } this.charsCounted += it.length; return it; }; exports.forange = function(){ var ref$, ref1$, ref2$; if (((ref$ = (ref1$ = this.tokens)[ref1$.length - 2 - ((ref2$ = this.last[0]) === 'NEWLINE' || ref2$ === 'INDENT')]) != null ? ref$[0] : void 8) === 'FOR' || this.last[0] === 'FOR') { this.fset('for', false); this.fset('from', true); return true; } else { return false; } }; exports.validate = function(flag){ var that; if (that = flag && /(.).*\1/.exec(flag)) { this.carp("duplicate regex flag `" + that[1] + "`"); } return flag; }; exports.fget = function(key){ var ref$; return (ref$ = this.flags[this.closes.length]) != null ? ref$[key] : void 8; }; exports.fset = function(key, val){ var ref$, key$; ((ref$ = this.flags)[key$ = this.closes.length] || (ref$[key$] = {}))[key] = val; }; exports.fclear = function(){ this.flags.splice(this.closes.length); }; exports.carp = function(it){ carp(it, this.line); }; exports.string = function(q, body){ return string(q, body, this.line); }; function carp(msg, lno){ throw SyntaxError(msg + " on line " + (-~lno)); } function able(tokens, i, call){ var token, tag; i == null && (i = tokens.length); tag = (token = tokens[i - 1])[0]; return (tag === 'ID' || tag === ']' || tag === '?') || (call ? token.callable || (tag === ')' || tag === ')CALL' || tag === 'BIOPBP') && token[1] : tag === '}' || tag === ')' || tag === ')CALL' || tag === 'STRNUM' || tag === 'LITERAL' || tag === 'WORDS'); } string = (function(re){ return function(q, body, lno){ body = body.replace(re, function(it, oct, xu, rest){ if (it === q || it === '\\') { return '\\' + it; } if (oct) { return '\\x' + (0x100 + parseInt(oct, 8)).toString(16).slice(1); } if (xu) { carp('malformed character escape sequence', lno); } if (!rest || q === rest) { return it; } else { return rest; } }); return q + body + q; }; }.call(this, /['"]|\\(?:([0-3]?[0-7]{2}|[1-7]|0(?=[89]))|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|([xu])|[\\0bfnrtv]|[^\n\S]|([\w\W]))?/g)); function heretabs(doc){ var dent, that, ref$; dent = 0 / 0; while (that = TABS.exec(doc)) { dent <= (ref$ = that[0].length - 1) || (dent = ref$); } return dent; } TABS = /\n(?!$)[^\n\S]*/mg; function detab(str, len){ if (len) { return str.replace(detab[len] || (detab[len] = RegExp('\\n[^\\n\\S]{1,' + len + '}', 'g')), '\n'); } else { return str; } } unlines = function(it){ return it.replace(/\n[^\n\S]*/g, ''); }; enlines = function(it){ return it.replace(/\n/g, '\\n'); }; enslash = function(it){ return it.replace(/\\/g, '\\\\'); }; reslash = function(it){ return it.replace(/(\\.)|\//g, function(){ return arguments[1] || '\\/'; }); }; camelize = function(it){ return it.replace(/-[a-z]/ig, function(it){ return it.charAt(1).toUpperCase(); }); }; deheregex = function(it){ return it.replace(/\s+(?:#.*)?|(\\[\s\S])/g, function(arg$, bs){ bs || (bs = ''); if ('\n' === bs.charAt(1)) { return '\\n'; } else { return bs; } }); }; function lchomp(it){ return it.slice(1 + it.lastIndexOf('\n', 0)); } function decode(val, lno){ if (!isNaN(val)) { return [+val]; } val = val.length > 8 ? 'ng' : Function('return ' + val)(); val.length === 1 || carp('bad string in range', lno); return [val.charCodeAt(), true]; } function uxxxx(it){ return '"\\u' + ('000' + it.toString(16)).slice(-4) + '"'; } character = typeof JSON == 'undefined' || JSON === null ? uxxxx : function(it){ switch (it) { case 0x2028: case 0x2029: return uxxxx(it); default: return JSON.stringify(String.fromCharCode(it)); } }; function firstPass(tokens){ var prev, i, token, tag, val, line, column, next, parens, i$, j, ts, ref$; prev = ['NEWLINE', '\n', 0]; i = 0; while (token = tokens[++i]) { tag = token[0], val = token[1], line = token[2], column = token[3]; switch (tag) { case 'ASSIGN': if (in$(prev[1], LS_KEYWORDS) && tokens[i - 2][0] !== 'DOT') { carp("cannot assign to reserved word '" + prev[1] + "'", line); } break; case 'DOT': switch (false) { case !(prev[0] === ']' && tokens[i - 2][0] === '[' && tokens[i - 3][0] === 'DOT'): tokens.splice(i - 2, 3); tokens[i - 3][1] = '[]'; i -= 3; break; case !(prev[0] === '}' && tokens[i - 2][0] === '{' && tokens[i - 3][0] === 'DOT'): tokens.splice(i - 2, 3); tokens[i - 3][1] = '{}'; i -= 3; break; case !(val === '.' && token.spaced && prev.spaced): tokens[i] = ['COMPOSE', '<<', line, column]; break; default: next = tokens[i + 1]; if (prev[0] === '(' && next[0] === ')') { tokens[i][0] = 'BIOP'; } else if (prev[0] === '(') { tokens.splice(i, 0, ['PARAM(', '(', line, column], [')PARAM', ')', line, column], ['->', '~>', line, column], ['ID', 'it', line, column]); } else if (next[0] === ')') { tokens.splice(i + 1, 0, ['[', '[', line, column], ['ID', 'it', line, column], [']', ']', line, column]); parens = 1; LOOP: for (i$ = i + 1; i$ >= 0; --i$) { j = i$; switch (tokens[j][0]) { case ')': ++parens; break; case '(': if (--parens === 0) { tokens.splice(j + 1, 0, ['PARAM(', '(', line, column], ['ID', 'it', line, column], [')PARAM', ')', line, column], ['->', '~>', line, column]); break LOOP; } } } } } break; case 'CREMENT': if (!(val === '++' && (next = tokens[i + 1]))) { break; } ts = ['ID', 'LITERAL', 'STRNUM']; if (prev.spaced && token.spaced || !(prev.spaced || token.spaced) && in$(prev[0], ts) && in$(next[0], ts)) { tokens[i][0] = 'CONCAT'; } if (prev[0] === '(' && next[0] === ')' || prev[0] === '(' && token.spaced || next[0] === ')' && prev.spaced) { tokens[i][0] = 'BIOP'; } break; case 'ID': if (val !== 'async') { break; } next = tokens[i + 1]; if ((ref$ = next[0]) === 'FUNCTION' || ref$ === 'GENERATOR') { token[0] = 'ASYNC'; } } prev = token; continue; } } function rewriteBlockless(tokens){ var i, token, tag; i = -1; while (token = tokens[++i]) { tag = token[0]; if (tag === 'IF' || tag === 'CLASS' || tag === 'CATCH') { detectEnd(tokens, i + 1, ok, go); } } function ok(it){ var ref$; return (ref$ = it[0]) === 'NEWLINE' || ref$ === 'INDENT'; } function go(it, i){ var lno, cno; if (tag === 'IF') { if (it[0] !== 'INDENT' || !it[1] && !it.then || in$(tokens[i - 1][0], BLOCK_USERS)) { token[0] = 'POST_IF'; } } else if (it[0] !== 'INDENT') { tokens.splice(i, 0, ['INDENT', 0, lno = tokens[i - 1][2], cno = tokens[i - 1][3]], ['DEDENT', 0, lno, cno]); } } } function addImplicitIndentation(tokens){ var i, token, tag, next, indent, dedent, ref$, ref1$, idx; i = 0; while (token = tokens[++i]) { tag = token[0]; if (tag !== '->' && tag !== 'THEN' && tag !== 'ELSE' && tag !== 'DEFAULT' && tag !== 'TRY' && tag !== 'FINALLY' && tag !== 'DECL') { continue; } switch (next = tokens[i + 1][0]) { case 'IF': if (tag === 'ELSE') { continue; } break; case 'INDENT': case 'THEN': if (tag === 'THEN') { tokens.splice(i--, 1); } continue; } indent = ['INDENT', 0, token[2], token[3]]; dedent = ['DEDENT', 0]; if (tag === 'THEN') { (tokens[i] = indent).then = true; } else { tokens.splice(++i, 0, indent); } switch (false) { case tag !== 'DECL': break; case next !== 'DOT' && next !== '?' && next !== ',' && next !== 'PIPE' && next !== 'BACKPIPE': --i; // fallthrough case !((next === 'ID' || next === 'STRNUM' || next === 'LITERAL') && ',' === ((ref$ = tokens[i + 2]) != null ? ref$[0] : void 8)): go(0, i += 2); ++i; continue; case !((next === '(' || next === '[' || next === '{') && ',' === ((ref1$ = tokens[idx = 1 + indexOfPair(tokens, i + 1)]) != null ? ref1$[0] : void 8)): go(0, idx); ++i; continue; } detectEnd(tokens, i + 1, ok, go); } function ok(token, i){ var t0, t; t0 = token[0]; t = tag; if (tag === t0 || tag === 'THEN' && t0 === 'SWITCH') { tag = ''; } switch (t0) { case 'NEWLINE': return token[1] !== ';'; case 'DOT': case '?': case ',': case 'PIPE': case 'BACKPIPE': return tokens[i - 1].eol; case 'ELSE': return t === 'THEN'; case 'CATCH': return t === 'TRY'; case 'FINALLY': return t === 'TRY' || t === 'CATCH' || t === 'THEN'; case 'CASE': case 'DEFAULT': return t === 'CASE' || t === 'THEN'; } } function go(arg$, i){ var prev; prev = tokens[i - 1]; tokens.splice(prev[0] === ',' ? i - 1 : i, 0, (dedent[2] = prev[2], dedent[3] = prev[3], dedent)); } } function addImplicitParentheses(tokens){ var i, brackets, token, endi, ref$, tpair, tag, prev, ref1$, skipBlock, seenSwitch; i = 0; brackets = []; while (token = tokens[++i]) { if (token[1] === 'do' && tokens[i + 1][0] === 'INDENT') { endi = indexOfPair(tokens, i + 1); if (tokens[endi + 1][0] === 'NEWLINE' && ((ref$ = tokens[endi + 2]) != null ? ref$[0] : void 8) === 'WHILE') { token[0] = 'DO'; tokens[endi + 2].done = true; tokens.splice(endi + 1, 1); } else { (token = tokens[1 + i])[0] = '('; (tpair = tokens[endi])[0] = ')'; token.doblock = true; tokens.splice(i, 1); } } tag = token[0]; prev = tokens[i - 1]; tag === '[' && brackets.push(prev[0] === 'DOT'); if (prev[0] === ']') { if (brackets.pop()) { prev.index = true; } else { continue; } } if (!(((ref1$ = prev[0]) === 'FUNCTION' || ref1$ === 'GENERATOR' || ref1$ === 'LET' || ref1$ === 'WHERE') || prev.spaced && able(tokens, i, true))) { continue; } if (token.doblock) { token[0] = 'CALL('; tpair[0] = ')CALL'; continue; } if (!exp(token)) { continue; } if (tag === 'CREMENT') { if (token.spaced || !in$((ref1$ = tokens[i + 1]) != null ? ref1$[0] : void 8, CHAIN)) { continue; } } skipBlock = seenSwitch = false; tokens.splice(i++, 0, ['CALL(', '', token[2], token[3]]); detectEnd(tokens, i, ok, go); } function exp(token){ var tag; tag = token[0]; return in$(tag, ARG) || !token.spaced && (tag === '+-' || tag === 'CLONE'); } function ok(token, i){ var tag, ref$, pre; tag = token[0]; if (tag === 'POST_IF' || tag === 'PIPE' || tag === 'BACKPIPE') { return true; } if (!skipBlock) { if (token.alias && ((ref$ = token[1]) === '&&' || ref$ === '||' || ref$ === 'xor') || (tag === 'TO' || tag === 'BY' || tag === 'IMPLEMENTS')) { return true; } } pre = tokens[i - 1]; switch (tag) { case 'NEWLINE': return pre[0] !== ','; case 'DOT': case '?': return !skipBlock && (pre.spaced || pre[0] === 'DEDENT'); case 'SWITCH': seenSwitch = true; // fallthrough case 'IF': case 'CLASS': case 'FUNCTION': case 'GENERATOR': case 'LET': case 'WITH': case 'CATCH': skipBlock = true; break; case 'CASE': if (seenSwitch) { skipBlock = true; } else { return true; } break; case 'INDENT': if (skipBlock) { return skipBlock = false; } return !in$(pre[0], BLOCK_USERS); case 'WHILE': if (token.done) { return false; } // fallthrough case 'FOR': skipBlock = true; return able(tokens, i) || pre[0] === 'CREMENT' || pre[0] === '...' && pre.spaced; } return false; } function go(token, i){ tokens.splice(i, 0, [')CALL', '', tokens[i - 1][2], tokens[i - 1][3]]); } } function addImplicitBraces(tokens){ var stack, i, token, tag, start, paren, index, pre, ref$, inline, ref1$; stack = []; i = 0; while (token = tokens[++i]) { if (':' !== (tag = token[0])) { switch (false) { case !in$(tag, CLOSERS): start = stack.pop(); break; case !in$(tag, OPENERS): if (tag === 'INDENT' && tokens[i - 1][0] === '{') { tag = '{'; } stack.push([tag, i]); } continue; } paren = tokens[i - 1][0] === ')'; index = paren ? start[1] : i - 1; pre = tokens[index - 1]; if (!(((ref$ = pre[0]) === ':' || ref$ === 'ASSIGN' || ref$ === 'IMPORT') || ((ref$ = stack[stack.length - 1]) != null ? ref$[0] : void 8) !== '{')) { continue; } stack.push(['{']); inline = !pre.doblock && ((ref1$ = pre[0]) !== 'NEWLINE' && ref1$ !== 'INDENT'); while (((ref1$ = tokens[index - 2]) != null ? ref1$[0] : void 8) === 'COMMENT') { index -= 2; } tokens.splice(index, 0, ['{', '{', tokens[index][2], tokens[index][3]]); detectEnd(tokens, ++i + 1, ok, go); } function ok(token, i){ var tag, t1, ref$, ref1$; switch (tag = token[0]) { case ',': break; case 'NEWLINE': if (inline) { return true; } break; case 'DEDENT': return true; case 'POST_IF': case 'FOR': case 'WHILE': return inline; default: return false; } t1 = (ref$ = tokens[i + 1]) != null ? ref$[0] : void 8; return t1 !== (tag === ',' ? 'NEWLINE' : 'COMMENT') && ':' !== ((ref1$ = tokens[t1 === '(' ? 1 + indexOfPair(tokens, i + 1) : i + 2]) != null ? ref1$[0] : void 8); } function go(token, i){ tokens.splice(i, 0, ['}', '', token[2], token[3]]); } } function expandLiterals(tokens){ var i, fromNum, token, sig, ref$, ref1$, lno, cno, ref2$, ref3$, ref4$, char, toNum, tochar, byNum, byp, ref5$, ts, enc, add, i$, n, ref6$, ref7$, len$, word, that; i = 0; while (token = tokens[++i]) { switch (token[0]) { case 'STRNUM': if (~'-+'.indexOf(sig = token[1].charAt(0))) { token[1] = token[1].slice(1); tokens.splice(i++, 0, ['+-', sig, token[2], token[3]]); } if (token.callable) { continue; } break; case 'TO': case 'TIL': if (!(tokens[i - 1][0] === '[' && ((tokens[i + 2][0] === ']' && (((ref$ = tokens[i + 1][1].charAt(0)) === '\'' || ref$ === '"') || +tokens[i + 1][1] >= 0)) || (tokens[i + 2][0] === 'BY' && ((ref$ = tokens[i + 3]) != null ? ref$[0] : void 8) === 'STRNUM' && ((ref1$ = tokens[i + 4]) != null ? ref1$[0] : void 8) === ']')))) { continue; } if (tokens[i + 2][0] === 'BY') { tokens[i + 2][0] = 'RANGE_BY'; } token.op = token[1]; fromNum = 0; // fallthrough case 'RANGE': lno = token[2]; cno = token[3]; if (fromNum != null || (tokens[i - 1][0] === '[' && tokens[i + 1][0] === 'STRNUM' && ((tokens[i + 2][0] === ']' && (((ref2$ = tokens[i + 1][1].charAt(0)) === '\'' || ref2$ === '"') || +tokens[i + 1][1] >= 0)) || (tokens[i + 2][0] === 'RANGE_BY' && ((ref2$ = tokens[i + 3]) != null ? ref2$[0] : void 8) === 'STRNUM' && ((ref3$ = tokens[i + 4]) != null ? ref3$[0] : void 8) === ']')))) { if (fromNum == null) { ref4$ = decode(token[1], lno), fromNum = ref4$[0], char = ref4$[1]; } ref4$ = decode(tokens[i + 1][1], lno), toNum = ref4$[0], tochar = ref4$[1]; if (toNum == null || char ^ tochar) { carp('bad "to" in range', lno); } byNum = 1; if (byp = ((ref4$ = tokens[i + 2]) != null ? ref4$[0] : void 8) === 'RANGE_BY') { if (!(byNum = +((ref5$ = tokens[i + 3]) != null ? ref5$[1] : void 8))) { carp('bad "by" in range', tokens[i + 2][2]); } } else if (fromNum > toNum) { byNum = -1; } ts = []; enc = char ? character : String; add = fn$; if (token.op === 'to') { for (i$ = fromNum; byNum < 0 ? i$ >= toNum : i$ <= toNum; i$ += byNum) { n = i$; add(); } } else { for (i$ = fromNum; byNum < 0 ? i$ > toNum : i$ < toNum; i$ += byNum) { n = i$; add(); } } ts.pop() || carp('empty range', lno); tokens.splice.apply(tokens, [i, 2 + 2 * byp].c