(function (exports) { 'use strict';

function getLocator ( source, options ) {

if ( options === void 0 ) options = {};

var offsetLine = options.offsetLine || 0;
var offsetColumn = options.offsetColumn || 0;

var originalLines = source.split( '\n' );

var start = 0;
var lineRanges = originalLines.map( function ( line, i ) {
        var end = start + line.length + 1;
        var range = { start: start, end: end, line: i };

        start = end;
        return range;
});

var i = 0;

function rangeContains ( range, index ) {
        return range.start <= index && index < range.end;
}

function getLocation ( range, index ) {
        return { line: offsetLine + range.line, column: offsetColumn + index - range.start, character: index };
}

return function locate ( search, startIndex ) {
        if ( typeof search === 'string' ) {
                search = source.indexOf( search, startIndex || 0 );
        }

        var range = lineRanges[i];

        var d = search >= range.end ? 1 : -1;

        while ( range ) {
                if ( rangeContains( range, search ) ) return getLocation( range, search );

                i += d;
                range = lineRanges[i];
        }
};

}

function locate ( source, search, options ) {

if ( typeof options === 'number' ) {
        throw new Error( 'locate takes a { startIndex, offsetLine, offsetColumn } object as the third argument' );
}

return getLocator( source, options )( search, options && options.startIndex );

}

// Reserved word lists for various dialects of the language

var reservedWords = {

3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile",
5: "class enum extends super const export import",
6: "enum",
strict: "implements interface let package private protected public static yield",
strictBind: "eval arguments"

};

// And the keywords

var ecma5AndLessKeywords = “break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this”;

var keywords = {

5: ecma5AndLessKeywords,
6: ecma5AndLessKeywords + " const class extends export import super"

};

// ## Character categories

// Big ugly regular expressions that match characters in the // whitespace, identifier, and identifier-start categories. These // are only applied when a character is found to actually have a // code point above 128. // Generated by `bin/generate-identifier-regex.js`.

var nonASCIIidentifierStartChars = “xaaxb5xbaxc0-xd6xd8-xf6xf8-u02c1u02c6-u02d1u02e0-u02e4u02ecu02eeu0370-u0374u0376u0377u037a-u037du037fu0386u0388-u038au038cu038e-u03a1u03a3-u03f5u03f7-u0481u048a-u052fu0531-u0556u0559u0561-u0587u05d0-u05eau05f0-u05f2u0620-u064au066eu066fu0671-u06d3u06d5u06e5u06e6u06eeu06efu06fa-u06fcu06ffu0710u0712-u072fu074d-u07a5u07b1u07ca-u07eau07f4u07f5u07fau0800-u0815u081au0824u0828u0840-u0858u08a0-u08b4u08b6-u08bdu0904-u0939u093du0950u0958-u0961u0971-u0980u0985-u098cu098fu0990u0993-u09a8u09aa-u09b0u09b2u09b6-u09b9u09bdu09ceu09dcu09ddu09df-u09e1u09f0u09f1u0a05-u0a0au0a0fu0a10u0a13-u0a28u0a2a-u0a30u0a32u0a33u0a35u0a36u0a38u0a39u0a59-u0a5cu0a5eu0a72-u0a74u0a85-u0a8du0a8f-u0a91u0a93-u0aa8u0aaa-u0ab0u0ab2u0ab3u0ab5-u0ab9u0abdu0ad0u0ae0u0ae1u0af9u0b05-u0b0cu0b0fu0b10u0b13-u0b28u0b2a-u0b30u0b32u0b33u0b35-u0b39u0b3du0b5cu0b5du0b5f-u0b61u0b71u0b83u0b85-u0b8au0b8e-u0b90u0b92-u0b95u0b99u0b9au0b9cu0b9eu0b9fu0ba3u0ba4u0ba8-u0baau0bae-u0bb9u0bd0u0c05-u0c0cu0c0e-u0c10u0c12-u0c28u0c2a-u0c39u0c3du0c58-u0c5au0c60u0c61u0c80u0c85-u0c8cu0c8e-u0c90u0c92-u0ca8u0caa-u0cb3u0cb5-u0cb9u0cbdu0cdeu0ce0u0ce1u0cf1u0cf2u0d05-u0d0cu0d0e-u0d10u0d12-u0d3au0d3du0d4eu0d54-u0d56u0d5f-u0d61u0d7a-u0d7fu0d85-u0d96u0d9a-u0db1u0db3-u0dbbu0dbdu0dc0-u0dc6u0e01-u0e30u0e32u0e33u0e40-u0e46u0e81u0e82u0e84u0e87u0e88u0e8au0e8du0e94-u0e97u0e99-u0e9fu0ea1-u0ea3u0ea5u0ea7u0eaau0eabu0ead-u0eb0u0eb2u0eb3u0ebdu0ec0-u0ec4u0ec6u0edc-u0edfu0f00u0f40-u0f47u0f49-u0f6cu0f88-u0f8cu1000-u102au103fu1050-u1055u105a-u105du1061u1065u1066u106e-u1070u1075-u1081u108eu10a0-u10c5u10c7u10cdu10d0-u10fau10fc-u1248u124a-u124du1250-u1256u1258u125a-u125du1260-u1288u128a-u128du1290-u12b0u12b2-u12b5u12b8-u12beu12c0u12c2-u12c5u12c8-u12d6u12d8-u1310u1312-u1315u1318-u135au1380-u138fu13a0-u13f5u13f8-u13fdu1401-u166cu166f-u167fu1681-u169au16a0-u16eau16ee-u16f8u1700-u170cu170e-u1711u1720-u1731u1740-u1751u1760-u176cu176e-u1770u1780-u17b3u17d7u17dcu1820-u1877u1880-u18a8u18aau18b0-u18f5u1900-u191eu1950-u196du1970-u1974u1980-u19abu19b0-u19c9u1a00-u1a16u1a20-u1a54u1aa7u1b05-u1b33u1b45-u1b4bu1b83-u1ba0u1baeu1bafu1bba-u1be5u1c00-u1c23u1c4d-u1c4fu1c5a-u1c7du1c80-u1c88u1ce9-u1cecu1cee-u1cf1u1cf5u1cf6u1d00-u1dbfu1e00-u1f15u1f18-u1f1du1f20-u1f45u1f48-u1f4du1f50-u1f57u1f59u1f5bu1f5du1f5f-u1f7du1f80-u1fb4u1fb6-u1fbcu1fbeu1fc2-u1fc4u1fc6-u1fccu1fd0-u1fd3u1fd6-u1fdbu1fe0-u1fecu1ff2-u1ff4u1ff6-u1ffcu2071u207fu2090-u209cu2102u2107u210a-u2113u2115u2118-u211du2124u2126u2128u212a-u2139u213c-u213fu2145-u2149u214eu2160-u2188u2c00-u2c2eu2c30-u2c5eu2c60-u2ce4u2ceb-u2ceeu2cf2u2cf3u2d00-u2d25u2d27u2d2du2d30-u2d67u2d6fu2d80-u2d96u2da0-u2da6u2da8-u2daeu2db0-u2db6u2db8-u2dbeu2dc0-u2dc6u2dc8-u2dceu2dd0-u2dd6u2dd8-u2ddeu3005-u3007u3021-u3029u3031-u3035u3038-u303cu3041-u3096u309b-u309fu30a1-u30fau30fc-u30ffu3105-u312du3131-u318eu31a0-u31bau31f0-u31ffu3400-u4db5u4e00-u9fd5ua000-ua48cua4d0-ua4fdua500-ua60cua610-ua61fua62aua62bua640-ua66eua67f-ua69dua6a0-ua6efua717-ua71fua722-ua788ua78b-ua7aeua7b0-ua7b7ua7f7-ua801ua803-ua805ua807-ua80aua80c-ua822ua840-ua873ua882-ua8b3ua8f2-ua8f7ua8fbua8fdua90a-ua925ua930-ua946ua960-ua97cua984-ua9b2ua9cfua9e0-ua9e4ua9e6-ua9efua9fa-ua9feuaa00-uaa28uaa40-uaa42uaa44-uaa4buaa60-uaa76uaa7auaa7e-uaaafuaab1uaab5uaab6uaab9-uaabduaac0uaac2uaadb-uaadduaae0-uaaeauaaf2-uaaf4uab01-uab06uab09-uab0euab11-uab16uab20-uab26uab28-uab2euab30-uab5auab5c-uab65uab70-uabe2uac00-ud7a3ud7b0-ud7c6ud7cb-ud7fbuf900-ufa6dufa70-ufad9ufb00-ufb06ufb13-ufb17ufb1dufb1f-ufb28ufb2a-ufb36ufb38-ufb3cufb3eufb40ufb41ufb43ufb44ufb46-ufbb1ufbd3-ufd3dufd50-ufd8fufd92-ufdc7ufdf0-ufdfbufe70-ufe74ufe76-ufefcuff21-uff3auff41-uff5auff66-uffbeuffc2-uffc7uffca-uffcfuffd2-uffd7uffda-uffdc”; var nonASCIIidentifierChars = “u200cu200dxb7u0300-u036fu0387u0483-u0487u0591-u05bdu05bfu05c1u05c2u05c4u05c5u05c7u0610-u061au064b-u0669u0670u06d6-u06dcu06df-u06e4u06e7u06e8u06ea-u06edu06f0-u06f9u0711u0730-u074au07a6-u07b0u07c0-u07c9u07eb-u07f3u0816-u0819u081b-u0823u0825-u0827u0829-u082du0859-u085bu08d4-u08e1u08e3-u0903u093a-u093cu093e-u094fu0951-u0957u0962u0963u0966-u096fu0981-u0983u09bcu09be-u09c4u09c7u09c8u09cb-u09cdu09d7u09e2u09e3u09e6-u09efu0a01-u0a03u0a3cu0a3e-u0a42u0a47u0a48u0a4b-u0a4du0a51u0a66-u0a71u0a75u0a81-u0a83u0abcu0abe-u0ac5u0ac7-u0ac9u0acb-u0acdu0ae2u0ae3u0ae6-u0aefu0b01-u0b03u0b3cu0b3e-u0b44u0b47u0b48u0b4b-u0b4du0b56u0b57u0b62u0b63u0b66-u0b6fu0b82u0bbe-u0bc2u0bc6-u0bc8u0bca-u0bcdu0bd7u0be6-u0befu0c00-u0c03u0c3e-u0c44u0c46-u0c48u0c4a-u0c4du0c55u0c56u0c62u0c63u0c66-u0c6fu0c81-u0c83u0cbcu0cbe-u0cc4u0cc6-u0cc8u0cca-u0ccdu0cd5u0cd6u0ce2u0ce3u0ce6-u0cefu0d01-u0d03u0d3e-u0d44u0d46-u0d48u0d4a-u0d4du0d57u0d62u0d63u0d66-u0d6fu0d82u0d83u0dcau0dcf-u0dd4u0dd6u0dd8-u0ddfu0de6-u0defu0df2u0df3u0e31u0e34-u0e3au0e47-u0e4eu0e50-u0e59u0eb1u0eb4-u0eb9u0ebbu0ebcu0ec8-u0ecdu0ed0-u0ed9u0f18u0f19u0f20-u0f29u0f35u0f37u0f39u0f3eu0f3fu0f71-u0f84u0f86u0f87u0f8d-u0f97u0f99-u0fbcu0fc6u102b-u103eu1040-u1049u1056-u1059u105e-u1060u1062-u1064u1067-u106du1071-u1074u1082-u108du108f-u109du135d-u135fu1369-u1371u1712-u1714u1732-u1734u1752u1753u1772u1773u17b4-u17d3u17ddu17e0-u17e9u180b-u180du1810-u1819u18a9u1920-u192bu1930-u193bu1946-u194fu19d0-u19dau1a17-u1a1bu1a55-u1a5eu1a60-u1a7cu1a7f-u1a89u1a90-u1a99u1ab0-u1abdu1b00-u1b04u1b34-u1b44u1b50-u1b59u1b6b-u1b73u1b80-u1b82u1ba1-u1badu1bb0-u1bb9u1be6-u1bf3u1c24-u1c37u1c40-u1c49u1c50-u1c59u1cd0-u1cd2u1cd4-u1ce8u1cedu1cf2-u1cf4u1cf8u1cf9u1dc0-u1df5u1dfb-u1dffu203fu2040u2054u20d0-u20dcu20e1u20e5-u20f0u2cef-u2cf1u2d7fu2de0-u2dffu302a-u302fu3099u309aua620-ua629ua66fua674-ua67dua69eua69fua6f0ua6f1ua802ua806ua80bua823-ua827ua880ua881ua8b4-ua8c5ua8d0-ua8d9ua8e0-ua8f1ua900-ua909ua926-ua92dua947-ua953ua980-ua983ua9b3-ua9c0ua9d0-ua9d9ua9e5ua9f0-ua9f9uaa29-uaa36uaa43uaa4cuaa4duaa50-uaa59uaa7b-uaa7duaab0uaab2-uaab4uaab7uaab8uaabeuaabfuaac1uaaeb-uaaefuaaf5uaaf6uabe3-uabeauabecuabeduabf0-uabf9ufb1eufe00-ufe0fufe20-ufe2fufe33ufe34ufe4d-ufe4fuff10-uff19uff3f”;

var nonASCIIidentifierStart = new RegExp(“[” + nonASCIIidentifierStartChars + “]”); var nonASCIIidentifier = new RegExp(“[” + nonASCIIidentifierStartChars + nonASCIIidentifierChars + “]”);

nonASCIIidentifierStartChars = nonASCIIidentifierChars = null;

// These are a run-length and offset encoded representation of the // >0xffff code points that are a valid part of identifiers. The // offset starts at 0x10000, and each pair of numbers represents an // offset to the next range, and then a size of the range. They were // generated by bin/generate-identifier-regex.js var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,785,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,25,391,63,32,0,449,56,264,8,2,36,18,0,50,29,881,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,65,0,32,6124,20,754,9486,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,10591,541]; var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,10,2,4,9,83,11,7,0,161,11,6,9,7,3,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,87,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,423,9,838,7,2,7,17,9,57,21,2,13,19882,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239];

// This has a complexity linear to the value of the code. The // assumption is that looking up astral identifier characters is // rare. function isInAstralSet(code, set) {

var pos = 0x10000;
for (var i = 0; i < set.length; i += 2) {
  pos += set[i];
  if (pos > code) return false
  pos += set[i + 1];
  if (pos >= code) return true
}

}

// Test whether a given character code starts an identifier.

function isIdentifierStart(code, astral) {

if (code < 65) return code === 36
if (code < 91) return true
if (code < 97) return code === 95
if (code < 123) return true
if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code))
if (astral === false) return false
return isInAstralSet(code, astralIdentifierStartCodes)

}

// Test whether a given character is part of an identifier.

function isIdentifierChar(code, astral) {

if (code < 48) return code === 36
if (code < 58) return true
if (code < 65) return false
if (code < 91) return true
if (code < 97) return code === 95
if (code < 123) return true
if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code))
if (astral === false) return false
return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes)

}

// ## Token types

// The assignment of fine-grained, information-carrying type objects // allows the tokenizer to store the information it has about a // token in a way that is very cheap for the parser to look up.

// All token type variables start with an underscore, to make them // easy to recognize.

// The `beforeExpr` property is used to disambiguate between regular // expressions and divisions. It is set on all token types that can // be followed by an expression (thus, a slash after them would be a // regular expression). // // The `startsExpr` property is used to check if the token ends a // `yield` expression. It is set on all token types that either can // directly start an expression (like a quotation mark) or can // continue an expression (like the body of a string). // // `isLoop` marks a keyword as starting a loop, which is important // to know when parsing a label, in order to allow or disallow // continue jumps to that label.

var TokenType = function TokenType(label, conf) {

if ( conf === void 0 ) conf = {};

this.label = label;
this.keyword = conf.keyword;
this.beforeExpr = !!conf.beforeExpr;
this.startsExpr = !!conf.startsExpr;
this.isLoop = !!conf.isLoop;
this.isAssign = !!conf.isAssign;
this.prefix = !!conf.prefix;
this.postfix = !!conf.postfix;
this.binop = conf.binop || null;
this.updateContext = null;

};

function binop(name, prec) {

return new TokenType(name, {beforeExpr: true, binop: prec})

} var beforeExpr = {beforeExpr: true}; var startsExpr = {startsExpr: true}; // Map keyword names to token types.

var keywordTypes = {};

// Succinct definitions of keyword token types function kw(name, options) {

if ( options === void 0 ) options = {};

options.keyword = name;
return keywordTypes[name] = new TokenType(name, options)

}

var tt = {

num: new TokenType("num", startsExpr),
regexp: new TokenType("regexp", startsExpr),
string: new TokenType("string", startsExpr),
name: new TokenType("name", startsExpr),
eof: new TokenType("eof"),

// Punctuation token types.
bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}),
bracketR: new TokenType("]"),
braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}),
braceR: new TokenType("}"),
parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}),
parenR: new TokenType(")"),
comma: new TokenType(",", beforeExpr),
semi: new TokenType(";", beforeExpr),
colon: new TokenType(":", beforeExpr),
dot: new TokenType("."),
question: new TokenType("?", beforeExpr),
arrow: new TokenType("=>", beforeExpr),
template: new TokenType("template"),
ellipsis: new TokenType("...", beforeExpr),
backQuote: new TokenType("`", startsExpr),
dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}),

// Operators. These carry several kinds of properties to help the
// parser use them properly (the presence of these properties is
// what categorizes them as operators).
//
// `binop`, when present, specifies that this operator is a binary
// operator, and will refer to its precedence.
//
// `prefix` and `postfix` mark the operator as a prefix or postfix
// unary operator.
//
// `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as
// binary operators with a very low precedence, that should result
// in AssignmentExpression nodes.

eq: new TokenType("=", {beforeExpr: true, isAssign: true}),
assign: new TokenType("_=", {beforeExpr: true, isAssign: true}),
incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}),
prefix: new TokenType("prefix", {beforeExpr: true, prefix: true, startsExpr: true}),
logicalOR: binop("||", 1),
logicalAND: binop("&&", 2),
bitwiseOR: binop("|", 3),
bitwiseXOR: binop("^", 4),
bitwiseAND: binop("&", 5),
equality: binop("==/!=", 6),
relational: binop("</>", 7),
bitShift: binop("<</>>", 8),
plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}),
modulo: binop("%", 10),
star: binop("*", 10),
slash: binop("/", 10),
starstar: new TokenType("**", {beforeExpr: true}),

// Keyword token types.
_break: kw("break"),
_case: kw("case", beforeExpr),
_catch: kw("catch"),
_continue: kw("continue"),
_debugger: kw("debugger"),
_default: kw("default", beforeExpr),
_do: kw("do", {isLoop: true, beforeExpr: true}),
_else: kw("else", beforeExpr),
_finally: kw("finally"),
_for: kw("for", {isLoop: true}),
_function: kw("function", startsExpr),
_if: kw("if"),
_return: kw("return", beforeExpr),
_switch: kw("switch"),
_throw: kw("throw", beforeExpr),
_try: kw("try"),
_var: kw("var"),
_const: kw("const"),
_while: kw("while", {isLoop: true}),
_with: kw("with"),
_new: kw("new", {beforeExpr: true, startsExpr: true}),
_this: kw("this", startsExpr),
_super: kw("super", startsExpr),
_class: kw("class"),
_extends: kw("extends", beforeExpr),
_export: kw("export"),
_import: kw("import"),
_null: kw("null", startsExpr),
_true: kw("true", startsExpr),
_false: kw("false", startsExpr),
_in: kw("in", {beforeExpr: true, binop: 7}),
_instanceof: kw("instanceof", {beforeExpr: true, binop: 7}),
_typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}),
_void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}),
_delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true})

};

// Matches a whole line break (where CRLF is considered a single // line break). Used to count lines.

var lineBreak = /rn?|n|u2028|u2029/; var lineBreakG = new RegExp(lineBreak.source, “g”);

function isNewLine(code) {

return code === 10 || code === 13 || code === 0x2028 || code === 0x2029

}

var nonASCIIwhitespace = /[u1680u180eu2000-u200au202fu205fu3000ufeff]/;

var skipWhiteSpace = /(?:s|//.*|/**?*/)*/g;

function isArray(obj) {

return Object.prototype.toString.call(obj) === "[object Array]"

}

// Checks if an object has a property.

function has(obj, propName) {

return Object.prototype.hasOwnProperty.call(obj, propName)

}

// These are used when `options.locations` is on, for the // `startLoc` and `endLoc` properties.

var Position = function Position(line, col) {

this.line = line;
this.column = col;

};

Position.prototype.offset = function offset (n) {

return new Position(this.line, this.column + n)

};

var SourceLocation = function SourceLocation(p, start, end) {

this.start = start;
this.end = end;
if (p.sourceFile !== null) this.source = p.sourceFile;

};

// The `getLineInfo` function is mostly useful when the // `locations` option is off (for performance reasons) and you // want to find the line/column position for a given character // offset. `input` should be the code string that the offset refers // into.

function getLineInfo(input, offset) {

for (var line = 1, cur = 0;;) {
  lineBreakG.lastIndex = cur;
  var match = lineBreakG.exec(input);
  if (match && match.index < offset) {
    ++line;
    cur = match.index + match[0].length;
  } else {
    return new Position(line, offset - cur)
  }
}

}

// A second optional argument can be given to further configure // the parser process. These options are recognized:

var defaultOptions = {

// `ecmaVersion` indicates the ECMAScript version to parse. Must
// be either 3, 5, 6 (2015), 7 (2016), or 8 (2017). This influences support
// for strict mode, the set of reserved words, and support for
// new syntax features. The default is 7.
ecmaVersion: 7,
// `sourceType` indicates the mode the code should be parsed in.
// Can be either `"script"` or `"module"`. This influences global
// strict mode and parsing of `import` and `export` declarations.
sourceType: "script",
// `onInsertedSemicolon` can be a callback that will be called
// when a semicolon is automatically inserted. It will be passed
// th position of the comma as an offset, and if `locations` is
// enabled, it is given the location as a `{line, column}` object
// as second argument.
onInsertedSemicolon: null,
// `onTrailingComma` is similar to `onInsertedSemicolon`, but for
// trailing commas.
onTrailingComma: null,
// By default, reserved words are only enforced if ecmaVersion >= 5.
// Set `allowReserved` to a boolean value to explicitly turn this on
// an off. When this option has the value "never", reserved words
// and keywords can also not be used as property names.
allowReserved: null,
// When enabled, a return at the top level is not considered an
// error.
allowReturnOutsideFunction: false,
// When enabled, import/export statements are not constrained to
// appearing at the top of the program.
allowImportExportEverywhere: false,
// When enabled, hashbang directive in the beginning of file
// is allowed and treated as a line comment.
allowHashBang: false,
// When `locations` is on, `loc` properties holding objects with
// `start` and `end` properties in `{line, column}` form (with
// line being 1-based and column 0-based) will be attached to the
// nodes.
locations: false,
// A function can be passed as `onToken` option, which will
// cause Acorn to call that function with object in the same
// format as tokens returned from `tokenizer().getToken()`. Note
// that you are not allowed to call the parser from the
// callback—that will corrupt its internal state.
onToken: null,
// A function can be passed as `onComment` option, which will
// cause Acorn to call that function with `(block, text, start,
// end)` parameters whenever a comment is skipped. `block` is a
// boolean indicating whether this is a block (`/* */`) comment,
// `text` is the content of the comment, and `start` and `end` are
// character offsets that denote the start and end of the comment.
// When the `locations` option is on, two more parameters are
// passed, the full `{line, column}` locations of the start and
// end of the comments. Note that you are not allowed to call the
// parser from the callback—that will corrupt its internal state.
onComment: null,
// Nodes have their start and end characters offsets recorded in
// `start` and `end` properties (directly on the node, rather than
// the `loc` object, which holds line/column data. To also add a
// [semi-standardized][range] `range` property holding a `[start,
// end]` array with the same numbers, set the `ranges` option to
// `true`.
//
// [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678
ranges: false,
// It is possible to parse multiple files into a single AST by
// passing the tree produced by parsing the first file as
// `program` option in subsequent parses. This will add the
// toplevel forms of the parsed file to the `Program` (top) node
// of an existing parse tree.
program: null,
// When `locations` is on, you can pass this to record the source
// file in every node's `loc` object.
sourceFile: null,
// This value, if given, is stored in every node, whether
// `locations` is on or off.
directSourceFile: null,
// When enabled, parenthesized expressions are represented by
// (non-standard) ParenthesizedExpression nodes
preserveParens: false,
plugins: {}

};

// Interpret and default an options object

function getOptions(opts) {

var options = {};

for (var opt in defaultOptions)
  options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt];

if (options.ecmaVersion >= 2015)
  options.ecmaVersion -= 2009;

if (options.allowReserved == null)
  options.allowReserved = options.ecmaVersion < 5;

if (isArray(options.onToken)) {
  var tokens = options.onToken;
  options.onToken = function (token) { return tokens.push(token); };
}
if (isArray(options.onComment))
  options.onComment = pushComment(options, options.onComment);

return options

}

function pushComment(options, array) {

return function (block, text, start, end, startLoc, endLoc) {
  var comment = {
    type: block ? 'Block' : 'Line',
    value: text,
    start: start,
    end: end
  };
  if (options.locations)
    comment.loc = new SourceLocation(this, startLoc, endLoc);
  if (options.ranges)
    comment.range = [start, end];
  array.push(comment);
}

}

// Registered plugins var plugins = {};

function keywordRegexp(words) {

return new RegExp("^(" + words.replace(/ /g, "|") + ")$")

}

var Parser = function Parser(options, input, startPos) {

this.options = options = getOptions(options);
this.sourceFile = options.sourceFile;
this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]);
var reserved = "";
if (!options.allowReserved) {
  for (var v = options.ecmaVersion;; v--)
    if (reserved = reservedWords[v]) break
  if (options.sourceType == "module") reserved += " await";
}
this.reservedWords = keywordRegexp(reserved);
var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict;
this.reservedWordsStrict = keywordRegexp(reservedStrict);
this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind);
this.input = String(input);

// Used to signal to callers of `readWord1` whether the word
// contained any escape sequences. This is needed because words with
// escape sequences must not be interpreted as keywords.
this.containsEsc = false;

// Load plugins
this.loadPlugins(options.plugins);

// Set up token state

// The current position of the tokenizer in the input.
if (startPos) {
  this.pos = startPos;
  this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1;
  this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length;
} else {
  this.pos = this.lineStart = 0;
  this.curLine = 1;
}

// Properties of the current token:
// Its type
this.type = tt.eof;
// For tokens that include more information than their type, the value
this.value = null;
// Its start and end offset
this.start = this.end = this.pos;
// And, if locations are used, the {line, column} object
// corresponding to those offsets
this.startLoc = this.endLoc = this.curPosition();

// Position information for the previous token
this.lastTokEndLoc = this.lastTokStartLoc = null;
this.lastTokStart = this.lastTokEnd = this.pos;

// The context stack is used to superficially track syntactic
// context to predict whether a regular expression is allowed in a
// given position.
this.context = this.initialContext();
this.exprAllowed = true;

// Figure out if it's a module code.
this.inModule = options.sourceType === "module";
this.strict = this.inModule || this.strictDirective(this.pos);

// Used to signify the start of a potential arrow function
this.potentialArrowAt = -1;

// Flags to track whether we are in a function, a generator, an async function.
this.inFunction = this.inGenerator = this.inAsync = false;
// Positions to delayed-check that yield/await does not exist in default parameters.
this.yieldPos = this.awaitPos = 0;
// Labels in scope.
this.labels = [];

// If enabled, skip leading hashbang line.
if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!')
  this.skipLineComment(2);

};

// DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them Parser.prototype.isKeyword = function isKeyword (word) { return this.keywords.test(word) }; Parser.prototype.isReservedWord = function isReservedWord (word) { return this.reservedWords.test(word) };

Parser.prototype.extend = function extend (name, f) {

this[name] = f(this[name]);

};

Parser.prototype.loadPlugins = function loadPlugins (pluginConfigs) {

  var this$1 = this;

for (var name in pluginConfigs) {
  var plugin = plugins[name];
  if (!plugin) throw new Error("Plugin '" + name + "' not found")
  plugin(this$1, pluginConfigs[name]);
}

};

Parser.prototype.parse = function parse () {

var node = this.options.program || this.startNode();
this.nextToken();
return this.parseTopLevel(node)

};

var pp = Parser.prototype;

// ## Parser utilities

var literal = /^(?:'((?:[^']|.)*)'|“((?:[^"]|.)*)”|;)/; pp.strictDirective = function(start) {

var this$1 = this;

for (;;) {
  skipWhiteSpace.lastIndex = start;
  start += skipWhiteSpace.exec(this$1.input)[0].length;
  var match = literal.exec(this$1.input.slice(start));
  if (!match) return false
  if ((match[1] || match[2]) == "use strict") return true
  start += match[0].length;
}

};

// Predicate that tests whether the next token is of the given // type, and if yes, consumes it as a side effect.

pp.eat = function(type) {

if (this.type === type) {
  this.next();
  return true
} else {
  return false
}

};

// Tests whether parsed token is a contextual keyword.

pp.isContextual = function(name) {

return this.type === tt.name && this.value === name

};

// Consumes contextual keyword if possible.

pp.eatContextual = function(name) {

return this.value === name && this.eat(tt.name)

};

// Asserts that following token is given contextual keyword.

pp.expectContextual = function(name) {

if (!this.eatContextual(name)) this.unexpected();

};

// Test whether a semicolon can be inserted at the current position.

pp.canInsertSemicolon = function() {

return this.type === tt.eof ||
  this.type === tt.braceR ||
  lineBreak.test(this.input.slice(this.lastTokEnd, this.start))

};

pp.insertSemicolon = function() {

if (this.canInsertSemicolon()) {
  if (this.options.onInsertedSemicolon)
    this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc);
  return true
}

};

// Consume a semicolon, or, failing that, see if we are allowed to // pretend that there is a semicolon at this position.

pp.semicolon = function() {

if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected();

};

pp.afterTrailingComma = function(tokType, notNext) {

if (this.type == tokType) {
  if (this.options.onTrailingComma)
    this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc);
  if (!notNext)
    this.next();
  return true
}

};

// Expect a token of a given type. If found, consume it, otherwise, // raise an unexpected token error.

pp.expect = function(type) {

this.eat(type) || this.unexpected();

};

// Raise an unexpected token error.

pp.unexpected = function(pos) {

this.raise(pos != null ? pos : this.start, "Unexpected token");

};

var DestructuringErrors = function DestructuringErrors() {

this.shorthandAssign = this.trailingComma = this.parenthesizedAssign = this.parenthesizedBind = -1;

};

pp.checkPatternErrors = function(refDestructuringErrors, isAssign) {

if (!refDestructuringErrors) return
if (refDestructuringErrors.trailingComma > -1)
  this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element");
var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind;
if (parens > -1) this.raiseRecoverable(parens, "Parenthesized pattern");

};

pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) {

var pos = refDestructuringErrors ? refDestructuringErrors.shorthandAssign : -1;
if (!andThrow) return pos >= 0
if (pos > -1) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns");

};

pp.checkYieldAwaitInDefaultParams = function() {

if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos))
  this.raise(this.yieldPos, "Yield expression cannot be a default value");
if (this.awaitPos)
  this.raise(this.awaitPos, "Await expression cannot be a default value");

};

pp.isSimpleAssignTarget = function(expr) {

if (expr.type === "ParenthesizedExpression")
  return this.isSimpleAssignTarget(expr.expression)
return expr.type === "Identifier" || expr.type === "MemberExpression"

};

var pp$1 = Parser.prototype;

// ### Statement parsing

// Parse a program. Initializes the parser, reads any number of // statements, and wraps them in a Program node. Optionally takes a // `program` argument. If present, the statements will be appended // to its body instead of creating a new node.

pp$1.parseTopLevel = function(node) {

var this$1 = this;

var exports = {};
if (!node.body) node.body = [];
while (this.type !== tt.eof) {
  var stmt = this$1.parseStatement(true, true, exports);
  node.body.push(stmt);
}
this.next();
if (this.options.ecmaVersion >= 6) {
  node.sourceType = this.options.sourceType;
}
return this.finishNode(node, "Program")

};

var loopLabel = {kind: “loop”}; var switchLabel = {kind: “switch”}; pp$1.isLet = function() {

if (this.type !== tt.name || this.options.ecmaVersion < 6 || this.value != "let") return false
skipWhiteSpace.lastIndex = this.pos;
var skip = skipWhiteSpace.exec(this.input);
var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next);
if (nextCh === 91 || nextCh == 123) return true // '{' and '['
if (isIdentifierStart(nextCh, true)) {
  for (var pos = next + 1; isIdentifierChar(this.input.charCodeAt(pos), true); ++pos) {}
  var ident = this.input.slice(next, pos);
  if (!this.isKeyword(ident)) return true
}
return false

};

// check 'async [no LineTerminator here] function' // - 'async /foo/ function' is OK. // - 'async /n/ function' is invalid. pp$1.isAsyncFunction = function() {

if (this.type !== tt.name || this.options.ecmaVersion < 8 || this.value != "async")
  return false

skipWhiteSpace.lastIndex = this.pos;
var skip = skipWhiteSpace.exec(this.input);
var next = this.pos + skip[0].length;
return !lineBreak.test(this.input.slice(this.pos, next)) &&
  this.input.slice(next, next + 8) === "function" &&
  (next + 8 == this.input.length || !isIdentifierChar(this.input.charAt(next + 8)))

};

// Parse a single statement. // // If expecting a statement and finding a slash operator, parse a // regular expression literal. This is to handle cases like // `if (foo) /blah/.exec(foo)`, where looking at the previous token // does not help.

pp$1.parseStatement = function(declaration, topLevel, exports) {

var starttype = this.type, node = this.startNode(), kind;

if (this.isLet()) {
  starttype = tt._var;
  kind = "let";
}

// Most types of statements are recognized by the keyword they
// start with. Many are trivial to parse, some require a bit of
// complexity.

switch (starttype) {
case tt._break: case tt._continue: return this.parseBreakContinueStatement(node, starttype.keyword)
case tt._debugger: return this.parseDebuggerStatement(node)
case tt._do: return this.parseDoStatement(node)
case tt._for: return this.parseForStatement(node)
case tt._function:
  if (!declaration && this.options.ecmaVersion >= 6) this.unexpected();
  return this.parseFunctionStatement(node, false)
case tt._class:
  if (!declaration) this.unexpected();
  return this.parseClass(node, true)
case tt._if: return this.parseIfStatement(node)
case tt._return: return this.parseReturnStatement(node)
case tt._switch: return this.parseSwitchStatement(node)
case tt._throw: return this.parseThrowStatement(node)
case tt._try: return this.parseTryStatement(node)
case tt._const: case tt._var:
  kind = kind || this.value;
  if (!declaration && kind != "var") this.unexpected();
  return this.parseVarStatement(node, kind)
case tt._while: return this.parseWhileStatement(node)
case tt._with: return this.parseWithStatement(node)
case tt.braceL: return this.parseBlock()
case tt.semi: return this.parseEmptyStatement(node)
case tt._export:
case tt._import:
  if (!this.options.allowImportExportEverywhere) {
    if (!topLevel)
      this.raise(this.start, "'import' and 'export' may only appear at the top level");
    if (!this.inModule)
      this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'");
  }
  return starttype === tt._import ? this.parseImport(node) : this.parseExport(node, exports)

  // If the statement does not start with a statement keyword or a
  // brace, it's an ExpressionStatement or LabeledStatement. We
  // simply start parsing an expression, and afterwards, if the
  // next token is a colon and the expression was a simple
  // Identifier node, we switch to interpreting it as a label.
default:
  if (this.isAsyncFunction() && declaration) {
    this.next();
    return this.parseFunctionStatement(node, true)
  }

  var maybeName = this.value, expr = this.parseExpression();
  if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon))
    return this.parseLabeledStatement(node, maybeName, expr)
  else return this.parseExpressionStatement(node, expr)
}

};

pp$1.parseBreakContinueStatement = function(node, keyword) {

var this$1 = this;

var isBreak = keyword == "break";
this.next();
if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null;
else if (this.type !== tt.name) this.unexpected();
else {
  node.label = this.parseIdent();
  this.semicolon();
}

// Verify that there is an actual destination to break or
// continue to.
for (var i = 0; i < this.labels.length; ++i) {
  var lab = this$1.labels[i];
  if (node.label == null || lab.name === node.label.name) {
    if (lab.kind != null && (isBreak || lab.kind === "loop")) break
    if (node.label && isBreak) break
  }
}
if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword);
return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement")

};

pp$1.parseDebuggerStatement = function(node) {

this.next();
this.semicolon();
return this.finishNode(node, "DebuggerStatement")

};

pp$1.parseDoStatement = function(node) {

this.next();
this.labels.push(loopLabel);
node.body = this.parseStatement(false);
this.labels.pop();
this.expect(tt._while);
node.test = this.parseParenExpression();
if (this.options.ecmaVersion >= 6)
  this.eat(tt.semi);
else
  this.semicolon();
return this.finishNode(node, "DoWhileStatement")

};

// Disambiguating between a `for` and a `for`/`in` or `for`/`of` // loop is non-trivial. Basically, we have to parse the init `var` // statement or expression, disallowing the `in` operator (see // the second parameter to `parseExpression`), and then check // whether the next token is `in` or `of`. When there is no init // part (semicolon immediately after the opening parenthesis), it // is a regular `for` loop.

pp$1.parseForStatement = function(node) {

this.next();
this.labels.push(loopLabel);
this.expect(tt.parenL);
if (this.type === tt.semi) return this.parseFor(node, null)
var isLet = this.isLet();
if (this.type === tt._var || this.type === tt._const || isLet) {
  var init$1 = this.startNode(), kind = isLet ? "let" : this.value;
  this.next();
  this.parseVar(init$1, true, kind);
  this.finishNode(init$1, "VariableDeclaration");
  if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 &&
      !(kind !== "var" && init$1.declarations[0].init))
    return this.parseForIn(node, init$1)
  return this.parseFor(node, init$1)
}
var refDestructuringErrors = new DestructuringErrors;
var init = this.parseExpression(true, refDestructuringErrors);
if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) {
  this.toAssignable(init);
  this.checkLVal(init);
  this.checkPatternErrors(refDestructuringErrors, true);
  return this.parseForIn(node, init)
} else {
  this.checkExpressionErrors(refDestructuringErrors, true);
}
return this.parseFor(node, init)

};

pp$1.parseFunctionStatement = function(node, isAsync) {

this.next();
return this.parseFunction(node, true, false, isAsync)

};

pp$1.isFunction = function() {

return this.type === tt._function || this.isAsyncFunction()

};

pp$1.parseIfStatement = function(node) {

this.next();
node.test = this.parseParenExpression();
// allow function declarations in branches, but only in non-strict mode
node.consequent = this.parseStatement(!this.strict && this.isFunction());
node.alternate = this.eat(tt._else) ? this.parseStatement(!this.strict && this.isFunction()) : null;
return this.finishNode(node, "IfStatement")

};

pp$1.parseReturnStatement = function(node) {

if (!this.inFunction && !this.options.allowReturnOutsideFunction)
  this.raise(this.start, "'return' outside of function");
this.next();

// In `return` (and `break`/`continue`), the keywords with
// optional arguments, we eagerly look for a semicolon or the
// possibility to insert one.

if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null;
else { node.argument = this.parseExpression(); this.semicolon(); }
return this.finishNode(node, "ReturnStatement")

};

pp$1.parseSwitchStatement = function(node) {

var this$1 = this;

this.next();
node.discriminant = this.parseParenExpression();
node.cases = [];
this.expect(tt.braceL);
this.labels.push(switchLabel);

// Statements under must be grouped (by label) in SwitchCase
// nodes. `cur` is used to keep the node that we are currently
// adding statements to.

for (var cur, sawDefault = false; this.type != tt.braceR;) {
  if (this$1.type === tt._case || this$1.type === tt._default) {
    var isCase = this$1.type === tt._case;
    if (cur) this$1.finishNode(cur, "SwitchCase");
    node.cases.push(cur = this$1.startNode());
    cur.consequent = [];
    this$1.next();
    if (isCase) {
      cur.test = this$1.parseExpression();
    } else {
      if (sawDefault) this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses");
      sawDefault = true;
      cur.test = null;
    }
    this$1.expect(tt.colon);
  } else {
    if (!cur) this$1.unexpected();
    cur.consequent.push(this$1.parseStatement(true));
  }
}
if (cur) this.finishNode(cur, "SwitchCase");
this.next(); // Closing brace
this.labels.pop();
return this.finishNode(node, "SwitchStatement")

};

pp$1.parseThrowStatement = function(node) {

this.next();
if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start)))
  this.raise(this.lastTokEnd, "Illegal newline after throw");
node.argument = this.parseExpression();
this.semicolon();
return this.finishNode(node, "ThrowStatement")

};

// Reused empty array added for node fields that are always empty.

var empty = [];

pp$1.parseTryStatement = function(node) {

this.next();
node.block = this.parseBlock();
node.handler = null;
if (this.type === tt._catch) {
  var clause = this.startNode();
  this.next();
  this.expect(tt.parenL);
  clause.param = this.parseBindingAtom();
  this.checkLVal(clause.param, true);
  this.expect(tt.parenR);
  clause.body = this.parseBlock();
  node.handler = this.finishNode(clause, "CatchClause");
}
node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null;
if (!node.handler && !node.finalizer)
  this.raise(node.start, "Missing catch or finally clause");
return this.finishNode(node, "TryStatement")

};

pp$1.parseVarStatement = function(node, kind) {

this.next();
this.parseVar(node, false, kind);
this.semicolon();
return this.finishNode(node, "VariableDeclaration")

};

pp$1.parseWhileStatement = function(node) {

this.next();
node.test = this.parseParenExpression();
this.labels.push(loopLabel);
node.body = this.parseStatement(false);
this.labels.pop();
return this.finishNode(node, "WhileStatement")

};

pp$1.parseWithStatement = function(node) {

if (this.strict) this.raise(this.start, "'with' in strict mode");
this.next();
node.object = this.parseParenExpression();
node.body = this.parseStatement(false);
return this.finishNode(node, "WithStatement")

};

pp$1.parseEmptyStatement = function(node) {

this.next();
return this.finishNode(node, "EmptyStatement")

};

pp$1.parseLabeledStatement = function(node, maybeName, expr) {

var this$1 = this;

for (var i = 0; i < this.labels.length; ++i)
  if (this$1.labels[i].name === maybeName) this$1.raise(expr.start, "Label '" + maybeName + "' is already declared");
var kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null;
for (var i$1 = this.labels.length - 1; i$1 >= 0; i$1--) {
  var label = this$1.labels[i$1];
  if (label.statementStart == node.start) {
    label.statementStart = this$1.start;
    label.kind = kind;
  } else break
}
this.labels.push({name: maybeName, kind: kind, statementStart: this.start});
node.body = this.parseStatement(true);
if (node.body.type == "ClassDeclaration" ||
    node.body.type == "VariableDeclaration" && (this.strict || node.body.kind != "var") ||
    node.body.type == "FunctionDeclaration" && (this.strict || node.body.generator))
  this.raiseRecoverable(node.body.start, "Invalid labeled declaration");
this.labels.pop();
node.label = expr;
return this.finishNode(node, "LabeledStatement")

};

pp$1.parseExpressionStatement = function(node, expr) {

node.expression = expr;
this.semicolon();
return this.finishNode(node, "ExpressionStatement")

};

// Parse a semicolon-enclosed block of statements, handling `“use // strict”` declarations when `allowStrict` is true (used for // function bodies).

pp$1.parseBlock = function() {

var this$1 = this;

var node = this.startNode();
node.body = [];
this.expect(tt.braceL);
while (!this.eat(tt.braceR)) {
  var stmt = this$1.parseStatement(true);
  node.body.push(stmt);
}
return this.finishNode(node, "BlockStatement")

};

// Parse a regular `for` loop. The disambiguation code in // `parseStatement` will already have parsed the init statement or // expression.

pp$1.parseFor = function(node, init) {

node.init = init;
this.expect(tt.semi);
node.test = this.type === tt.semi ? null : this.parseExpression();
this.expect(tt.semi);
node.update = this.type === tt.parenR ? null : this.parseExpression();
this.expect(tt.parenR);
node.body = this.parseStatement(false);
this.labels.pop();
return this.finishNode(node, "ForStatement")

};

// Parse a `for`/`in` and `for`/`of` loop, which are almost // same from parser's perspective.

pp$1.parseForIn = function(node, init) {

var type = this.type === tt._in ? "ForInStatement" : "ForOfStatement";
this.next();
node.left = init;
node.right = this.parseExpression();
this.expect(tt.parenR);
node.body = this.parseStatement(false);
this.labels.pop();
return this.finishNode(node, type)

};

// Parse a list of variable declarations.

pp$1.parseVar = function(node, isFor, kind) {

var this$1 = this;

node.declarations = [];
node.kind = kind;
for (;;) {
  var decl = this$1.startNode();
  this$1.parseVarId(decl);
  if (this$1.eat(tt.eq)) {
    decl.init = this$1.parseMaybeAssign(isFor);
  } else if (kind === "const" && !(this$1.type === tt._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) {
    this$1.unexpected();
  } else if (decl.id.type != "Identifier" && !(isFor && (this$1.type === tt._in || this$1.isContextual("of")))) {
    this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value");
  } else {
    decl.init = null;
  }
  node.declarations.push(this$1.finishNode(decl, "VariableDeclarator"));
  if (!this$1.eat(tt.comma)) break
}
return node

};

pp$1.parseVarId = function(decl) {

decl.id = this.parseBindingAtom();
this.checkLVal(decl.id, true);

};

// Parse a function declaration or literal (depending on the // `isStatement` parameter).

pp$1.parseFunction = function(node, isStatement, allowExpressionBody, isAsync) {

this.initFunction(node);
if (this.options.ecmaVersion >= 6 && !isAsync)
  node.generator = this.eat(tt.star);
if (this.options.ecmaVersion >= 8)
  node.async = !!isAsync;

if (isStatement == null)
  isStatement = this.type == tt.name;
if (isStatement)
  node.id = this.parseIdent();

var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
    oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;
this.inGenerator = node.generator;
this.inAsync = node.async;
this.yieldPos = 0;
this.awaitPos = 0;
this.inFunction = true;

if (!isStatement && this.type === tt.name)
  node.id = this.parseIdent();
this.parseFunctionParams(node);
this.parseFunctionBody(node, allowExpressionBody);

this.inGenerator = oldInGen;
this.inAsync = oldInAsync;
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
this.inFunction = oldInFunc;
return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression")

};

pp$1.parseFunctionParams = function(node) {

this.expect(tt.parenL);
node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8, true);
this.checkYieldAwaitInDefaultParams();

};

// Parse a class declaration or literal (depending on the // `isStatement` parameter).

pp$1.parseClass = function(node, isStatement) {

var this$1 = this;

this.next();
if (isStatement == null) isStatement = this.type === tt.name;
this.parseClassId(node, isStatement);
this.parseClassSuper(node);
var classBody = this.startNode();
var hadConstructor = false;
classBody.body = [];
this.expect(tt.braceL);
while (!this.eat(tt.braceR)) {
  if (this$1.eat(tt.semi)) continue
  var method = this$1.startNode();
  var isGenerator = this$1.eat(tt.star);
  var isAsync = false;
  var isMaybeStatic = this$1.type === tt.name && this$1.value === "static";
  this$1.parsePropertyName(method);
  method.static = isMaybeStatic && this$1.type !== tt.parenL;
  if (method.static) {
    if (isGenerator) this$1.unexpected();
    isGenerator = this$1.eat(tt.star);
    this$1.parsePropertyName(method);
  }
  if (this$1.options.ecmaVersion >= 8 && !isGenerator && !method.computed &&
      method.key.type === "Identifier" && method.key.name === "async" && this$1.type !== tt.parenL &&
      !this$1.canInsertSemicolon()) {
    isAsync = true;
    this$1.parsePropertyName(method);
  }
  method.kind = "method";
  var isGetSet = false;
  if (!method.computed) {
    var key = method.key;
    if (!isGenerator && !isAsync && key.type === "Identifier" && this$1.type !== tt.parenL && (key.name === "get" || key.name === "set")) {
      isGetSet = true;
      method.kind = key.name;
      key = this$1.parsePropertyName(method);
    }
    if (!method.static && (key.type === "Identifier" && key.name === "constructor" ||
        key.type === "Literal" && key.value === "constructor")) {
      if (hadConstructor) this$1.raise(key.start, "Duplicate constructor in the same class");
      if (isGetSet) this$1.raise(key.start, "Constructor can't have get/set modifier");
      if (isGenerator) this$1.raise(key.start, "Constructor can't be a generator");
      if (isAsync) this$1.raise(key.start, "Constructor can't be an async method");
      method.kind = "constructor";
      hadConstructor = true;
    }
  }
  this$1.parseClassMethod(classBody, method, isGenerator, isAsync);
  if (isGetSet) {
    var paramCount = method.kind === "get" ? 0 : 1;
    if (method.value.params.length !== paramCount) {
      var start = method.value.start;
      if (method.kind === "get")
        this$1.raiseRecoverable(start, "getter should have no params");
      else
        this$1.raiseRecoverable(start, "setter should have exactly one param");
    } else {
      if (method.kind === "set" && method.value.params[0].type === "RestElement")
        this$1.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params");
    }
  }
}
node.body = this.finishNode(classBody, "ClassBody");
return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression")

};

pp$1.parseClassMethod = function(classBody, method, isGenerator, isAsync) {

method.value = this.parseMethod(isGenerator, isAsync);
classBody.body.push(this.finishNode(method, "MethodDefinition"));

};

pp$1.parseClassId = function(node, isStatement) {

node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null;

};

pp$1.parseClassSuper = function(node) {

node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null;

};

// Parses module export declaration.

pp$1.parseExport = function(node, exports) {

var this$1 = this;

this.next();
// export * from '...'
if (this.eat(tt.star)) {
  this.expectContextual("from");
  node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
  this.semicolon();
  return this.finishNode(node, "ExportAllDeclaration")
}
if (this.eat(tt._default)) { // export default ...
  this.checkExport(exports, "default", this.lastTokStart);
  var isAsync;
  if (this.type === tt._function || (isAsync = this.isAsyncFunction())) {
    var fNode = this.startNode();
    this.next();
    if (isAsync) this.next();
    node.declaration = this.parseFunction(fNode, null, false, isAsync);
  } else if (this.type === tt._class) {
    var cNode = this.startNode();
    node.declaration = this.parseClass(cNode, null);
  } else {
    node.declaration = this.parseMaybeAssign();
    this.semicolon();
  }
  return this.finishNode(node, "ExportDefaultDeclaration")
}
// export var|const|let|function|class ...
if (this.shouldParseExportStatement()) {
  node.declaration = this.parseStatement(true);
  if (node.declaration.type === "VariableDeclaration")
    this.checkVariableExport(exports, node.declaration.declarations);
  else
    this.checkExport(exports, node.declaration.id.name, node.declaration.id.start);
  node.specifiers = [];
  node.source = null;
} else { // export { x, y as z } [from '...']
  node.declaration = null;
  node.specifiers = this.parseExportSpecifiers(exports);
  if (this.eatContextual("from")) {
    node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
  } else {
    // check for keywords used as local names
    for (var i = 0; i < node.specifiers.length; i++) {
      if (this$1.keywords.test(node.specifiers[i].local.name) || this$1.reservedWords.test(node.specifiers[i].local.name)) {
        this$1.unexpected(node.specifiers[i].local.start);
      }
    }

    node.source = null;
  }
  this.semicolon();
}
return this.finishNode(node, "ExportNamedDeclaration")

};

pp$1.checkExport = function(exports, name, pos) {

if (!exports) return
if (Object.prototype.hasOwnProperty.call(exports, name))
  this.raiseRecoverable(pos, "Duplicate export '" + name + "'");
exports[name] = true;

};

pp$1.checkPatternExport = function(exports, pat) {

var this$1 = this;

var type = pat.type;
if (type == "Identifier")
  this.checkExport(exports, pat.name, pat.start);
else if (type == "ObjectPattern")
  for (var i = 0; i < pat.properties.length; ++i)
    this$1.checkPatternExport(exports, pat.properties[i].value);
else if (type == "ArrayPattern")
  for (var i$1 = 0; i$1 < pat.elements.length; ++i$1) {
    var elt = pat.elements[i$1];
    if (elt) this$1.checkPatternExport(exports, elt);
  }
else if (type == "AssignmentPattern")
  this.checkPatternExport(exports, pat.left);
else if (type == "ParenthesizedExpression")
  this.checkPatternExport(exports, pat.expression);

};

pp$1.checkVariableExport = function(exports, decls) {

var this$1 = this;

if (!exports) return
for (var i = 0; i < decls.length; i++)
  this$1.checkPatternExport(exports, decls[i].id);

};

pp$1.shouldParseExportStatement = function() {

return this.type.keyword === "var"
  || this.type.keyword === "const"
  || this.type.keyword === "class"
  || this.type.keyword === "function"
  || this.isLet()
  || this.isAsyncFunction()

};

// Parses a comma-separated list of module exports.

pp$1.parseExportSpecifiers = function(exports) {

var this$1 = this;

var nodes = [], first = true;
// export { x, y as z } [from '...']
this.expect(tt.braceL);
while (!this.eat(tt.braceR)) {
  if (!first) {
    this$1.expect(tt.comma);
    if (this$1.afterTrailingComma(tt.braceR)) break
  } else first = false;

  var node = this$1.startNode();
  node.local = this$1.parseIdent(true);
  node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local;
  this$1.checkExport(exports, node.exported.name, node.exported.start);
  nodes.push(this$1.finishNode(node, "ExportSpecifier"));
}
return nodes

};

// Parses import declaration.

pp$1.parseImport = function(node) {

this.next();
// import '...'
if (this.type === tt.string) {
  node.specifiers = empty;
  node.source = this.parseExprAtom();
} else {
  node.specifiers = this.parseImportSpecifiers();
  this.expectContextual("from");
  node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected();
}
this.semicolon();
return this.finishNode(node, "ImportDeclaration")

};

// Parses a comma-separated list of module imports.

pp$1.parseImportSpecifiers = function() {

var this$1 = this;

var nodes = [], first = true;
if (this.type === tt.name) {
  // import defaultObj, { x, y as z } from '...'
  var node = this.startNode();
  node.local = this.parseIdent();
  this.checkLVal(node.local, true);
  nodes.push(this.finishNode(node, "ImportDefaultSpecifier"));
  if (!this.eat(tt.comma)) return nodes
}
if (this.type === tt.star) {
  var node$1 = this.startNode();
  this.next();
  this.expectContextual("as");
  node$1.local = this.parseIdent();
  this.checkLVal(node$1.local, true);
  nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier"));
  return nodes
}
this.expect(tt.braceL);
while (!this.eat(tt.braceR)) {
  if (!first) {
    this$1.expect(tt.comma);
    if (this$1.afterTrailingComma(tt.braceR)) break
  } else first = false;

  var node$2 = this$1.startNode();
  node$2.imported = this$1.parseIdent(true);
  if (this$1.eatContextual("as")) {
    node$2.local = this$1.parseIdent();
  } else {
    node$2.local = node$2.imported;
    if (this$1.isKeyword(node$2.local.name)) this$1.unexpected(node$2.local.start);
    if (this$1.reservedWordsStrict.test(node$2.local.name)) this$1.raiseRecoverable(node$2.local.start, "The keyword '" + node$2.local.name + "' is reserved");
  }
  this$1.checkLVal(node$2.local, true);
  nodes.push(this$1.finishNode(node$2, "ImportSpecifier"));
}
return nodes

};

var pp$2 = Parser.prototype;

// Convert existing expression atom to assignable pattern // if possible.

pp$2.toAssignable = function(node, isBinding) {

var this$1 = this;

if (this.options.ecmaVersion >= 6 && node) {
  switch (node.type) {
    case "Identifier":
    if (this.inAsync && node.name === "await")
      this.raise(node.start, "Can not use 'await' as identifier inside an async function");
    break

  case "ObjectPattern":
  case "ArrayPattern":
    break

  case "ObjectExpression":
    node.type = "ObjectPattern";
    for (var i = 0; i < node.properties.length; i++) {
      var prop = node.properties[i];
      if (prop.kind !== "init") this$1.raise(prop.key.start, "Object pattern can't contain getter or setter");
      this$1.toAssignable(prop.value, isBinding);
    }
    break

  case "ArrayExpression":
    node.type = "ArrayPattern";
    this.toAssignableList(node.elements, isBinding);
    break

  case "AssignmentExpression":
    if (node.operator === "=") {
      node.type = "AssignmentPattern";
      delete node.operator;
      this.toAssignable(node.left, isBinding);
      // falls through to AssignmentPattern
    } else {
      this.raise(node.left.end, "Only '=' operator can be used for specifying default value.");
      break
    }

  case "AssignmentPattern":
    break

  case "ParenthesizedExpression":
    node.expression = this.toAssignable(node.expression, isBinding);
    break

  case "MemberExpression":
    if (!isBinding) break

  default:
    this.raise(node.start, "Assigning to rvalue");
  }
}
return node

};

// Convert list of expression atoms to binding list.

pp$2.toAssignableList = function(exprList, isBinding) {

var this$1 = this;

var end = exprList.length;
if (end) {
  var last = exprList[end - 1];
  if (last && last.type == "RestElement") {
    --end;
  } else if (last && last.type == "SpreadElement") {
    last.type = "RestElement";
    var arg = last.argument;
    this.toAssignable(arg, isBinding);
    if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern")
      this.unexpected(arg.start);
    --end;
  }

  if (isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier")
    this.unexpected(last.argument.start);
}
for (var i = 0; i < end; i++) {
  var elt = exprList[i];
  if (elt) this$1.toAssignable(elt, isBinding);
}
return exprList

};

// Parses spread element.

pp$2.parseSpread = function(refDestructuringErrors) {

var node = this.startNode();
this.next();
node.argument = this.parseMaybeAssign(false, refDestructuringErrors);
return this.finishNode(node, "SpreadElement")

};

pp$2.parseRest = function(allowNonIdent) {

var node = this.startNode();
this.next();

// RestElement inside of a function parameter must be an identifier
if (allowNonIdent) node.argument = this.type === tt.name ? this.parseIdent() : this.unexpected();
else node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected();

return this.finishNode(node, "RestElement")

};

// Parses lvalue (assignable) atom.

pp$2.parseBindingAtom = function() {

if (this.options.ecmaVersion < 6) return this.parseIdent()
switch (this.type) {
case tt.name:
  return this.parseIdent()

case tt.bracketL:
  var node = this.startNode();
  this.next();
  node.elements = this.parseBindingList(tt.bracketR, true, true);
  return this.finishNode(node, "ArrayPattern")

case tt.braceL:
  return this.parseObj(true)

default:
  this.unexpected();
}

};

pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowNonIdent) {

var this$1 = this;

var elts = [], first = true;
while (!this.eat(close)) {
  if (first) first = false;
  else this$1.expect(tt.comma);
  if (allowEmpty && this$1.type === tt.comma) {
    elts.push(null);
  } else if (allowTrailingComma && this$1.afterTrailingComma(close)) {
    break
  } else if (this$1.type === tt.ellipsis) {
    var rest = this$1.parseRest(allowNonIdent);
    this$1.parseBindingListItem(rest);
    elts.push(rest);
    if (this$1.type === tt.comma) this$1.raise(this$1.start, "Comma is not permitted after the rest element");
    this$1.expect(close);
    break
  } else {
    var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc);
    this$1.parseBindingListItem(elem);
    elts.push(elem);
  }
}
return elts

};

pp$2.parseBindingListItem = function(param) {

return param

};

// Parses assignment pattern around given atom if possible.

pp$2.parseMaybeDefault = function(startPos, startLoc, left) {

left = left || this.parseBindingAtom();
if (this.options.ecmaVersion < 6 || !this.eat(tt.eq)) return left
var node = this.startNodeAt(startPos, startLoc);
node.left = left;
node.right = this.parseMaybeAssign();
return this.finishNode(node, "AssignmentPattern")

};

// Verify that a node is an lval — something that can be assigned // to.

pp$2.checkLVal = function(expr, isBinding, checkClashes) {

var this$1 = this;

switch (expr.type) {
case "Identifier":
  if (this.strict && this.reservedWordsStrictBind.test(expr.name))
    this.raiseRecoverable(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode");
  if (checkClashes) {
    if (has(checkClashes, expr.name))
      this.raiseRecoverable(expr.start, "Argument name clash");
    checkClashes[expr.name] = true;
  }
  break

case "MemberExpression":
  if (isBinding) this.raiseRecoverable(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression");
  break

case "ObjectPattern":
  for (var i = 0; i < expr.properties.length; i++)
    this$1.checkLVal(expr.properties[i].value, isBinding, checkClashes);
  break

case "ArrayPattern":
  for (var i$1 = 0; i$1 < expr.elements.length; i$1++) {
    var elem = expr.elements[i$1];
    if (elem) this$1.checkLVal(elem, isBinding, checkClashes);
  }
  break

case "AssignmentPattern":
  this.checkLVal(expr.left, isBinding, checkClashes);
  break

case "RestElement":
  this.checkLVal(expr.argument, isBinding, checkClashes);
  break

case "ParenthesizedExpression":
  this.checkLVal(expr.expression, isBinding, checkClashes);
  break

default:
  this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue");
}

};

// A recursive descent parser operates by defining functions for all // syntactic elements, and recursively calling those, each function // advancing the input stream and returning an AST node. Precedence // of constructs (for example, the fact that `!x` means `!(x)` // instead of `(!x)` is handled by the fact that the parser // function that parses unary prefix operators is called first, and // in turn calls the function that parses `[]` subscripts — that // way, it'll receive the node for `x` already parsed, and wraps // that in the unary operator node. // // Acorn uses an [operator precedence parser] to handle binary // operator precedence, because it is much more compact than using // the technique outlined above, which uses different, nesting // functions to specify precedence, for all of the ten binary // precedence levels that JavaScript defines. // // [opp]: en.wikipedia.org/wiki/Operator-precedence_parser

var pp$3 = Parser.prototype;

// Check if property name clashes with already added. // Object/class getters and setters are not allowed to clash — // either with each other or with an init property — and in // strict mode, init properties are also not allowed to be repeated.

pp$3.checkPropClash = function(prop, propHash) {

if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
  return
var key = prop.key;
var name;
switch (key.type) {
case "Identifier": name = key.name; break
case "Literal": name = String(key.value); break
default: return
}
var kind = prop.kind;
if (this.options.ecmaVersion >= 6) {
  if (name === "__proto__" && kind === "init") {
    if (propHash.proto) this.raiseRecoverable(key.start, "Redefinition of __proto__ property");
    propHash.proto = true;
  }
  return
}
name = "$" + name;
var other = propHash[name];
if (other) {
  var isGetSet = kind !== "init";
  if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init))
    this.raiseRecoverable(key.start, "Redefinition of property");
} else {
  other = propHash[name] = {
    init: false,
    get: false,
    set: false
  };
}
other[kind] = true;

};

// ### Expression parsing

// These nest, from the most general expression type at the top to // 'atomic', nondivisible expression types at the bottom. Most of // the functions will simply let the function(s) below them parse, // and, if the syntactic construct they handle is present, wrap // the AST node that the inner parser gave them in another node.

// Parse a full expression. The optional arguments are used to // forbid the `in` operator (in for loops initalization expressions) // and provide reference for storing '=' operator inside shorthand // property assignment in contexts where both object expression // and object pattern might appear (so it's possible to raise // delayed syntax error at correct position).

pp$3.parseExpression = function(noIn, refDestructuringErrors) {

var this$1 = this;

var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseMaybeAssign(noIn, refDestructuringErrors);
if (this.type === tt.comma) {
  var node = this.startNodeAt(startPos, startLoc);
  node.expressions = [expr];
  while (this.eat(tt.comma)) node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors));
  return this.finishNode(node, "SequenceExpression")
}
return expr

};

// Parse an assignment expression. This includes applications of // operators like `+=`.

pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) {

if (this.inGenerator && this.isContextual("yield")) return this.parseYield()

var ownDestructuringErrors = false, oldParenAssign = -1;
if (refDestructuringErrors) {
  oldParenAssign = refDestructuringErrors.parenthesizedAssign;
  refDestructuringErrors.parenthesizedAssign = -1;
} else {
  refDestructuringErrors = new DestructuringErrors;
  ownDestructuringErrors = true;
}

var startPos = this.start, startLoc = this.startLoc;
if (this.type == tt.parenL || this.type == tt.name)
  this.potentialArrowAt = this.start;
var left = this.parseMaybeConditional(noIn, refDestructuringErrors);
if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc);
if (this.type.isAssign) {
  this.checkPatternErrors(refDestructuringErrors, true);
  if (!ownDestructuringErrors) DestructuringErrors.call(refDestructuringErrors);
  var node = this.startNodeAt(startPos, startLoc);
  node.operator = this.value;
  node.left = this.type === tt.eq ? this.toAssignable(left) : left;
  refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly
  this.checkLVal(left);
  this.next();
  node.right = this.parseMaybeAssign(noIn);
  return this.finishNode(node, "AssignmentExpression")
} else {
  if (ownDestructuringErrors) this.checkExpressionErrors(refDestructuringErrors, true);
}
if (oldParenAssign > -1) refDestructuringErrors.parenthesizedAssign = oldParenAssign;
return left

};

// Parse a ternary conditional (`?:`) operator.

pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) {

var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseExprOps(noIn, refDestructuringErrors);
if (this.checkExpressionErrors(refDestructuringErrors)) return expr
if (this.eat(tt.question)) {
  var node = this.startNodeAt(startPos, startLoc);
  node.test = expr;
  node.consequent = this.parseMaybeAssign();
  this.expect(tt.colon);
  node.alternate = this.parseMaybeAssign(noIn);
  return this.finishNode(node, "ConditionalExpression")
}
return expr

};

// Start the precedence parser.

pp$3.parseExprOps = function(noIn, refDestructuringErrors) {

var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseMaybeUnary(refDestructuringErrors, false);
if (this.checkExpressionErrors(refDestructuringErrors)) return expr
return this.parseExprOp(expr, startPos, startLoc, -1, noIn)

};

// Parse binary operators with the operator precedence parsing // algorithm. `left` is the left-hand side of the operator. // `minPrec` provides context that allows the function to stop and // defer further parser to one of its callers when it encounters an // operator that has a lower precedence than the set it is parsing.

pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) {

var prec = this.type.binop;
if (prec != null && (!noIn || this.type !== tt._in)) {
  if (prec > minPrec) {
    var logical = this.type === tt.logicalOR || this.type === tt.logicalAND;
    var op = this.value;
    this.next();
    var startPos = this.start, startLoc = this.startLoc;
    var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
    var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
    return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn)
  }
}
return left

};

pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) {

var node = this.startNodeAt(startPos, startLoc);
node.left = left;
node.operator = op;
node.right = right;
return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression")

};

// Parse unary operators, both prefix and postfix.

pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {

var this$1 = this;

var startPos = this.start, startLoc = this.startLoc, expr;
if (this.inAsync && this.isContextual("await")) {
  expr = this.parseAwait(refDestructuringErrors);
  sawUnary = true;
} else if (this.type.prefix) {
  var node = this.startNode(), update = this.type === tt.incDec;
  node.operator = this.value;
  node.prefix = true;
  this.next();
  node.argument = this.parseMaybeUnary(null, true);
  this.checkExpressionErrors(refDestructuringErrors, true);
  if (update) this.checkLVal(node.argument);
  else if (this.strict && node.operator === "delete" &&
           node.argument.type === "Identifier")
    this.raiseRecoverable(node.start, "Deleting local variable in strict mode");
  else sawUnary = true;
  expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression");
} else {
  expr = this.parseExprSubscripts(refDestructuringErrors);
  if (this.checkExpressionErrors(refDestructuringErrors)) return expr
  while (this.type.postfix && !this.canInsertSemicolon()) {
    var node$1 = this$1.startNodeAt(startPos, startLoc);
    node$1.operator = this$1.value;
    node$1.prefix = false;
    node$1.argument = expr;
    this$1.checkLVal(expr);
    this$1.next();
    expr = this$1.finishNode(node$1, "UpdateExpression");
  }
}

if (!sawUnary && this.eat(tt.starstar))
  return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false)
else
  return expr

};

// Parse call, dot, and `[]`-subscript expressions.

pp$3.parseExprSubscripts = function(refDestructuringErrors) {

var startPos = this.start, startLoc = this.startLoc;
var expr = this.parseExprAtom(refDestructuringErrors);
var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")";
if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr
var result = this.parseSubscripts(expr, startPos, startLoc);
if (refDestructuringErrors && result.type === "MemberExpression") {
  if (refDestructuringErrors.parenthesizedAssign >= result.start) refDestructuringErrors.parenthesizedAssign = -1;
  if (refDestructuringErrors.parenthesizedBind >= result.start) refDestructuringErrors.parenthesizedBind = -1;
}
return result

};

pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) {

var this$1 = this;

var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" &&
    this.lastTokEnd == base.end && !this.canInsertSemicolon();
for (var computed;;) {
  if ((computed = this$1.eat(tt.bracketL)) || this$1.eat(tt.dot)) {
    var node = this$1.startNodeAt(startPos, startLoc);
    node.object = base;
    node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true);
    node.computed = !!computed;
    if (computed) this$1.expect(tt.bracketR);
    base = this$1.finishNode(node, "MemberExpression");
  } else if (!noCalls && this$1.eat(tt.parenL)) {
    var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos;
    this$1.yieldPos = 0;
    this$1.awaitPos = 0;
    var exprList = this$1.parseExprList(tt.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors);
    if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(tt.arrow)) {
      this$1.checkPatternErrors(refDestructuringErrors, false);
      this$1.checkYieldAwaitInDefaultParams();
      this$1.yieldPos = oldYieldPos;
      this$1.awaitPos = oldAwaitPos;
      return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true)
    }
    this$1.checkExpressionErrors(refDestructuringErrors, true);
    this$1.yieldPos = oldYieldPos || this$1.yieldPos;
    this$1.awaitPos = oldAwaitPos || this$1.awaitPos;
    var node$1 = this$1.startNodeAt(startPos, startLoc);
    node$1.callee = base;
    node$1.arguments = exprList;
    base = this$1.finishNode(node$1, "CallExpression");
  } else if (this$1.type === tt.backQuote) {
    var node$2 = this$1.startNodeAt(startPos, startLoc);
    node$2.tag = base;
    node$2.quasi = this$1.parseTemplate();
    base = this$1.finishNode(node$2, "TaggedTemplateExpression");
  } else {
    return base
  }
}

};

// Parse an atomic expression — either a single token that is an // expression, an expression started by a keyword like `function` or // `new`, or an expression wrapped in punctuation like `()`, `[]`, // or `{}`.

pp$3.parseExprAtom = function(refDestructuringErrors) {

var node, canBeArrow = this.potentialArrowAt == this.start;
switch (this.type) {
case tt._super:
  if (!this.inFunction)
    this.raise(this.start, "'super' outside of function or class");

case tt._this:
  var type = this.type === tt._this ? "ThisExpression" : "Super";
  node = this.startNode();
  this.next();
  return this.finishNode(node, type)

case tt.name:
  var startPos = this.start, startLoc = this.startLoc;
  var id = this.parseIdent(this.type !== tt.name);
  if (this.options.ecmaVersion >= 8 && id.name === "async" && !this.canInsertSemicolon() && this.eat(tt._function))
    return this.parseFunction(this.startNodeAt(startPos, startLoc), false, false, true)
  if (canBeArrow && !this.canInsertSemicolon()) {
    if (this.eat(tt.arrow))
      return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false)
    if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === tt.name) {
      id = this.parseIdent();
      if (this.canInsertSemicolon() || !this.eat(tt.arrow))
        this.unexpected();
      return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true)
    }
  }
  return id

case tt.regexp:
  var value = this.value;
  node = this.parseLiteral(value.value);
  node.regex = {pattern: value.pattern, flags: value.flags};
  return node

case tt.num: case tt.string:
  return this.parseLiteral(this.value)

case tt._null: case tt._true: case tt._false:
  node = this.startNode();
  node.value = this.type === tt._null ? null : this.type === tt._true;
  node.raw = this.type.keyword;
  this.next();
  return this.finishNode(node, "Literal")

case tt.parenL:
  var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow);
  if (refDestructuringErrors) {
    if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr))
      refDestructuringErrors.parenthesizedAssign = start;
    if (refDestructuringErrors.parenthesizedBind < 0)
      refDestructuringErrors.parenthesizedBind = start;
  }
  return expr

case tt.bracketL:
  node = this.startNode();
  this.next();
  node.elements = this.parseExprList(tt.bracketR, true, true, refDestructuringErrors);
  return this.finishNode(node, "ArrayExpression")

case tt.braceL:
  return this.parseObj(false, refDestructuringErrors)

case tt._function:
  node = this.startNode();
  this.next();
  return this.parseFunction(node, false)

case tt._class:
  return this.parseClass(this.startNode(), false)

case tt._new:
  return this.parseNew()

case tt.backQuote:
  return this.parseTemplate()

default:
  this.unexpected();
}

};

pp$3.parseLiteral = function(value) {

var node = this.startNode();
node.value = value;
node.raw = this.input.slice(this.start, this.end);
this.next();
return this.finishNode(node, "Literal")

};

pp$3.parseParenExpression = function() {

this.expect(tt.parenL);
var val = this.parseExpression();
this.expect(tt.parenR);
return val

};

pp$3.parseParenAndDistinguishExpression = function(canBeArrow) {

var this$1 = this;

var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8;
if (this.options.ecmaVersion >= 6) {
  this.next();

  var innerStartPos = this.start, innerStartLoc = this.startLoc;
  var exprList = [], first = true, lastIsComma = false;
  var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart, innerParenStart;
  this.yieldPos = 0;
  this.awaitPos = 0;
  while (this.type !== tt.parenR) {
    first ? first = false : this$1.expect(tt.comma);
    if (allowTrailingComma && this$1.afterTrailingComma(tt.parenR, true)) {
      lastIsComma = true;
      break
    } else if (this$1.type === tt.ellipsis) {
      spreadStart = this$1.start;
      exprList.push(this$1.parseParenItem(this$1.parseRest()));
      if (this$1.type === tt.comma) this$1.raise(this$1.start, "Comma is not permitted after the rest element");
      break
    } else {
      if (this$1.type === tt.parenL && !innerParenStart) {
        innerParenStart = this$1.start;
      }
      exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem));
    }
  }
  var innerEndPos = this.start, innerEndLoc = this.startLoc;
  this.expect(tt.parenR);

  if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) {
    this.checkPatternErrors(refDestructuringErrors, false);
    this.checkYieldAwaitInDefaultParams();
    if (innerParenStart) this.unexpected(innerParenStart);
    this.yieldPos = oldYieldPos;
    this.awaitPos = oldAwaitPos;
    return this.parseParenArrowList(startPos, startLoc, exprList)
  }

  if (!exprList.length || lastIsComma) this.unexpected(this.lastTokStart);
  if (spreadStart) this.unexpected(spreadStart);
  this.checkExpressionErrors(refDestructuringErrors, true);
  this.yieldPos = oldYieldPos || this.yieldPos;
  this.awaitPos = oldAwaitPos || this.awaitPos;

  if (exprList.length > 1) {
    val = this.startNodeAt(innerStartPos, innerStartLoc);
    val.expressions = exprList;
    this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc);
  } else {
    val = exprList[0];
  }
} else {
  val = this.parseParenExpression();
}

if (this.options.preserveParens) {
  var par = this.startNodeAt(startPos, startLoc);
  par.expression = val;
  return this.finishNode(par, "ParenthesizedExpression")
} else {
  return val
}

};

pp$3.parseParenItem = function(item) {

return item

};

pp$3.parseParenArrowList = function(startPos, startLoc, exprList) {

return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList)

};

// New's precedence is slightly tricky. It must allow its argument to // be a `[]` or dot subscript expression, but not a call — at least, // not without wrapping it in parentheses. Thus, it uses the noCalls // argument to parseSubscripts to prevent it from consuming the // argument list.

var empty$1 = [];

pp$3.parseNew = function() {

var node = this.startNode();
var meta = this.parseIdent(true);
if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) {
  node.meta = meta;
  node.property = this.parseIdent(true);
  if (node.property.name !== "target")
    this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target");
  if (!this.inFunction)
    this.raiseRecoverable(node.start, "new.target can only be used in functions");
  return this.finishNode(node, "MetaProperty")
}
var startPos = this.start, startLoc = this.startLoc;
node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true);
if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, this.options.ecmaVersion >= 8, false);
else node.arguments = empty$1;
return this.finishNode(node, "NewExpression")

};

// Parse template expression.

pp$3.parseTemplateElement = function() {

var elem = this.startNode();
elem.value = {
  raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'),
  cooked: this.value
};
this.next();
elem.tail = this.type === tt.backQuote;
return this.finishNode(elem, "TemplateElement")

};

pp$3.parseTemplate = function() {

var this$1 = this;

var node = this.startNode();
this.next();
node.expressions = [];
var curElt = this.parseTemplateElement();
node.quasis = [curElt];
while (!curElt.tail) {
  this$1.expect(tt.dollarBraceL);
  node.expressions.push(this$1.parseExpression());
  this$1.expect(tt.braceR);
  node.quasis.push(curElt = this$1.parseTemplateElement());
}
this.next();
return this.finishNode(node, "TemplateLiteral")

};

// Parse an object literal or binding pattern.

pp$3.parseObj = function(isPattern, refDestructuringErrors) {

var this$1 = this;

var node = this.startNode(), first = true, propHash = {};
node.properties = [];
this.next();
while (!this.eat(tt.braceR)) {
  if (!first) {
    this$1.expect(tt.comma);
    if (this$1.afterTrailingComma(tt.braceR)) break
  } else first = false;

  var prop = this$1.startNode(), isGenerator, isAsync, startPos, startLoc;
  if (this$1.options.ecmaVersion >= 6) {
    prop.method = false;
    prop.shorthand = false;
    if (isPattern || refDestructuringErrors) {
      startPos = this$1.start;
      startLoc = this$1.startLoc;
    }
    if (!isPattern)
      isGenerator = this$1.eat(tt.star);
  }
  this$1.parsePropertyName(prop);
  if (!isPattern && this$1.options.ecmaVersion >= 8 && !isGenerator && !prop.computed &&
      prop.key.type === "Identifier" && prop.key.name === "async" && this$1.type !== tt.parenL &&
      this$1.type !== tt.colon && !this$1.canInsertSemicolon()) {
    isAsync = true;
    this$1.parsePropertyName(prop, refDestructuringErrors);
  } else {
    isAsync = false;
  }
  this$1.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors);
  this$1.checkPropClash(prop, propHash);
  node.properties.push(this$1.finishNode(prop, "Property"));
}
return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression")

};

pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors) {

if ((isGenerator || isAsync) && this.type === tt.colon)
  this.unexpected();

if (this.eat(tt.colon)) {
  prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors);
  prop.kind = "init";
} else if (this.options.ecmaVersion >= 6 && this.type === tt.parenL) {
  if (isPattern) this.unexpected();
  prop.kind = "init";
  prop.method = true;
  prop.value = this.parseMethod(isGenerator, isAsync);
} else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" &&
           (prop.key.name === "get" || prop.key.name === "set") &&
           (this.type != tt.comma && this.type != tt.braceR)) {
  if (isGenerator || isAsync || isPattern) this.unexpected();
  prop.kind = prop.key.name;
  this.parsePropertyName(prop);
  prop.value = this.parseMethod(false);
  var paramCount = prop.kind === "get" ? 0 : 1;
  if (prop.value.params.length !== paramCount) {
    var start = prop.value.start;
    if (prop.kind === "get")
      this.raiseRecoverable(start, "getter should have no params");
    else
      this.raiseRecoverable(start, "setter should have exactly one param");
  } else {
    if (prop.kind === "set" && prop.value.params[0].type === "RestElement")
      this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params");
  }
} else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
  if (this.keywords.test(prop.key.name) ||
      (this.strict ? this.reservedWordsStrict : this.reservedWords).test(prop.key.name) ||
      (this.inGenerator && prop.key.name == "yield") ||
      (this.inAsync && prop.key.name == "await"))
    this.raiseRecoverable(prop.key.start, "'" + prop.key.name + "' can not be used as shorthand property");
  prop.kind = "init";
  if (isPattern) {
    prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
  } else if (this.type === tt.eq && refDestructuringErrors) {
    if (refDestructuringErrors.shorthandAssign < 0)
      refDestructuringErrors.shorthandAssign = this.start;
    prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key);
  } else {
    prop.value = prop.key;
  }
  prop.shorthand = true;
} else this.unexpected();

};

pp$3.parsePropertyName = function(prop) {

if (this.options.ecmaVersion >= 6) {
  if (this.eat(tt.bracketL)) {
    prop.computed = true;
    prop.key = this.parseMaybeAssign();
    this.expect(tt.bracketR);
    return prop.key
  } else {
    prop.computed = false;
  }
}
return prop.key = this.type === tt.num || this.type === tt.string ? this.parseExprAtom() : this.parseIdent(true)

};

// Initialize empty function node.

pp$3.initFunction = function(node) {

node.id = null;
if (this.options.ecmaVersion >= 6) {
  node.generator = false;
  node.expression = false;
}
if (this.options.ecmaVersion >= 8)
  node.async = false;

};

// Parse object or class method.

pp$3.parseMethod = function(isGenerator, isAsync) {

var node = this.startNode(), oldInGen = this.inGenerator, oldInAsync = this.inAsync,
    oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;

this.initFunction(node);
if (this.options.ecmaVersion >= 6)
  node.generator = isGenerator;
if (this.options.ecmaVersion >= 8)
  node.async = !!isAsync;

this.inGenerator = node.generator;
this.inAsync = node.async;
this.yieldPos = 0;
this.awaitPos = 0;
this.inFunction = true;

this.expect(tt.parenL);
node.params = this.parseBindingList(tt.parenR, false, this.options.ecmaVersion >= 8);
this.checkYieldAwaitInDefaultParams();
this.parseFunctionBody(node, false);

this.inGenerator = oldInGen;
this.inAsync = oldInAsync;
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
this.inFunction = oldInFunc;
return this.finishNode(node, "FunctionExpression")

};

// Parse arrow function expression with given parameters.

pp$3.parseArrowExpression = function(node, params, isAsync) {

var oldInGen = this.inGenerator, oldInAsync = this.inAsync,
    oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldInFunc = this.inFunction;

this.initFunction(node);
if (this.options.ecmaVersion >= 8)
  node.async = !!isAsync;

this.inGenerator = false;
this.inAsync = node.async;
this.yieldPos = 0;
this.awaitPos = 0;
this.inFunction = true;

node.params = this.toAssignableList(params, true);
this.parseFunctionBody(node, true);

this.inGenerator = oldInGen;
this.inAsync = oldInAsync;
this.yieldPos = oldYieldPos;
this.awaitPos = oldAwaitPos;
this.inFunction = oldInFunc;
return this.finishNode(node, "ArrowFunctionExpression")

};

// Parse function body and check parameters.

pp$3.parseFunctionBody = function(node, isArrowFunction) {

var isExpression = isArrowFunction && this.type !== tt.braceL;
var oldStrict = this.strict, useStrict = false;

if (isExpression) {
  node.body = this.parseMaybeAssign();
  node.expression = true;
} else {
  var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params);
  if (!oldStrict || nonSimple) {
    useStrict = this.strictDirective(this.end);
    // If this is a strict mode function, verify that argument names
    // are not repeated, and it does not try to bind the words `eval`
    // or `arguments`.
    if (useStrict && nonSimple)
      this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list");
  }
  // Start a new scope with regard to labels and the `inFunction`
  // flag (restore them to their old value afterwards).
  var oldLabels = this.labels;
  this.labels = [];
  if (useStrict) this.strict = true;
  node.body = this.parseBlock(true);
  node.expression = false;
  this.labels = oldLabels;
}

if (oldStrict || useStrict) {
  this.strict = true;
  if (node.id)
    this.checkLVal(node.id, true);
  this.checkParams(node);
  this.strict = oldStrict;
} else if (isArrowFunction || !this.isSimpleParamList(node.params)) {
  this.checkParams(node);
}

};

pp$3.isSimpleParamList = function(params) {

for (var i = 0; i < params.length; i++)
  if (params[i].type !== "Identifier") return false
return true

};

// Checks function params for various disallowed patterns such as using “eval” // or “arguments” and duplicate parameters.

pp$3.checkParams = function(node) {

var this$1 = this;

var nameHash = {};
for (var i = 0; i < node.params.length; i++) this$1.checkLVal(node.params[i], true, nameHash);

};

// Parses a comma-separated list of expressions, and returns them as // an array. `close` is the token type that ends the list, and // `allowEmpty` can be turned on to allow subsequent commas with // nothing in between them to be parsed as `null` (which is needed // for array literals).

pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) {

var this$1 = this;

var elts = [], first = true;
while (!this.eat(close)) {
  if (!first) {
    this$1.expect(tt.comma);
    if (allowTrailingComma && this$1.afterTrailingComma(close)) break
  } else first = false;

  var elt;
  if (allowEmpty && this$1.type === tt.comma)
    elt = null;
  else if (this$1.type === tt.ellipsis) {
    elt = this$1.parseSpread(refDestructuringErrors);
    if (refDestructuringErrors && this$1.type === tt.comma && refDestructuringErrors.trailingComma < 0)
      refDestructuringErrors.trailingComma = this$1.start;
  } else {
    elt = this$1.parseMaybeAssign(false, refDestructuringErrors);
  }
  elts.push(elt);
}
return elts

};

// Parse the next token as an identifier. If `liberal` is true (used // when parsing properties), it will also convert keywords into // identifiers.

pp$3.parseIdent = function(liberal) {

var node = this.startNode();
if (liberal && this.options.allowReserved == "never") liberal = false;
if (this.type === tt.name) {
  if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) &&
      (this.options.ecmaVersion >= 6 ||
       this.input.slice(this.start, this.end).indexOf("\\") == -1))
    this.raiseRecoverable(this.start, "The keyword '" + this.value + "' is reserved");
  if (this.inGenerator && this.value === "yield")
    this.raiseRecoverable(this.start, "Can not use 'yield' as identifier inside a generator");
  if (this.inAsync && this.value === "await")
    this.raiseRecoverable(this.start, "Can not use 'await' as identifier inside an async function");
  node.name = this.value;
} else if (liberal && this.type.keyword) {
  node.name = this.type.keyword;
} else {
  this.unexpected();
}
this.next();
return this.finishNode(node, "Identifier")

};

// Parses yield expression inside generator.

pp$3.parseYield = function() {

if (!this.yieldPos) this.yieldPos = this.start;

var node = this.startNode();
this.next();
if (this.type == tt.semi || this.canInsertSemicolon() || (this.type != tt.star && !this.type.startsExpr)) {
  node.delegate = false;
  node.argument = null;
} else {
  node.delegate = this.eat(tt.star);
  node.argument = this.parseMaybeAssign();
}
return this.finishNode(node, "YieldExpression")

};

pp$3.parseAwait = function() {

if (!this.awaitPos) this.awaitPos = this.start;

var node = this.startNode();
this.next();
node.argument = this.parseMaybeUnary(null, true);
return this.finishNode(node, "AwaitExpression")

};

var pp$4 = Parser.prototype;

// This function is used to raise exceptions on parse errors. It // takes an offset integer (into the current `input`) to indicate // the location of the error, attaches the position to the end // of the error message, and then raises a `SyntaxError` with that // message.

pp$4.raise = function(pos, message) {

var loc = getLineInfo(this.input, pos);
message += " (" + loc.line + ":" + loc.column + ")";
var err = new SyntaxError(message);
err.pos = pos; err.loc = loc; err.raisedAt = this.pos;
throw err

};

pp$4.raiseRecoverable = pp$4.raise;

pp$4.curPosition = function() {

if (this.options.locations) {
  return new Position(this.curLine, this.pos - this.lineStart)
}

};

var Node = function Node(parser, pos, loc) {

this.type = "";
this.start = pos;
this.end = 0;
if (parser.options.locations)
  this.loc = new SourceLocation(parser, loc);
if (parser.options.directSourceFile)
  this.sourceFile = parser.options.directSourceFile;
if (parser.options.ranges)
  this.range = [pos, 0];

};

// Start an AST node, attaching a start offset.

var pp$5 = Parser.prototype;

pp$5.startNode = function() {

return new Node(this, this.start, this.startLoc)

};

pp$5.startNodeAt = function(pos, loc) {

return new Node(this, pos, loc)

};

// Finish an AST node, adding `type` and `end` properties.

function finishNodeAt(node, type, pos, loc) {

node.type = type;
node.end = pos;
if (this.options.locations)
  node.loc.end = loc;
if (this.options.ranges)
  node.range[1] = pos;
return node

}

pp$5.finishNode = function(node, type) {

return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc)

};

// Finish node at given position

pp$5.finishNodeAt = function(node, type, pos, loc) {

return finishNodeAt.call(this, node, type, pos, loc)

};

// The algorithm used to determine whether a regexp can appear at a // given point in the program is loosely based on sweet.js' approach. // See github.com/mozilla/sweet.js/wiki/design

var TokContext = function TokContext(token, isExpr, preserveSpace, override) {

this.token = token;
this.isExpr = !!isExpr;
this.preserveSpace = !!preserveSpace;
this.override = override;

};

var types = {

b_stat: new TokContext("{", false),
b_expr: new TokContext("{", true),
b_tmpl: new TokContext("${", true),
p_stat: new TokContext("(", false),
p_expr: new TokContext("(", true),
q_tmpl: new TokContext("`", true, true, function (p) { return p.readTmplToken(); }),
f_expr: new TokContext("function", true)

};

var pp$6 = Parser.prototype;

pp$6.initialContext = function() {

return [types.b_stat]

};

pp$6.braceIsBlock = function(prevType) {

if (prevType === tt.colon) {
  var parent = this.curContext();
  if (parent === types.b_stat || parent === types.b_expr)
    return !parent.isExpr
}
if (prevType === tt._return)
  return lineBreak.test(this.input.slice(this.lastTokEnd, this.start))
if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR)
  return true
if (prevType == tt.braceL)
  return this.curContext() === types.b_stat
return !this.exprAllowed

};

pp$6.updateContext = function(prevType) {

var update, type = this.type;
if (type.keyword && prevType == tt.dot)
  this.exprAllowed = false;
else if (update = type.updateContext)
  update.call(this, prevType);
else
  this.exprAllowed = type.beforeExpr;

};

// Token-specific context update code

tt.parenR.updateContext = tt.braceR.updateContext = function() {

if (this.context.length == 1) {
  this.exprAllowed = true;
  return
}
var out = this.context.pop();
if (out === types.b_stat && this.curContext() === types.f_expr) {
  this.context.pop();
  this.exprAllowed = false;
} else if (out === types.b_tmpl) {
  this.exprAllowed = true;
} else {
  this.exprAllowed = !out.isExpr;
}

};

tt.braceL.updateContext = function(prevType) {

this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr);
this.exprAllowed = true;

};

tt.dollarBraceL.updateContext = function() {

this.context.push(types.b_tmpl);
this.exprAllowed = true;

};

tt.parenL.updateContext = function(prevType) {

var statementParens = prevType === tt._if || prevType === tt._for || prevType === tt._with || prevType === tt._while;
this.context.push(statementParens ? types.p_stat : types.p_expr);
this.exprAllowed = true;

};

tt.incDec.updateContext = function() {

// tokExprAllowed stays unchanged

};

tt._function.updateContext = function(prevType) {

if (prevType.beforeExpr && prevType !== tt.semi && prevType !== tt._else &&
    !((prevType === tt.colon || prevType === tt.braceL) && this.curContext() === types.b_stat))
  this.context.push(types.f_expr);
this.exprAllowed = false;

};

tt.backQuote.updateContext = function() {

if (this.curContext() === types.q_tmpl)
  this.context.pop();
else
  this.context.push(types.q_tmpl);
this.exprAllowed = false;

};

// Object type used to represent tokens. Note that normally, tokens // simply exist as properties on the parser object. This is only // used for the onToken callback and the external tokenizer.

var Token = function Token(p) {

this.type = p.type;
this.value = p.value;
this.start = p.start;
this.end = p.end;
if (p.options.locations)
  this.loc = new SourceLocation(p, p.startLoc, p.endLoc);
if (p.options.ranges)
  this.range = [p.start, p.end];

};

// ## Tokenizer

var pp$7 = Parser.prototype;

// Are we running under Rhino? var isRhino = typeof Packages == “object” && Object.prototype.toString.call(Packages) == “[object JavaPackage]”;

// Move to the next token

pp$7.next = function() {

if (this.options.onToken)
  this.options.onToken(new Token(this));

this.lastTokEnd = this.end;
this.lastTokStart = this.start;
this.lastTokEndLoc = this.endLoc;
this.lastTokStartLoc = this.startLoc;
this.nextToken();

};

pp$7.getToken = function() {

this.next();
return new Token(this)

};

// If we're in an ES6 environment, make parsers iterable if (typeof Symbol !== “undefined”)

pp$7[Symbol.iterator] = function () {
  var self = this;
  return {next: function () {
    var token = self.getToken();
    return {
      done: token.type === tt.eof,
      value: token
    }
  }}
};

// Toggle strict mode. Re-reads the next number or string to please // pedantic tests (`“use strict”; 010;` should fail).

pp$7.curContext = function() {

return this.context[this.context.length - 1]

};

// Read a single token, updating the parser object's token-related // properties.

pp$7.nextToken = function() {

var curContext = this.curContext();
if (!curContext || !curContext.preserveSpace) this.skipSpace();

this.start = this.pos;
if (this.options.locations) this.startLoc = this.curPosition();
if (this.pos >= this.input.length) return this.finishToken(tt.eof)

if (curContext.override) return curContext.override(this)
else this.readToken(this.fullCharCodeAtPos());

};

pp$7.readToken = function(code) {

// Identifier or keyword. '\uXXXX' sequences are allowed in
// identifiers, so '\' also dispatches to that.
if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */)
  return this.readWord()

return this.getTokenFromCode(code)

};

pp$7.fullCharCodeAtPos = function() {

var code = this.input.charCodeAt(this.pos);
if (code <= 0xd7ff || code >= 0xe000) return code
var next = this.input.charCodeAt(this.pos + 1);
return (code << 10) + next - 0x35fdc00

};

pp$7.skipBlockComment = function() {

var this$1 = this;

var startLoc = this.options.onComment && this.curPosition();
var start = this.pos, end = this.input.indexOf("*/", this.pos += 2);
if (end === -1) this.raise(this.pos - 2, "Unterminated comment");
this.pos = end + 2;
if (this.options.locations) {
  lineBreakG.lastIndex = start;
  var match;
  while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
    ++this$1.curLine;
    this$1.lineStart = match.index + match[0].length;
  }
}
if (this.options.onComment)
  this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos,
                         startLoc, this.curPosition());

};

pp$7.skipLineComment = function(startSkip) {

var this$1 = this;

var start = this.pos;
var startLoc = this.options.onComment && this.curPosition();
var ch = this.input.charCodeAt(this.pos+=startSkip);
while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) {
  ++this$1.pos;
  ch = this$1.input.charCodeAt(this$1.pos);
}
if (this.options.onComment)
  this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos,
                         startLoc, this.curPosition());

};

// Called at the start of the parse and after every token. Skips // whitespace and comments, and.

pp$7.skipSpace = function() {

var this$1 = this;

loop: while (this.pos < this.input.length) {
  var ch = this$1.input.charCodeAt(this$1.pos);
  switch (ch) {
    case 32: case 160: // ' '
      ++this$1.pos;
      break
    case 13:
      if (this$1.input.charCodeAt(this$1.pos + 1) === 10) {
        ++this$1.pos;
      }
    case 10: case 8232: case 8233:
      ++this$1.pos;
      if (this$1.options.locations) {
        ++this$1.curLine;
        this$1.lineStart = this$1.pos;
      }
      break
    case 47: // '/'
      switch (this$1.input.charCodeAt(this$1.pos + 1)) {
        case 42: // '*'
          this$1.skipBlockComment();
          break
        case 47:
          this$1.skipLineComment(2);
          break
        default:
          break loop
      }
      break
    default:
      if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) {
        ++this$1.pos;
      } else {
        break loop
      }
  }
}

};

// Called at the end of every token. Sets `end`, `val`, and // maintains `context` and `exprAllowed`, and skips the space after // the token, so that the next one's `start` will point at the // right position.

pp$7.finishToken = function(type, val) {

this.end = this.pos;
if (this.options.locations) this.endLoc = this.curPosition();
var prevType = this.type;
this.type = type;
this.value = val;

this.updateContext(prevType);

};

// ### Token reading

// This is the function that is called to fetch the next token. It // is somewhat obscure, because it works in character codes rather // than characters, and because operator parsing has been inlined // into it. // // All in the name of speed. // pp$7.readToken_dot = function() {

var next = this.input.charCodeAt(this.pos + 1);
if (next >= 48 && next <= 57) return this.readNumber(true)
var next2 = this.input.charCodeAt(this.pos + 2);
if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.'
  this.pos += 3;
  return this.finishToken(tt.ellipsis)
} else {
  ++this.pos;
  return this.finishToken(tt.dot)
}

};

pp$7.readToken_slash = function() { // '/'

var next = this.input.charCodeAt(this.pos + 1);
if (this.exprAllowed) {++this.pos; return this.readRegexp()}
if (next === 61) return this.finishOp(tt.assign, 2)
return this.finishOp(tt.slash, 1)

};

pp$7.readToken_mult_modulo_exp = function(code) { // '%*'

var next = this.input.charCodeAt(this.pos + 1);
var size = 1;
var tokentype = code === 42 ? tt.star : tt.modulo;

// exponentiation operator ** and **=
if (this.options.ecmaVersion >= 7 && next === 42) {
  ++size;
  tokentype = tt.starstar;
  next = this.input.charCodeAt(this.pos + 2);
}

if (next === 61) return this.finishOp(tt.assign, size + 1)
return this.finishOp(tokentype, size)

};

pp$7.readToken_pipe_amp = function(code) { // '|&'

var next = this.input.charCodeAt(this.pos + 1);
if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2)
if (next === 61) return this.finishOp(tt.assign, 2)
return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1)

};

pp$7.readToken_caret = function() { // '^'

var next = this.input.charCodeAt(this.pos + 1);
if (next === 61) return this.finishOp(tt.assign, 2)
return this.finishOp(tt.bitwiseXOR, 1)

};

pp$7.readToken_plus_min = function(code) { // '+-'

var next = this.input.charCodeAt(this.pos + 1);
if (next === code) {
  if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 &&
      lineBreak.test(this.input.slice(this.lastTokEnd, this.pos))) {
    // A `-->` line comment
    this.skipLineComment(3);
    this.skipSpace();
    return this.nextToken()
  }
  return this.finishOp(tt.incDec, 2)
}
if (next === 61) return this.finishOp(tt.assign, 2)
return this.finishOp(tt.plusMin, 1)

};

pp$7.readToken_lt_gt = function(code) { // '<>'

var next = this.input.charCodeAt(this.pos + 1);
var size = 1;
if (next === code) {
  size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2;
  if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1)
  return this.finishOp(tt.bitShift, size)
}
if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 &&
    this.input.charCodeAt(this.pos + 3) == 45) {
  if (this.inModule) this.unexpected();
  // `<!--`, an XML-style comment that should be interpreted as a line comment
  this.skipLineComment(4);
  this.skipSpace();
  return this.nextToken()
}
if (next === 61) size = 2;
return this.finishOp(tt.relational, size)

};

pp$7.readToken_eq_excl = function(code) { // '=!'

var next = this.input.charCodeAt(this.pos + 1);
if (next === 61) return this.finishOp(tt.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2)
if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>'
  this.pos += 2;
  return this.finishToken(tt.arrow)
}
return this.finishOp(code === 61 ? tt.eq : tt.prefix, 1)

};

pp$7.getTokenFromCode = function(code) {

switch (code) {
  // The interpretation of a dot depends on whether it is followed
  // by a digit or another two dots.
case 46: // '.'
  return this.readToken_dot()

  // Punctuation tokens.
case 40: ++this.pos; return this.finishToken(tt.parenL)
case 41: ++this.pos; return this.finishToken(tt.parenR)
case 59: ++this.pos; return this.finishToken(tt.semi)
case 44: ++this.pos; return this.finishToken(tt.comma)
case 91: ++this.pos; return this.finishToken(tt.bracketL)
case 93: ++this.pos; return this.finishToken(tt.bracketR)
case 123: ++this.pos; return this.finishToken(tt.braceL)
case 125: ++this.pos; return this.finishToken(tt.braceR)
case 58: ++this.pos; return this.finishToken(tt.colon)
case 63: ++this.pos; return this.finishToken(tt.question)

case 96: // '`'
  if (this.options.ecmaVersion < 6) break
  ++this.pos;
  return this.finishToken(tt.backQuote)

case 48: // '0'
  var next = this.input.charCodeAt(this.pos + 1);
  if (next === 120 || next === 88) return this.readRadixNumber(16) // '0x', '0X' - hex number
  if (this.options.ecmaVersion >= 6) {
    if (next === 111 || next === 79) return this.readRadixNumber(8) // '0o', '0O' - octal number
    if (next === 98 || next === 66) return this.readRadixNumber(2) // '0b', '0B' - binary number
  }
  // Anything else beginning with a digit is an integer, octal
  // number, or float.
case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9
  return this.readNumber(false)

  // Quotes produce strings.
case 34: case 39: // '"', "'"
  return this.readString(code)

  // Operators are parsed inline in tiny state machines. '=' (61) is
  // often referred to. `finishOp` simply skips the amount of
  // characters it is given as second argument, and returns a token
  // of the type given by its first argument.

case 47: // '/'
  return this.readToken_slash()

case 37: case 42: // '%*'
  return this.readToken_mult_modulo_exp(code)

case 124: case 38: // '|&'
  return this.readToken_pipe_amp(code)

case 94: // '^'
  return this.readToken_caret()

case 43: case 45: // '+-'
  return this.readToken_plus_min(code)

case 60: case 62: // '<>'
  return this.readToken_lt_gt(code)

case 61: case 33: // '=!'
  return this.readToken_eq_excl(code)

case 126: // '~'
  return this.finishOp(tt.prefix, 1)
}

this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'");

};

pp$7.finishOp = function(type, size) {

var str = this.input.slice(this.pos, this.pos + size);
this.pos += size;
return this.finishToken(type, str)

};

// Parse a regular expression. Some context-awareness is necessary, // since a '/' inside a '[]' set does not end the expression.

function tryCreateRegexp(src, flags, throwErrorAt, parser) {

try {
  return new RegExp(src, flags)
} catch (e) {
  if (throwErrorAt !== undefined) {
    if (e instanceof SyntaxError) parser.raise(throwErrorAt, "Error parsing regular expression: " + e.message);
    throw e
  }
}

}

var regexpUnicodeSupport = !!tryCreateRegexp(“uffff”, “u”);

pp$7.readRegexp = function() {

var this$1 = this;

var escaped, inClass, start = this.pos;
for (;;) {
  if (this$1.pos >= this$1.input.length) this$1.raise(start, "Unterminated regular expression");
  var ch = this$1.input.charAt(this$1.pos);
  if (lineBreak.test(ch)) this$1.raise(start, "Unterminated regular expression");
  if (!escaped) {
    if (ch === "[") inClass = true;
    else if (ch === "]" && inClass) inClass = false;
    else if (ch === "/" && !inClass) break
    escaped = ch === "\\";
  } else escaped = false;
  ++this$1.pos;
}
var content = this.input.slice(start, this.pos);
++this.pos;
// Need to use `readWord1` because '\uXXXX' sequences are allowed
// here (don't ask).
var mods = this.readWord1();
var tmp = content, tmpFlags = "";
if (mods) {
  var validFlags = /^[gim]*$/;
  if (this.options.ecmaVersion >= 6) validFlags = /^[gimuy]*$/;
  if (!validFlags.test(mods)) this.raise(start, "Invalid regular expression flag");
  if (mods.indexOf("u") >= 0) {
    if (regexpUnicodeSupport) {
      tmpFlags = "u";
    } else {
      // Replace each astral symbol and every Unicode escape sequence that
      // possibly represents an astral symbol or a paired surrogate with a
      // single ASCII symbol to avoid throwing on regular expressions that
      // are only valid in combination with the `/u` flag.
      // Note: replacing with the ASCII symbol `x` might cause false
      // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
      // perfectly valid pattern that is equivalent to `[a-b]`, but it would
      // be replaced by `[x-b]` which throws an error.
      tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, function (_match, code, offset) {
        code = Number("0x" + code);
        if (code > 0x10FFFF) this$1.raise(start + offset + 3, "Code point out of bounds");
        return "x"
      });
      tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x");
      tmpFlags = tmpFlags.replace("u", "");
    }
  }
}
// Detect invalid regular expressions.
var value = null;
// Rhino's regular expression parser is flaky and throws uncatchable exceptions,
// so don't do detection if we are running under Rhino
if (!isRhino) {
  tryCreateRegexp(tmp, tmpFlags, start, this);
  // Get a regular expression object for this pattern-flag pair, or `null` in
  // case the current environment doesn't support the flags it uses.
  value = tryCreateRegexp(content, mods);
}
return this.finishToken(tt.regexp, {pattern: content, flags: mods, value: value})

};

// Read an integer in the given radix. Return null if zero digits // were read, the integer value otherwise. When `len` is given, this // will return `null` unless the integer has exactly `len` digits.

pp$7.readInt = function(radix, len) {

var this$1 = this;

var start = this.pos, total = 0;
for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) {
  var code = this$1.input.charCodeAt(this$1.pos), val;
  if (code >= 97) val = code - 97 + 10; // a
  else if (code >= 65) val = code - 65 + 10; // A
  else if (code >= 48 && code <= 57) val = code - 48; // 0-9
  else val = Infinity;
  if (val >= radix) break
  ++this$1.pos;
  total = total * radix + val;
}
if (this.pos === start || len != null && this.pos - start !== len) return null

return total

};

pp$7.readRadixNumber = function(radix) {

this.pos += 2; // 0x
var val = this.readInt(radix);
if (val == null) this.raise(this.start + 2, "Expected number in radix " + radix);
if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number");
return this.finishToken(tt.num, val)

};

// Read an integer, octal integer, or floating-point number.

pp$7.readNumber = function(startsWithDot) {

var start = this.pos, isFloat = false, octal = this.input.charCodeAt(this.pos) === 48;
if (!startsWithDot && this.readInt(10) === null) this.raise(start, "Invalid number");
if (octal && this.pos == start + 1) octal = false;
var next = this.input.charCodeAt(this.pos);
if (next === 46 && !octal) { // '.'
  ++this.pos;
  this.readInt(10);
  isFloat = true;
  next = this.input.charCodeAt(this.pos);
}
if ((next === 69 || next === 101) && !octal) { // 'eE'
  next = this.input.charCodeAt(++this.pos);
  if (next === 43 || next === 45) ++this.pos; // '+-'
  if (this.readInt(10) === null) this.raise(start, "Invalid number");
  isFloat = true;
}
if (isIdentifierStart(this.fullCharCodeAtPos())) this.raise(this.pos, "Identifier directly after number");

var str = this.input.slice(start, this.pos), val;
if (isFloat) val = parseFloat(str);
else if (!octal || str.length === 1) val = parseInt(str, 10);
else if (/[89]/.test(str) || this.strict) this.raise(start, "Invalid number");
else val = parseInt(str, 8);
return this.finishToken(tt.num, val)

};

// Read a string value, interpreting backslash-escapes.

pp$7.readCodePoint = function() {

var ch = this.input.charCodeAt(this.pos), code;

if (ch === 123) {
  if (this.options.ecmaVersion < 6) this.unexpected();
  var codePos = ++this.pos;
  code = this.readHexChar(this.input.indexOf('}', this.pos) - this.pos);
  ++this.pos;
  if (code > 0x10FFFF) this.raise(codePos, "Code point out of bounds");
} else {
  code = this.readHexChar(4);
}
return code

};

function codePointToString(code) {

// UTF-16 Decoding
if (code <= 0xFFFF) return String.fromCharCode(code)
code -= 0x10000;
return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00)

}

pp$7.readString = function(quote) {

var this$1 = this;

var out = "", chunkStart = ++this.pos;
for (;;) {
  if (this$1.pos >= this$1.input.length) this$1.raise(this$1.start, "Unterminated string constant");
  var ch = this$1.input.charCodeAt(this$1.pos);
  if (ch === quote) break
  if (ch === 92) { // '\'
    out += this$1.input.slice(chunkStart, this$1.pos);
    out += this$1.readEscapedChar(false);
    chunkStart = this$1.pos;
  } else {
    if (isNewLine(ch)) this$1.raise(this$1.start, "Unterminated string constant");
    ++this$1.pos;
  }
}
out += this.input.slice(chunkStart, this.pos++);
return this.finishToken(tt.string, out)

};

// Reads template string tokens.

pp$7.readTmplToken = function() {

var this$1 = this;

var out = "", chunkStart = this.pos;
for (;;) {
  if (this$1.pos >= this$1.input.length) this$1.raise(this$1.start, "Unterminated template");
  var ch = this$1.input.charCodeAt(this$1.pos);
  if (ch === 96 || ch === 36 && this$1.input.charCodeAt(this$1.pos + 1) === 123) { // '`', '${'
    if (this$1.pos === this$1.start && this$1.type === tt.template) {
      if (ch === 36) {
        this$1.pos += 2;
        return this$1.finishToken(tt.dollarBraceL)
      } else {
        ++this$1.pos;
        return this$1.finishToken(tt.backQuote)
      }
    }
    out += this$1.input.slice(chunkStart, this$1.pos);
    return this$1.finishToken(tt.template, out)
  }
  if (ch === 92) { // '\'
    out += this$1.input.slice(chunkStart, this$1.pos);
    out += this$1.readEscapedChar(true);
    chunkStart = this$1.pos;
  } else if (isNewLine(ch)) {
    out += this$1.input.slice(chunkStart, this$1.pos);
    ++this$1.pos;
    switch (ch) {
      case 13:
        if (this$1.input.charCodeAt(this$1.pos) === 10) ++this$1.pos;
      case 10:
        out += "\n";
        break
      default:
        out += String.fromCharCode(ch);
        break
    }
    if (this$1.options.locations) {
      ++this$1.curLine;
      this$1.lineStart = this$1.pos;
    }
    chunkStart = this$1.pos;
  } else {
    ++this$1.pos;
  }
}

};

// Used to read escaped characters

pp$7.readEscapedChar = function(inTemplate) {

var ch = this.input.charCodeAt(++this.pos);
++this.pos;
switch (ch) {
case 110: return "\n" // 'n' -> '\n'
case 114: return "\r" // 'r' -> '\r'
case 120: return String.fromCharCode(this.readHexChar(2)) // 'x'
case 117: return codePointToString(this.readCodePoint()) // 'u'
case 116: return "\t" // 't' -> '\t'
case 98: return "\b" // 'b' -> '\b'
case 118: return "\u000b" // 'v' -> '\u000b'
case 102: return "\f" // 'f' -> '\f'
case 13: if (this.input.charCodeAt(this.pos) === 10) ++this.pos; // '\r\n'
case 10: // ' \n'
  if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; }
  return ""
default:
  if (ch >= 48 && ch <= 55) {
    var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0];
    var octal = parseInt(octalStr, 8);
    if (octal > 255) {
      octalStr = octalStr.slice(0, -1);
      octal = parseInt(octalStr, 8);
    }
    if (octalStr !== "0" && (this.strict || inTemplate)) {
      this.raise(this.pos - 2, "Octal literal in strict mode");
    }
    this.pos += octalStr.length - 1;
    return String.fromCharCode(octal)
  }
  return String.fromCharCode(ch)
}

};

// Used to read character escape sequences ('x', 'u', 'U').

pp$7.readHexChar = function(len) {

var codePos = this.pos;
var n = this.readInt(16, len);
if (n === null) this.raise(codePos, "Bad character escape sequence");
return n

};

// Read an identifier, and return it as a string. Sets `this.containsEsc` // to whether the word contained a 'u' escape. // // Incrementally adds only escaped chars, adding other chunks as-is // as a micro-optimization.

pp$7.readWord1 = function() {

var this$1 = this;

this.containsEsc = false;
var word = "", first = true, chunkStart = this.pos;
var astral = this.options.ecmaVersion >= 6;
while (this.pos < this.input.length) {
  var ch = this$1.fullCharCodeAtPos();
  if (isIdentifierChar(ch, astral)) {
    this$1.pos += ch <= 0xffff ? 1 : 2;
  } else if (ch === 92) { // "\"
    this$1.containsEsc = true;
    word += this$1.input.slice(chunkStart, this$1.pos);
    var escStart = this$1.pos;
    if (this$1.input.charCodeAt(++this$1.pos) != 117) // "u"
      this$1.raise(this$1.pos, "Expecting Unicode escape sequence \\uXXXX");
    ++this$1.pos;
    var esc = this$1.readCodePoint();
    if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral))
      this$1.raise(escStart, "Invalid Unicode escape");
    word += codePointToString(esc);
    chunkStart = this$1.pos;
  } else {
    break
  }
  first = false;
}
return word + this.input.slice(chunkStart, this.pos)

};

// Read an identifier or keyword token. Will check for reserved // words when necessary.

pp$7.readWord = function() {

var word = this.readWord1();
var type = tt.name;
if (this.keywords.test(word)) {
  if (this.containsEsc) this.raiseRecoverable(this.start, "Escape sequence in keyword " + word);
  type = keywordTypes[word];
}
return this.finishToken(type, word)

};

// The main exported interface (under `self.acorn` when in the // browser) is a `parse` function that takes a code string and // returns an abstract syntax tree as specified by [Mozilla parser // API]. // // [api]: developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API

function parse$1(input, options) {

return new Parser(options, input).parse()

}

// This function tries to parse a single expression at a given // offset in a string. Useful for parsing mixed-language formats // that embed JavaScript expressions.

function parseExpressionAt(input, pos, options) {

var p = new Parser(options, input, pos);
p.nextToken();
return p.parseExpression()

}

function readExpression ( parser ) {

var start = parser.index;

var name = parser.readUntil( /\s*}}/ );
if ( name && /^\w+$/.test( name ) ) {
        return {
                type: 'Identifier',
                start: start,
                end: start + name.length,
                name: name
        };
}

parser.index = start;

try {
        var node = parseExpressionAt( parser.template, parser.index );
        parser.index = node.end;

        return node;
} catch ( err ) {
        parser.acornError( err );
}

}

function spaces ( i ) {

var result = '';
while ( i-- ) { result += ' '; }
return result;

}

var scriptClosingTag = '</script>';

function readScript ( parser, start, attributes ) {

var scriptStart = parser.index;
var scriptEnd = parser.template.indexOf( scriptClosingTag, scriptStart );

var source = spaces( scriptStart ) + parser.template.slice( scriptStart, scriptEnd );
parser.index = scriptEnd + scriptClosingTag.length;

var ast;

try {
        ast = parse$1( source, {
                ecmaVersion: 8,
                sourceType: 'module'
        });
} catch ( err ) {
        parser.acornError( err );
}

if ( !ast.body.length ) { return null; }

ast.start = scriptStart;
return {
        start: start,
        end: parser.index,
        attributes: attributes,
        content: ast
};

}

var MAX_LINE_LENGTH = 100; var OFFSET_CORRECTION = 60;

function sourceFragment(error, extraLines) {

function processLines(start, end) {
    return lines.slice(start, end).map(function(line, idx) {
        var num = String(start + idx + 1);

        while (num.length < maxNumLength) {
            num = ' ' + num;
        }

        return num + ' |' + line;
    }).join('\n');
}

var lines = error.source.split(/\n|\r\n?|\f/);
var column = error.column;
var line = error.line;
var startLine = Math.max(1, line - extraLines) - 1;
var endLine = Math.min(line + extraLines, lines.length + 1);
var maxNumLength = Math.max(4, String(endLine).length) + 1;
var cutLeft = 0;

if (column > MAX_LINE_LENGTH) {
    cutLeft = column - OFFSET_CORRECTION + 3;
    column = OFFSET_CORRECTION - 2;
}

for (var i = startLine; i <= endLine; i++) {
    if (i >= 0 && i < lines.length) {
        lines[i] =
            (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
            lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
            (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
    }
}

return [
    processLines(startLine, line),
    new Array(column + maxNumLength + 2).join('-') + '^',
    processLines(line, endLine)
].join('\n');

}

var CssSyntaxError$1 = function(message, source, offset, line, column) {

var error = new SyntaxError();
error.name = 'CssSyntaxError';
error.message = message;
error.source = source;
error.offset = offset;
error.line = line;
error.column = column;

error.sourceFragment = function(extraLines) {
    return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
};
Object.defineProperty(error, 'formattedMessage', {
    get: function() {
        return (
            'Parse error: ' + error.message + '\n' +
            sourceFragment(error, 2)
        );
    }
});

// for backward capability
error.parseError = {
    offset: offset,
    line: line,
    column: column
};

return error;

};

var error = CssSyntaxError$1;

// token types (note: value shouldn't intersect with used char codes) var WHITESPACE$2 = 1; var IDENTIFIER$1 = 2; var NUMBER$1 = 3; var STRING$1 = 4; var COMMENT$2 = 5; var PUNCTUATOR$1 = 6;

var TAB = 9; var N$1 = 10; var F$1 = 12; var R$1 = 13; var SPACE = 32;

var TYPE$2 = {

Whitespace:   WHITESPACE$2,
Identifier:   IDENTIFIER$1,
Number:           NUMBER$1,
String:           STRING$1,
Comment:         COMMENT$2,
Punctuator:   PUNCTUATOR$1,

ExclamationMark:      33,  // !
QuotationMark:        34,  // "
NumberSign:           35,  // #
DollarSign:           36,  // $
PercentSign:          37,  // %
Ampersand:            38,  // &
Apostrophe:           39,  // '
LeftParenthesis:      40,  // (
RightParenthesis:     41,  // )
Asterisk:             42,  // *
PlusSign:             43,  // +
Comma:                44,  // ,
HyphenMinus:          45,  // -
FullStop:             46,  // .
Solidus:              47,  // /
Colon:                58,  // :
Semicolon:            59,  // ;
LessThanSign:         60,  // <
EqualsSign:           61,  // =
GreaterThanSign:      62,  // >
QuestionMark:         63,  // ?
CommercialAt:         64,  // @
LeftSquareBracket:    91,  // [
Backslash:            92,  // \
RightSquareBracket:   93,  // ]
CircumflexAccent:     94,  // ^
LowLine:              95,  // _
GraveAccent:          96,  // `
LeftCurlyBracket:    123,  // {
VerticalLine:        124,  // |
RightCurlyBracket:   125,  // }
Tilde:               126   // ~

};

var NAME$1 = Object.keys(TYPE$2).reduce(function(result, key) {

result[TYPE$2[key]] = key;
return result;

}, {});

var SafeUint32Array$1 = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported var SYMBOL_TYPE$1 = new SafeUint32Array$1(Math.max.apply(null, Object.keys(NAME$1).map(Number)) + 1); var PUNCTUATION = new SafeUint32Array$1(SYMBOL_TYPE$1.length);

for (var i = 0; i < SYMBOL_TYPE$1.length; i++) {

SYMBOL_TYPE$1[i] = IDENTIFIER$1;

}

// fill categories [

TYPE$2.ExclamationMark,    // !
TYPE$2.QuotationMark,      // "
TYPE$2.NumberSign,         // #
TYPE$2.DollarSign,         // $
TYPE$2.PercentSign,        // %
TYPE$2.Ampersand,          // &
TYPE$2.Apostrophe,         // '
TYPE$2.LeftParenthesis,    // (
TYPE$2.RightParenthesis,   // )
TYPE$2.Asterisk,           // *
TYPE$2.PlusSign,           // +
TYPE$2.Comma,              // ,
TYPE$2.HyphenMinus,        // -
TYPE$2.FullStop,           // .
TYPE$2.Solidus,            // /
TYPE$2.Colon,              // :
TYPE$2.Semicolon,          // ;
TYPE$2.LessThanSign,       // <
TYPE$2.EqualsSign,         // =
TYPE$2.GreaterThanSign,    // >
TYPE$2.QuestionMark,       // ?
TYPE$2.CommercialAt,       // @
TYPE$2.LeftSquareBracket,  // [
// TYPE.Backslash,          // \
TYPE$2.RightSquareBracket, // ]
TYPE$2.CircumflexAccent,   // ^
// TYPE.LowLine,            // _
TYPE$2.GraveAccent,        // `
TYPE$2.LeftCurlyBracket,   // {
TYPE$2.VerticalLine,       // |
TYPE$2.RightCurlyBracket,  // }
TYPE$2.Tilde               // ~

].forEach(function(key) {

SYMBOL_TYPE$1[Number(key)] = PUNCTUATOR$1;
PUNCTUATION[Number(key)] = PUNCTUATOR$1;

}, SYMBOL_TYPE$1);

for (var i = 48; i <= 57; i++) {

SYMBOL_TYPE$1[i] = NUMBER$1;

}

SYMBOL_TYPE$1 = WHITESPACE$2; SYMBOL_TYPE$1 = WHITESPACE$2; SYMBOL_TYPE$1 = WHITESPACE$2; SYMBOL_TYPE$1 = WHITESPACE$2; SYMBOL_TYPE$1 = WHITESPACE$2;

SYMBOL_TYPE$1 = STRING$1; SYMBOL_TYPE$1 = STRING$1;

// whitespace is punctuation … PUNCTUATION = PUNCTUATOR$1; PUNCTUATION = PUNCTUATOR$1; PUNCTUATION = PUNCTUATOR$1; PUNCTUATION = PUNCTUATOR$1; PUNCTUATION = PUNCTUATOR$1; // … hyper minus is not PUNCTUATION = 0;

var _const = {

TYPE: TYPE$2,
NAME: NAME$1,

SYMBOL_TYPE: SYMBOL_TYPE$1,
PUNCTUATION: PUNCTUATION

};

var constants$1 = _const; var PUNCTUATION$1 = constants$1.PUNCTUATION; var SYMBOL_TYPE$2 = constants$1.SYMBOL_TYPE; var SYMBOL_TYPE_LENGTH$1 = SYMBOL_TYPE$2.length; var TYPE$3 = constants$1.TYPE; var FULLSTOP$1 = TYPE$3.FullStop; var PLUSSIGN$1 = TYPE$3.PlusSign; var HYPHENMINUS$1 = TYPE$3.HyphenMinus; var PUNCTUATOR$2 = TYPE$3.Punctuator; var TAB$1 = 9; var N$2 = 10; var F$2 = 12; var R$2 = 13; var SPACE$1 = 32; var BACK_SLASH = 92; var E = 101; // 'e'.charCodeAt(0)

function firstCharOffset$1(source) {

return source.charCodeAt(0) === 0xFEFF ? 1 : 0;

}

function isHex(code) {

return (code >= 48 && code <= 57) || // 0 .. 9
       (code >= 65 && code <= 70) || // A .. F
       (code >= 97 && code <= 102);  // a .. f

}

function isNumber$1(code) {

return code >= 48 && code <= 57;

}

function isNewline(source, offset, code) {

if (code === N$2 || code === F$2 || code === R$2) {
    if (code === R$2 && offset + 1 < source.length && source.charCodeAt(offset + 1) === N$2) {
        return 2;
    }

    return 1;
}

return 0;

}

function cmpChar(testStr, offset, referenceCode) {

var code = testStr.charCodeAt(offset);

// code.toLowerCase()
if (code >= 65 && code <= 90) {
    code = code | 32;
}

return code === referenceCode;

}

function cmpStr$1(testStr, start, end, referenceStr) {

if (end - start !== referenceStr.length) {
    return false;
}

if (start < 0 || end > testStr.length) {
    return false;
}

for (var i = start; i < end; i++) {
    var testCode = testStr.charCodeAt(i);
    var refCode = referenceStr.charCodeAt(i - start);

    // testStr[i].toLowerCase()
    if (testCode >= 65 && testCode <= 90) {
        testCode = testCode | 32;
    }

    if (testCode !== refCode) {
        return false;
    }
}

return true;

}

function endsWith(testStr, referenceStr) {

return cmpStr$1(testStr, testStr.length - referenceStr.length, testStr.length, referenceStr);

}

function findLastNonSpaceLocation$1(scanner) {

for (var i = scanner.source.length - 1; i >= 0; i--) {
    var code = scanner.source.charCodeAt(i);

    if (code !== SPACE$1 && code !== TAB$1 && code !== R$2 && code !== N$2 && code !== F$2) {
        break;
    }
}

return scanner.getLocation(i + 1);

}

function findWhitespaceEnd$1(source, offset) {

for (; offset < source.length; offset++) {
    var code = source.charCodeAt(offset);

    if (code !== SPACE$1 && code !== TAB$1 && code !== R$2 && code !== N$2 && code !== F$2) {
        break;
    }
}

return offset;

}

function findCommentEnd$1(source, offset) {

var commentEnd = source.indexOf('*/', offset);

if (commentEnd === -1) {
    return source.length;
}

return commentEnd + 2;

}

function findStringEnd$1(source, offset, quote) {

for (; offset < source.length; offset++) {
    var code = source.charCodeAt(offset);

    // TODO: bad string
    if (code === BACK_SLASH) {
        offset++;
    } else if (code === quote) {
        offset++;
        break;
    }
}

return offset;

}

function findDecimalNumberEnd(source, offset) {

for (; offset < source.length; offset++) {
    var code = source.charCodeAt(offset);

    if (code < 48 || code > 57) {  // not a 0 .. 9
        break;
    }
}

return offset;

}

function findNumberEnd$1(source, offset, allowFraction) {

var code;

offset = findDecimalNumberEnd(source, offset);

// fraction: .\d+
if (allowFraction && offset + 1 < source.length && source.charCodeAt(offset) === FULLSTOP$1) {
    code = source.charCodeAt(offset + 1);

    if (isNumber$1(code)) {
        offset = findDecimalNumberEnd(source, offset + 1);
    }
}

// exponent: e[+-]\d+
if (offset + 1 < source.length) {
    if ((source.charCodeAt(offset) | 32) === E) { // case insensitive check for `e`
        code = source.charCodeAt(offset + 1);

        if (code === PLUSSIGN$1 || code === HYPHENMINUS$1) {
            if (offset + 2 < source.length) {
                code = source.charCodeAt(offset + 2);
            }
        }

        if (isNumber$1(code)) {
            offset = findDecimalNumberEnd(source, offset + 2);
        }
    }
}

return offset;

}

// skip escaped unicode sequence that can ends with space // [0-9a-f]{1,6}(rn|[ nrtf])? function findEscaseEnd(source, offset) {

for (var i = 0; i < 7 && offset + i < source.length; i++) {
    var code = source.charCodeAt(offset + i);

    if (i !== 6 && isHex(code)) {
        continue;
    }

    if (i > 0) {
        offset += i - 1 + isNewline(source, offset + i, code);
        if (code === SPACE$1 || code === TAB$1) {
            offset++;
        }
    }

    break;
}

return offset;

}

function findIdentifierEnd$1(source, offset) {

for (; offset < source.length; offset++) {
    var code = source.charCodeAt(offset);

    if (code === BACK_SLASH) {
        offset = findEscaseEnd(source, offset + 1);
    } else if (code < SYMBOL_TYPE_LENGTH$1 && PUNCTUATION$1[code] === PUNCTUATOR$2) {
        break;
    }
}

return offset;

}

var utils$1 = {

firstCharOffset: firstCharOffset$1,

isHex: isHex,
isNumber: isNumber$1,
isNewline: isNewline,

cmpChar: cmpChar,
cmpStr: cmpStr$1,
endsWith: endsWith,

findLastNonSpaceLocation: findLastNonSpaceLocation$1,
findWhitespaceEnd: findWhitespaceEnd$1,
findCommentEnd: findCommentEnd$1,
findStringEnd: findStringEnd$1,
findDecimalNumberEnd: findDecimalNumberEnd,
findNumberEnd: findNumberEnd$1,
findEscaseEnd: findEscaseEnd,
findIdentifierEnd: findIdentifierEnd$1

};

var CssSyntaxError = error;

var constants = _const; var TYPE$1 = constants.TYPE; var NAME = constants.NAME; var SYMBOL_TYPE = constants.SYMBOL_TYPE; var SYMBOL_TYPE_LENGTH = SYMBOL_TYPE.length;

var utils = utils$1; var firstCharOffset = utils.firstCharOffset; var cmpStr = utils.cmpStr; var isNumber = utils.isNumber; var findLastNonSpaceLocation = utils.findLastNonSpaceLocation; var findWhitespaceEnd = utils.findWhitespaceEnd; var findCommentEnd = utils.findCommentEnd; var findStringEnd = utils.findStringEnd; var findNumberEnd = utils.findNumberEnd; var findIdentifierEnd = utils.findIdentifierEnd;

var NULL = 0; var WHITESPACE$1 = TYPE$1.Whitespace; var IDENTIFIER = TYPE$1.Identifier; var NUMBER = TYPE$1.Number; var STRING = TYPE$1.String; var COMMENT$1 = TYPE$1.Comment; var PUNCTUATOR = TYPE$1.Punctuator;

var N = 10; var F = 12; var R = 13; var STAR = TYPE$1.Asterisk; var SLASH = TYPE$1.Solidus; var FULLSTOP = TYPE$1.FullStop; var PLUSSIGN = TYPE$1.PlusSign; var HYPHENMINUS = TYPE$1.HyphenMinus;

var MIN_BUFFER_SIZE = 16 * 1024; var OFFSET_MASK = 0x00FFFFFF; var TYPE_OFFSET = 24; var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported

function computeLinesAndColumns(tokenizer, source) {

var sourceLength = source.length;
var start = firstCharOffset(source);
var lines = tokenizer.lines;
var line = tokenizer.startLine;
var columns = tokenizer.columns;
var column = tokenizer.startColumn;

if (lines === null || lines.length < sourceLength + 1) {
    lines = new SafeUint32Array(Math.max(sourceLength + 1024, MIN_BUFFER_SIZE));
    columns = new SafeUint32Array(lines.length);
}

for (var i = start; i < sourceLength; i++) {
    var code = source.charCodeAt(i);

    lines[i] = line;
    columns[i] = column++;

    if (code === N || code === R || code === F) {
        if (code === R && i + 1 < sourceLength && source.charCodeAt(i + 1) === N) {
            i++;
            lines[i] = line;
            columns[i] = column;
        }

        line++;
        column = 1;
    }
}

lines[i] = line;
columns[i] = column;

tokenizer.linesAnsColumnsComputed = true;
tokenizer.lines = lines;
tokenizer.columns = columns;

}

function tokenLayout(tokenizer, source, startPos) {

var sourceLength = source.length;
var offsetAndType = tokenizer.offsetAndType;
var tokenCount = 0;
var prevType = 0;
var offset = startPos;

if (offsetAndType === null || offsetAndType.length < sourceLength + 1) {
    offsetAndType = new SafeUint32Array(sourceLength + 1024);
}

while (offset < sourceLength) {
    var code = source.charCodeAt(offset);
    var type = code < SYMBOL_TYPE_LENGTH ? SYMBOL_TYPE[code] : IDENTIFIER;

    switch (type) {
        case WHITESPACE$1:
            offset = findWhitespaceEnd(source, offset + 1);
            break;

        case PUNCTUATOR:
            if (code === STAR && prevType === SLASH) { // /*
                type = COMMENT$1;
                offset = findCommentEnd(source, offset + 1);
                tokenCount--; // rewrite prev token
            } else {
                // edge case for -.123 and +.123
                if (code === FULLSTOP && (prevType === PLUSSIGN || prevType === HYPHENMINUS)) {
                    if (offset + 1 < sourceLength && isNumber(source.charCodeAt(offset + 1))) {
                        type = NUMBER;
                        offset = findNumberEnd(source, offset + 2, false);
                        tokenCount--; // rewrite prev token
                        break;
                    }
                }

                type = code;
                offset = offset + 1;
            }

            break;

        case NUMBER:
            offset = findNumberEnd(source, offset + 1, prevType !== FULLSTOP);

            // merge number with a preceding dot, dash or plus
            if (prevType === FULLSTOP ||
                prevType === HYPHENMINUS ||
                prevType === PLUSSIGN) {
                tokenCount--; // rewrite prev token
            }

            break;

        case STRING:
            offset = findStringEnd(source, offset + 1, code);
            break;

        default:
            offset = findIdentifierEnd(source, offset);

            // merge identifier with a preceding dash
            if (prevType === HYPHENMINUS) {
                tokenCount--; // rewrite prev token
            }
    }

    offsetAndType[tokenCount++] = (type << TYPE_OFFSET) | offset;
    prevType = type;
}

offsetAndType[tokenCount] = offset;

tokenizer.offsetAndType = offsetAndType;
tokenizer.tokenCount = tokenCount;

}

// // tokenizer //

var Tokenizer$1 = function(source, startOffset, startLine, startColumn) {

this.offsetAndType = null;
this.lines = null;
this.columns = null;

this.setSource(source || '', startOffset, startLine, startColumn);

};

Tokenizer$1.prototype = {

setSource: function(source, startOffset, startLine, startColumn) {
    var start = firstCharOffset(source);

    this.source = source;
    this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
    this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
    this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
    this.linesAnsColumnsComputed = false;

    this.eof = false;
    this.currentToken = -1;
    this.tokenType = 0;
    this.tokenStart = start;
    this.tokenEnd = start;

    tokenLayout(this, source, start);
    this.next();
},

lookupType: function(offset) {
    offset += this.currentToken;

    if (offset < this.tokenCount) {
        return this.offsetAndType[offset] >> TYPE_OFFSET;
    }

    return NULL;
},
lookupNonWSType: function(offset) {
    offset += this.currentToken;

    for (var type; offset < this.tokenCount; offset++) {
        type = this.offsetAndType[offset] >> TYPE_OFFSET;

        if (type !== WHITESPACE$1) {
            return type;
        }
    }

    return NULL;
},
lookupValue: function(offset, referenceStr) {
    offset += this.currentToken;

    if (offset < this.tokenCount) {
        return cmpStr(
            this.source,
            this.offsetAndType[offset - 1] & OFFSET_MASK,
            this.offsetAndType[offset] & OFFSET_MASK,
            referenceStr
        );
    }

    return false;
},

getTokenValue: function() {
    return this.source.substring(this.tokenStart, this.tokenEnd);
},
substrToCursor: function(start) {
    return this.source.substring(start, this.tokenStart);
},

skipWS: function() {
    for (var i = this.currentToken, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
        if ((this.offsetAndType[i] >> TYPE_OFFSET) !== WHITESPACE$1) {
            break;
        }
    }

    if (skipTokenCount > 0) {
        this.skip(skipTokenCount);
    }
},
skip: function(tokenCount) {
    var next = this.currentToken + tokenCount;

    if (next < this.tokenCount) {
        this.currentToken = next;
        this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
        next = this.offsetAndType[next];
        this.tokenType = next >> TYPE_OFFSET;
        this.tokenEnd = next & OFFSET_MASK;
    } else {
        this.currentToken = this.tokenCount;
        this.next();
    }
},
next: function() {
    var next = this.currentToken + 1;

    if (next < this.tokenCount) {
        this.currentToken = next;
        this.tokenStart = this.tokenEnd;
        next = this.offsetAndType[next];
        this.tokenType = next >> TYPE_OFFSET;
        this.tokenEnd = next & OFFSET_MASK;
    } else {
        this.currentToken = this.tokenCount;
        this.eof = true;
        this.tokenType = NULL;
        this.tokenStart = this.tokenEnd = this.source.length;
    }
},

eat: function(tokenType) {
    if (this.tokenType !== tokenType) {
        this.error(
            NAME[tokenType] + ' is expected',
            // when test type is part of another token show error for current position + 1
            // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
            this.tokenStart + (this.source.charCodeAt(this.tokenStart) === tokenType ? 1 : 0)
        );
    }

    this.next();
},
eatNonWS: function(tokenType) {
    this.skipWS();
    this.eat(tokenType);
},

consume: function(tokenType) {
    var start = this.tokenStart;

    this.eat(tokenType);

    return this.substrToCursor(start);
},
consumeNonWS: function(tokenType) {
    this.skipWS();

    return this.consume(tokenType);
},

expectIdentifier: function(name) {
    if (this.tokenType !== IDENTIFIER || cmpStr(this.source, this.tokenStart, this.tokenEnd, name) === false) {
        this.error('Identifier `' + name + '` is expected');
    }

    this.next();
},

getLocation: function(offset, filename) {
    if (!this.linesAnsColumnsComputed) {
        computeLinesAndColumns(this, this.source);
    }

    return {
        source: filename,
        offset: this.startOffset + offset,
        line: this.lines[offset],
        column: this.columns[offset]
    };
},

getLocationRange: function(start, end, filename) {
    if (!this.linesAnsColumnsComputed) {
        computeLinesAndColumns(this, this.source);
    }

    return {
        source: filename,
        start: {
            offset: this.startOffset + start,
            line: this.lines[start],
            column: this.columns[start]
        },
        end: {
            offset: this.startOffset + end,
            line: this.lines[end],
            column: this.columns[end]
        }
    };
},

error: function(message, offset) {
    var location = typeof offset !== 'undefined' && offset < this.source.length
        ? this.getLocation(offset)
        : this.eof
            ? findLastNonSpaceLocation(this)
            : this.getLocation(this.tokenStart);

    throw new CssSyntaxError(
        message || 'Unexpected input',
        this.source,
        location.offset,
        location.line,
        location.column
    );
},

getTypes: function() {
    return Array.prototype.slice.call(this.offsetAndType, 0, this.tokenCount).map(function(item) {
        return NAME[item >> TYPE_OFFSET];
    });
}

};

// extend with error class Tokenizer$1.CssSyntaxError = CssSyntaxError;

// extend tokenizer with constants Object.keys(constants).forEach(function(key) {

Tokenizer$1[key] = constants[key];

});

// extend tokenizer with static methods from utils Object.keys(utils).forEach(function(key) {

Tokenizer$1[key] = utils[key];

});

// warm up tokenizer to elimitate code branches that never execute // fix soft deoptimizations (insufficient type feedback) new Tokenizer$1('nrrnf//“”''/*rnf*/1a;.\31t+2{url(a);+1.2e3 -.4e-5 .6e+7}').getLocation();

var Tokenizer_1 = Tokenizer$1;

var index$1 = Tokenizer_1;

// // item item item item // /——\ /——\ /——\ /——\ // | data | | data | | data | | data | // null <–+-prev |<—+-prev |<—+-prev |<—+-prev | // | next-+—>| next-+—>| next-+—>| next-+–> null // -—–/ -—–/ -—–/ -—–/ // ^ ^ // | list | // | /——\ | // -————-+-head | | // | tail-+————–/ // -—–/ //

function createItem(data) {

return {
    prev: null,
    next: null,
    data: data
};

}

var cursors = null; var List$1 = function() {

this.cursor = null;
this.head = null;
this.tail = null;

};

List$1.createItem = createItem; List$1.prototype.createItem = createItem;

List$1.prototype.getSize = function() {

var size = 0;
var cursor = this.head;

while (cursor) {
    size++;
    cursor = cursor.next;
}

return size;

};

List$1.prototype.fromArray = function(array) {

var cursor = null;

this.head = null;

for (var i = 0; i < array.length; i++) {
    var item = createItem(array[i]);

    if (cursor !== null) {
        cursor.next = item;
    } else {
        this.head = item;
    }

    item.prev = cursor;
    cursor = item;
}

this.tail = cursor;

return this;

};

List$1.prototype.toArray = function() {

var cursor = this.head;
var result = [];

while (cursor) {
    result.push(cursor.data);
    cursor = cursor.next;
}

return result;

};

List$1.prototype.toJSON = List$1.prototype.toArray;

List$1.prototype.isEmpty = function() {

return this.head === null;

};

List$1.prototype.first = function() {

return this.head && this.head.data;

};

List$1.prototype.last = function() {

return this.tail && this.tail.data;

};

function allocateCursor(node, prev, next) {

var cursor;

if (cursors !== null) {
    cursor = cursors;
    cursors = cursors.cursor;
    cursor.prev = prev;
    cursor.next = next;
    cursor.cursor = node.cursor;
} else {
    cursor = {
        prev: prev,
        next: next,
        cursor: node.cursor
    };
}

node.cursor = cursor;

return cursor;

}

function releaseCursor(node) {

var cursor = node.cursor;

node.cursor = cursor.cursor;
cursor.prev = null;
cursor.next = null;
cursor.cursor = cursors;
cursors = cursor;

}

List$1.prototype.each = function(fn, context) {

var item;

if (context === undefined) {
    context = this;
}

// push cursor
var cursor = allocateCursor(this, null, this.head);

while (cursor.next !== null) {
    item = cursor.next;
    cursor.next = item.next;

    fn.call(context, item.data, item, this);
}

// pop cursor
releaseCursor(this);

};

List$1.prototype.eachRight = function(fn, context) {

var item;

if (context === undefined) {
    context = this;
}

// push cursor
var cursor = allocateCursor(this, this.tail, null);

while (cursor.prev !== null) {
    item = cursor.prev;
    cursor.prev = item.prev;

    fn.call(context, item.data, item, this);
}

// pop cursor
releaseCursor(this);

};

List$1.prototype.nextUntil = function(start, fn, context) {

if (start === null) {
    return;
}

var item;

if (context === undefined) {
    context = this;
}

// push cursor
var cursor = allocateCursor(this, null, start);

while (cursor.next !== null) {
    item = cursor.next;
    cursor.next = item.next;

    if (fn.call(context, item.data, item, this)) {
        break;
    }
}

// pop cursor
releaseCursor(this);

};

List$1.prototype.prevUntil = function(start, fn, context) {

if (start === null) {
    return;
}

var item;

if (context === undefined) {
    context = this;
}

// push cursor
var cursor = allocateCursor(this, start, null);

while (cursor.prev !== null) {
    item = cursor.prev;
    cursor.prev = item.prev;

    if (fn.call(context, item.data, item, this)) {
        break;
    }
}

// pop cursor
releaseCursor(this);

};

List$1.prototype.some = function(fn, context) {

var cursor = this.head;

if (context === undefined) {
    context = this;
}

while (cursor !== null) {
    if (fn.call(context, cursor.data, cursor, this)) {
        return true;
    }

    cursor = cursor.next;
}

return false;

};

List$1.prototype.map = function(fn, context) {

var result = [];
var cursor = this.head;

if (context === undefined) {
    context = this;
}

while (cursor !== null) {
    result.push(fn.call(context, cursor.data, cursor, this));
    cursor = cursor.next;
}

return result;

};

List$1.prototype.clear = function() {

this.head = null;
this.tail = null;

};

List$1.prototype.copy = function() {

var result = new List$1();
var cursor = this.head;

while (cursor !== null) {
    result.insert(createItem(cursor.data));
    cursor = cursor.next;
}

return result;

};

List$1.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {

var cursor = this.cursor;

while (cursor !== null) {
    if (cursor.prev === prevOld) {
        cursor.prev = prevNew;
    }

    if (cursor.next === nextOld) {
        cursor.next = nextNew;
    }

    cursor = cursor.cursor;
}

};

List$1.prototype.append = function(item) {

// tail
//      ^
//     item
this.updateCursors(this.tail, item, null, item);

// insert to end of the list
if (this.tail !== null) {
    // if list has a tail, then it also has a head, but head doesn't change

    // last item -> new item
    this.tail.next = item;

    // last item <- new item
    item.prev = this.tail;
} else {
    // if list has no a tail, then it also has no a head
    // in this case points head to new item
    this.head = item;
}

// tail always start point to new item
this.tail = item;

return this;

};

List$1.prototype.appendData = function(data) {

return this.append(createItem(data));

};

List$1.prototype.insert = function(item, before) {

if (before !== undefined && before !== null) {
    // prev   before
    //      ^
    //     item
    this.updateCursors(before.prev, item, before, item);

    if (before.prev === null) {
        // insert to the beginning of list
        if (this.head !== before) {
            throw new Error('before doesn\'t below to list');
        }

        // since head points to before therefore list doesn't empty
        // no need to check tail
        this.head = item;
        before.prev = item;
        item.next = before;

        this.updateCursors(null, item);
    } else {

        // insert between two items
        before.prev.next = item;
        item.prev = before.prev;

        before.prev = item;
        item.next = before;
    }
} else {
    this.append(item);
}

};

List$1.prototype.remove = function(item) {

//      item
//       ^
// prev     next
this.updateCursors(item, item.prev, item, item.next);

if (item.prev !== null) {
    item.prev.next = item.next;
} else {
    if (this.head !== item) {
        throw new Error('item doesn\'t below to list');
    }

    this.head = item.next;
}

if (item.next !== null) {
    item.next.prev = item.prev;
} else {
    if (this.tail !== item) {
        throw new Error('item doesn\'t below to list');
    }

    this.tail = item.prev;
}

item.prev = null;
item.next = null;

return item;

};

List$1.prototype.appendList = function(list) {

// ignore empty lists
if (list.head === null) {
    return;
}

this.updateCursors(this.tail, list.tail, null, list.head);

// insert to end of the list
if (this.tail !== null) {
    // if destination list has a tail, then it also has a head,
    // but head doesn't change

    // dest tail -> source head
    this.tail.next = list.head;

    // dest tail <- source head
    list.head.prev = this.tail;
} else {
    // if list has no a tail, then it also has no a head
    // in this case points head to new item
    this.head = list.head;
}

// tail always start point to new item
this.tail = list.tail;

list.head = null;
list.tail = null;

};

var list = List$1;

var List = list; var cmpChar$1 = index$1.cmpChar; var TYPE$4 = index$1.TYPE;

var WHITESPACE$3 = TYPE$4.Whitespace; var IDENTIFIER$2 = TYPE$4.Identifier; var STRING$2 = TYPE$4.String; var NUMBER$2 = TYPE$4.Number; var COMMENT$3 = TYPE$4.Comment; var NUMBERSIGN = TYPE$4.NumberSign; var LEFTPARENTHESIS = TYPE$4.LeftParenthesis; var LEFTSQUAREBRACKET = TYPE$4.LeftSquareBracket; var PLUSSIGN$2 = TYPE$4.PlusSign; var HYPHENMINUS$2 = TYPE$4.HyphenMinus; var COMMA = TYPE$4.Comma; var SOLIDUS = TYPE$4.Solidus; var ASTERISK = TYPE$4.Asterisk; var PERCENTSIGN = TYPE$4.PercentSign; var FULLSTOP$2 = TYPE$4.FullStop; var COLON = TYPE$4.Colon; var GREATERTHANSIGN = TYPE$4.GreaterThanSign; var VERTICALLINE = TYPE$4.VerticalLine; var TILDE = TYPE$4.Tilde; var U = 117; // 'u'.charCodeAt(0)

var ALLOW_OF_CLAUSE = true; var DISALLOW_OF_CLAUSE = false;

function singleIdentifier() {

return new List().appendData(
    this.Identifier()
);

}

function selectorList() {

return new List().appendData(
    this.SelectorList()
);

}

function compoundSelector() {

return new List().appendData(
    this.Selector()
);

}

function nth() {

return new List().appendData(
    this.Nth(DISALLOW_OF_CLAUSE)
);

}

function nthWithOfClause() {

return new List().appendData(
    this.Nth(ALLOW_OF_CLAUSE)
);

}

function selectorSequence() {

var children = new List();
var space = null;
var child = null;
var ignoreWSAfter = false;
var ignoreWS = false;

this.readSC();

scan:
while (!this.scanner.eof) {
    switch (this.scanner.tokenType) {
        case COMMENT$3:
            this.scanner.next();
            continue;

        case WHITESPACE$3:
            if (ignoreWS) {
                this.scanner.next();
            } else {
                space = this.WhiteSpace();
            }
            continue;

        case PLUSSIGN$2:
        case GREATERTHANSIGN:
        case TILDE:
            space = null;
            ignoreWSAfter = true;
            child = this.Combinator();
            break;

        case SOLIDUS:  // /deep/
            child = this.Combinator();
            break;

        case FULLSTOP$2:
            child = this.ClassSelector();
            break;

        case LEFTSQUAREBRACKET:
            child = this.AttributeSelector();
            break;

        case NUMBERSIGN:
            child = this.IdSelector();
            break;

        case COLON:
            if (this.scanner.lookupType(1) === COLON) {
                child = this.PseudoElementSelector();
            } else {
                child = this.PseudoClassSelector();
            }

            break;

        case IDENTIFIER$2:
        case ASTERISK:
        case VERTICALLINE:
            child = this.TypeSelector();
            break;

        case NUMBER$2:
            child = this.Percentage();
            break;

        default:
            if (typeof this.readSelectorSequenceFallback === 'function') {
                child = this.readSelectorSequenceFallback();
                if (!child) {
                    break scan;
                }
            } else {
                break scan;
            }
    }

    if (space !== null) {
        children.appendData(space);
        space = null;
    }

    children.appendData(child);

    if (ignoreWSAfter) {
        ignoreWSAfter = false;
        ignoreWS = true;
    } else {
        ignoreWS = false;
    }
}

// nothing were consumed
if (child === null) {
    this.scanner.error('Selector is expected');
}

return children;

}

function defaultSequence(scope) {

var children = new List();
var space = null;
var child = null;
var ignoreWSAfter = false;
var ignoreWS = false;

this.readSC();

scan:
while (!this.scanner.eof) {
    switch (this.scanner.tokenType) {
        case COMMENT$3:
            this.scanner.next();
            continue;

        case WHITESPACE$3:
            if (ignoreWS) {
                this.scanner.next();
            } else {
                space = this.WhiteSpace();
            }
            continue;

        case NUMBERSIGN:
            child = this.HexColor();
            break;

        case COMMA:
            space = null;
            ignoreWSAfter = true;
            child = this.Operator();
            break;

        case SOLIDUS:
        case ASTERISK:
        case PLUSSIGN$2:
        case HYPHENMINUS$2:
            child = this.Operator();
            break;

        case LEFTPARENTHESIS:
            child = this.Parentheses(defaultSequence);
            break;

        case LEFTSQUAREBRACKET:
            child = this.Brackets(defaultSequence);
            break;

        case STRING$2:
            child = this.String();
            break;

        case NUMBER$2:
            switch (this.scanner.lookupType(1)) {
                case PERCENTSIGN:
                    child = this.Percentage();
                    break;

                case IDENTIFIER$2:
                    child = this.Dimension();
                    break;

                default:
                    child = this.Number();
            }

            break;

        case IDENTIFIER$2:
            // check for unicode range, it should start with u+ or U+
            if (cmpChar$1(this.scanner.source, this.scanner.tokenStart, U) &&
                cmpChar$1(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$2)) {
                child = this.UnicodeRange();
            } else if (this.scanner.lookupType(1) === LEFTPARENTHESIS) {
                if (this.scanner.lookupValue(0, 'url')) {
                    child = this.Url();
                } else {
                    child = this.Function(scope, defaultSequence);
                }
            } else {
                child = this.Identifier();
            }

            break;

        default:
            if (typeof this.readSequenceFallback === 'function') {
                child = this.readSequenceFallback();
                if (!child) {
                    break scan;
                }
            } else {
                break scan;
            }
    }

    if (space !== null) {
        children.appendData(space);
        space = null;
    }

    children.appendData(child);

    if (ignoreWSAfter) {
        ignoreWSAfter = false;
        ignoreWS = true;
    } else {
        ignoreWS = false;
    }
}

return children;

}

var sequence$1 = {

singleIdentifier: singleIdentifier,
selectorList: selectorList,
compoundSelector: compoundSelector,
nth: nth,
nthWithOfClause: nthWithOfClause,
selector: selectorSequence,
default: defaultSequence

};

var cmpChar$2 = index$1.cmpChar; var isNumber$2 = index$1.isNumber; var TYPE$5 = index$1.TYPE;

var IDENTIFIER$3 = TYPE$5.Identifier; var NUMBER$3 = TYPE$5.Number; var PLUSSIGN$3 = TYPE$5.PlusSign; var HYPHENMINUS$3 = TYPE$5.HyphenMinus; var N$3 = 110; // 'n'.charCodeAt(0) var DISALLOW_SIGN = true; var ALLOW_SIGN = false;

function checkTokenIsInteger(scanner, disallowSign) {

var pos = scanner.tokenStart;

if (scanner.source.charCodeAt(pos) === PLUSSIGN$3 ||
    scanner.source.charCodeAt(pos) === HYPHENMINUS$3) {
    if (disallowSign) {
        scanner.error();
    }
    pos++;
}

for (; pos < scanner.tokenEnd; pos++) {
    if (!isNumber$2(scanner.source.charCodeAt(pos))) {
        scanner.error('Unexpected input', pos);
    }
}

}

// An+B microsyntax www.w3.org/TR/css-syntax-3/#anb var AnPlusB = function AnPlusB() {

var start = this.scanner.tokenStart;
var end = start;
var prefix = '';
var a = null;
var b = null;

if (this.scanner.tokenType === NUMBER$3 ||
    this.scanner.tokenType === PLUSSIGN$3) {
    checkTokenIsInteger(this.scanner, ALLOW_SIGN);
    prefix = this.scanner.getTokenValue();
    this.scanner.next();
    end = this.scanner.tokenStart;
}

if (this.scanner.tokenType === IDENTIFIER$3) {
    var bStart = this.scanner.tokenStart;

    if (cmpChar$2(this.scanner.source, bStart, HYPHENMINUS$3)) {
        if (prefix === '') {
            prefix = '-';
            bStart++;
        } else {
            this.scanner.error('Unexpected hyphen minus');
        }
    }

    if (!cmpChar$2(this.scanner.source, bStart, N$3)) {
        this.scanner.error();
    }

    a = prefix === ''  ? '1'  :
        prefix === '+' ? '+1' :
        prefix === '-' ? '-1' :
        prefix;

    var len = this.scanner.tokenEnd - bStart;
    if (len > 1) {
        // ..n-..
        if (this.scanner.source.charCodeAt(bStart + 1) !== HYPHENMINUS$3) {
            this.scanner.error('Unexpected input', bStart + 1);
        }

        if (len > 2) {
            // ..n-{number}..
            this.scanner.tokenStart = bStart + 2;
        } else {
            // ..n- {number}
            this.scanner.next();
            this.readSC();
        }

        checkTokenIsInteger(this.scanner, DISALLOW_SIGN);
        b = '-' + this.scanner.getTokenValue();
        this.scanner.next();
        end = this.scanner.tokenStart;
    } else {
        prefix = '';
        this.scanner.next();
        end = this.scanner.tokenStart;
        this.readSC();

        if (this.scanner.tokenType === HYPHENMINUS$3 ||
            this.scanner.tokenType === PLUSSIGN$3) {
            prefix = this.scanner.getTokenValue();
            this.scanner.next();
            this.readSC();
        }

        if (this.scanner.tokenType === NUMBER$3) {
            checkTokenIsInteger(this.scanner, prefix !== '');

            if (!isNumber$2(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
                prefix = this.scanner.source.charAt(this.scanner.tokenStart);
                this.scanner.tokenStart++;
            }

            if (prefix === '') {
                // should be an operator before number
                this.scanner.error();
            } else if (prefix === '+') {
                // plus is using by default
                prefix = '';
            }

            b = prefix + this.scanner.getTokenValue();

            this.scanner.next();
            end = this.scanner.tokenStart;
        } else {
            if (prefix) {
                this.scanner.eat(NUMBER$3);
            }
        }
    }
} else {
    if (prefix === '' || prefix === '+') { // no number
        this.scanner.error(
            'Number or identifier is expected',
            this.scanner.tokenStart + (
                this.scanner.tokenType === PLUSSIGN$3 ||
                this.scanner.tokenType === HYPHENMINUS$3
            )
        );
    }

    b = prefix;
}

return {
    type: 'AnPlusB',
    loc: this.getLocation(start, end),
    a: a,
    b: b
};

};

var TYPE$6 = index$1.TYPE;

var IDENTIFIER$4 = TYPE$6.Identifier; var SEMICOLON = TYPE$6.Semicolon; var COMMERCIALAT = TYPE$6.CommercialAt; var LEFTCURLYBRACKET = TYPE$6.LeftCurlyBracket; var RIGHTCURLYBRACKET = TYPE$6.RightCurlyBracket; var BALANCED = true;

function isBlockAtrule() {

for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
    if (type === RIGHTCURLYBRACKET) {
        return true;
    }

    if (type === LEFTCURLYBRACKET ||
        type === COMMERCIALAT) {
        return false;
    }
}

this.scanner.skip(offset);
this.scanner.eat(RIGHTCURLYBRACKET);

}

var Atrule = function Atrule() {

var start = this.scanner.tokenStart;
var name;
var nameLowerCase;
var expression = null;
var block = null;

this.scanner.eat(COMMERCIALAT);

name = this.scanner.consume(IDENTIFIER$4);
nameLowerCase = name.toLowerCase();
this.readSC();

if (this.parseAtruleExpression) {
    expression = this.AtruleExpression(name);
    this.readSC();
} else {
    expression = this.Raw(BALANCED, SEMICOLON, LEFTCURLYBRACKET);
}

if (this.atrule.hasOwnProperty(nameLowerCase)) {
    if (typeof this.atrule[nameLowerCase].block === 'function') {
        if (this.scanner.tokenType !== LEFTCURLYBRACKET) {
            this.scanner.error('Curly bracket is expected');
        }

        block = this.atrule[nameLowerCase].block.call(this);
    } else {
        this.scanner.eat(SEMICOLON);
    }
} else {
    switch (this.scanner.tokenType) {
        case SEMICOLON:
            this.scanner.next();
            break;

        case LEFTCURLYBRACKET:
            block = this.Block(isBlockAtrule.call(this) ? this.Declaration : this.Rule);
            break;

        default:
            this.scanner.error('Semicolon or block is expected');
    }
}

return {
    type: 'Atrule',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: name,
    expression: expression,
    block: block
};

};

var List$2 = list;

var AtruleExpression = function AtruleExpression(name) {

var children = null;

if (name !== null) {
    name = name.toLowerCase();
}

// custom consumer
if (this.atrule.hasOwnProperty(name)) {
    if (typeof this.atrule[name].expression === 'function') {
        children = this.atrule[name].expression.call(this);

        if (children instanceof List$2 === false) {
            return children;
        }
    }
} else {
    // default consumer
    this.readSC();
    children = this.readSequence(this.scopeAtruleExpression);
}

if (children === null || children.isEmpty()) {
    return null;
}

return {
    type: 'AtruleExpression',
    loc: this.getLocationFromList(children),
    children: children
};

};

var TYPE$7 = index$1.TYPE;

var IDENTIFIER$5 = TYPE$7.Identifier; var STRING$3 = TYPE$7.String; var DOLLARSIGN = TYPE$7.DollarSign; var ASTERISK$1 = TYPE$7.Asterisk; var COLON$1 = TYPE$7.Colon; var EQUALSSIGN = TYPE$7.EqualsSign; var LEFTSQUAREBRACKET$1 = TYPE$7.LeftSquareBracket; var RIGHTSQUAREBRACKET = TYPE$7.RightSquareBracket; var CIRCUMFLEXACCENT = TYPE$7.CircumflexAccent; var VERTICALLINE$1 = TYPE$7.VerticalLine; var TILDE$1 = TYPE$7.Tilde;

function getAttributeName() {

if (this.scanner.eof) {
    this.scanner.error('Unexpected end of input');
}

var start = this.scanner.tokenStart;
var expectIdentifier = false;
var checkColon = true;

if (this.scanner.tokenType === ASTERISK$1) {
    expectIdentifier = true;
    checkColon = false;
    this.scanner.next();
} else if (this.scanner.tokenType !== VERTICALLINE$1) {
    this.scanner.eat(IDENTIFIER$5);
}

if (this.scanner.tokenType === VERTICALLINE$1) {
    if (this.scanner.lookupType(1) !== EQUALSSIGN) {
        this.scanner.next();
        this.scanner.eat(IDENTIFIER$5);
    } else if (expectIdentifier) {
        this.scanner.error('Identifier is expected', this.scanner.tokenEnd);
    }
} else if (expectIdentifier) {
    this.scanner.error('Vertical line is expected');
}

if (checkColon && this.scanner.tokenType === COLON$1) {
    this.scanner.next();
    this.scanner.eat(IDENTIFIER$5);
}

return {
    type: 'Identifier',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: this.scanner.substrToCursor(start)
};

}

function getOperator$1() {

var start = this.scanner.tokenStart;
var tokenType = this.scanner.tokenType;

if (tokenType !== EQUALSSIGN &&        // =
    tokenType !== TILDE$1 &&             // ~=
    tokenType !== CIRCUMFLEXACCENT &&  // ^=
    tokenType !== DOLLARSIGN &&        // $=
    tokenType !== ASTERISK$1 &&          // *=
    tokenType !== VERTICALLINE$1         // |=
) {
    this.scanner.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
}

if (tokenType === EQUALSSIGN) {
    this.scanner.next();
} else {
    this.scanner.next();
    this.scanner.eat(EQUALSSIGN);
}

return this.scanner.substrToCursor(start);

}

// '[' S* attrib_name ']' // '[' S* attrib_name S* attrib_match S* [ IDENT | STRING ] S* attrib_flags? S* ']' var AttributeSelector = function AttributeSelector() {

var start = this.scanner.tokenStart;
var name;
var operator = null;
var value = null;
var flags = null;

this.scanner.eat(LEFTSQUAREBRACKET$1);
this.readSC();

name = getAttributeName.call(this);
this.readSC();

if (this.scanner.tokenType !== RIGHTSQUAREBRACKET) {
    // avoid case `[name i]`
    if (this.scanner.tokenType !== IDENTIFIER$5) {
        operator = getOperator$1.call(this);

        this.readSC();

        value = this.scanner.tokenType === STRING$3
            ? this.String()
            : this.Identifier();

        this.readSC();
    }

    // attribute flags
    if (this.scanner.tokenType === IDENTIFIER$5) {
        flags = this.scanner.getTokenValue();
        this.scanner.next();

        this.readSC();
    }
}

this.scanner.eat(RIGHTSQUAREBRACKET);

return {
    type: 'AttributeSelector',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: name,
    operator: operator,
    value: value,
    flags: flags
};

};

var List$3 = list; var TYPE$8 = index$1.TYPE;

var WHITESPACE$4 = TYPE$8.Whitespace; var COMMENT$4 = TYPE$8.Comment; var SEMICOLON$1 = TYPE$8.Semicolon; var COMMERCIALAT$1 = TYPE$8.CommercialAt; var LEFTCURLYBRACKET$1 = TYPE$8.LeftCurlyBracket; var RIGHTCURLYBRACKET$1 = TYPE$8.RightCurlyBracket;

var Block = function Block(defaultConsumer) {

defaultConsumer = defaultConsumer || this.Declaration;

var start = this.scanner.tokenStart;
var children = new List$3();

this.scanner.eat(LEFTCURLYBRACKET$1);

scan:
while (!this.scanner.eof) {
    switch (this.scanner.tokenType) {
        case RIGHTCURLYBRACKET$1:
            break scan;

        case WHITESPACE$4:
        case COMMENT$4:
        case SEMICOLON$1:
            this.scanner.next();
            break;

        case COMMERCIALAT$1:
            children.appendData(this.Atrule());
            break;

        default:
            children.appendData(defaultConsumer.call(this));
    }
}

this.scanner.eat(RIGHTCURLYBRACKET$1);

return {
    type: 'Block',
    loc: this.getLocation(start, this.scanner.tokenStart),
    children: children
};

};

var TYPE$9 = index$1.TYPE; var LEFTSQUAREBRACKET$2 = TYPE$9.LeftSquareBracket; var RIGHTSQUAREBRACKET$1 = TYPE$9.RightSquareBracket;

// currently only Grid Layout uses square brackets, but left it universal // drafts.csswg.org/css-grid/#track-sizing // [ ident* ] var Brackets = function Brackets(readSequence) {

var start = this.scanner.tokenStart;
var children = null;

this.scanner.eat(LEFTSQUAREBRACKET$2);
children = readSequence.call(this);
this.scanner.eat(RIGHTSQUAREBRACKET$1);

return {
    type: 'Brackets',
    loc: this.getLocation(start, this.scanner.tokenStart),
    children: children
};

};

var TYPE$10 = index$1.TYPE; var IDENTIFIER$6 = TYPE$10.Identifier; var FULLSTOP$3 = TYPE$10.FullStop;

// '.' ident var ClassSelector = function ClassSelector() {

this.scanner.eat(FULLSTOP$3);

return {
    type: 'ClassSelector',
    loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
    name: this.scanner.consume(IDENTIFIER$6)
};

};

var TYPE$11 = index$1.TYPE;

var PLUSSIGN$4 = TYPE$11.PlusSign; var SOLIDUS$1 = TYPE$11.Solidus; var GREATERTHANSIGN$1 = TYPE$11.GreaterThanSign; var TILDE$2 = TYPE$11.Tilde;

// + | > | ~ | /deep/ var Combinator = function Combinator() {

var start = this.scanner.tokenStart;

switch (this.scanner.tokenType) {
    case GREATERTHANSIGN$1:
    case PLUSSIGN$4:
    case TILDE$2:
        this.scanner.next();
        break;

    case SOLIDUS$1:
        this.scanner.next();
        this.scanner.expectIdentifier('deep');
        this.scanner.eat(SOLIDUS$1);
        break;

    default:
        this.scanner.error('Combinator is expected');
}

return {
    type: 'Combinator',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: this.scanner.substrToCursor(start)
};

};

var TYPE$12 = index$1.TYPE;

var ASTERISK$2 = TYPE$12.Asterisk; var SOLIDUS$2 = TYPE$12.Solidus;

// '/*' .* '*/' var Comment = function Comment() {

var start = this.scanner.tokenStart;
var end = this.scanner.tokenEnd;

if ((end - start + 2) >= 2 &&
    this.scanner.source.charCodeAt(end - 2) === ASTERISK$2 &&
    this.scanner.source.charCodeAt(end - 1) === SOLIDUS$2) {
    end -= 2;
}

this.scanner.next();

return {
    type: 'Comment',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: this.scanner.source.substring(start + 2, end)
};

};

var TYPE$13 = index$1.TYPE;

var IDENTIFIER$7 = TYPE$13.Identifier; var COLON$2 = TYPE$13.Colon; var EXCLAMATIONMARK = TYPE$13.ExclamationMark; var SOLIDUS$3 = TYPE$13.Solidus; var ASTERISK$3 = TYPE$13.Asterisk; var DOLLARSIGN$1 = TYPE$13.DollarSign; var HYPHENMINUS$4 = TYPE$13.HyphenMinus; var SEMICOLON$2 = TYPE$13.Semicolon; var RIGHTCURLYBRACKET$2 = TYPE$13.RightCurlyBracket; var RIGHTPARENTHESIS = TYPE$13.RightParenthesis; var BALANCED$1 = true;

function readProperty() {

var start = this.scanner.tokenStart;
var prefix = 0;

// hacks
switch (this.scanner.tokenType) {
    case ASTERISK$3:
    case DOLLARSIGN$1:
        prefix = 1;
        break;

    // TODO: not sure we should support this hack
    case SOLIDUS$3:
        prefix = this.scanner.lookupType(1) === SOLIDUS$3 ? 2 : 1;
        break;
}

if (this.scanner.lookupType(prefix) === HYPHENMINUS$4) {
    prefix++;
}

if (prefix) {
    this.scanner.skip(prefix);
}

this.scanner.eat(IDENTIFIER$7);

return this.scanner.substrToCursor(start);

}

// ! ws* important function getImportant() {

this.scanner.eat(EXCLAMATIONMARK);
this.readSC();

this.scanner.expectIdentifier('important');

// should return identifier in future for original source restoring as is
// returns true for now since it's fit to optimizer purposes
return true;

}

function isCustomProperty(name) {

return name.length >= 2 &&
       name.charCodeAt(0) === HYPHENMINUS$4 &&
       name.charCodeAt(1) === HYPHENMINUS$4;

}

var Declaration = function Declaration() {

var start = this.scanner.tokenStart;
var property = readProperty.call(this);
var important = false;
var value;

this.readSC();
this.scanner.eat(COLON$2);

if (isCustomProperty(property) ? this.parseCustomProperty : this.parseValue) {
    value = this.Value(property);
} else {
    value = this.Raw(BALANCED$1, SEMICOLON$2, EXCLAMATIONMARK);
}

if (this.scanner.tokenType === EXCLAMATIONMARK) {
    important = getImportant.call(this);
    this.readSC();
}

// TODO: include or not to include semicolon to range?
// if (this.scanner.tokenType === SEMICOLON) {
//     this.scanner.next();
// }

if (!this.scanner.eof &&
    this.scanner.tokenType !== SEMICOLON$2 &&
    this.scanner.tokenType !== RIGHTPARENTHESIS &&
    this.scanner.tokenType !== RIGHTCURLYBRACKET$2) {
    this.scanner.error();
}

return {
    type: 'Declaration',
    loc: this.getLocation(start, this.scanner.tokenStart),
    important: important,
    property: property,
    value: value
};

};

var List$4 = list; var TYPE$14 = index$1.TYPE;

var WHITESPACE$5 = TYPE$14.Whitespace; var COMMENT$5 = TYPE$14.Comment; var SEMICOLON$3 = TYPE$14.Semicolon;

var DeclarationList = function DeclarationList() {

var children = new List$4();

scan:
while (!this.scanner.eof) {
    switch (this.scanner.tokenType) {
        case WHITESPACE$5:
        case COMMENT$5:
        case SEMICOLON$3:
            this.scanner.next();
            break;

        default:
            children.appendData(this.Declaration());
    }
}

return {
    type: 'DeclarationList',
    loc: this.getLocationFromList(children),
    children: children
};

};

var NUMBER$4 = index$1.TYPE.Number;

// special reader for units to avoid adjoined IE hacks (i.e. '1px9') function readUnit(scanner) {

var unit = scanner.getTokenValue();
var backSlashPos = unit.indexOf('\\');

if (backSlashPos !== -1) {
    // patch token offset
    scanner.tokenStart += backSlashPos;

    // return part before backslash
    return unit.substring(0, backSlashPos);
}

// no backslash in unit name
scanner.next();

return unit;

}

// number ident var Dimention = function Dimension() {

var start = this.scanner.tokenStart;
var value = this.scanner.consume(NUMBER$4);
var unit = readUnit(this.scanner);

return {
    type: 'Dimension',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: value,
    unit: unit
};

};

var TYPE$15 = index$1.TYPE;

var IDENTIFIER$8 = TYPE$15.Identifier; var LEFTPARENTHESIS$1 = TYPE$15.LeftParenthesis; var RIGHTPARENTHESIS$1 = TYPE$15.RightParenthesis;

// ident '(' <sequence> ')' var _Function = function Function(scope, readSequence) {

var start = this.scanner.tokenStart;
var name = this.scanner.consume(IDENTIFIER$8);
var nameLowerCase = name.toLowerCase();
var children;

this.scanner.eat(LEFTPARENTHESIS$1);

children = scope.hasOwnProperty(nameLowerCase)
    ? scope[nameLowerCase].call(this, scope, start, readSequence)
    : readSequence.call(this, scope);

this.scanner.eat(RIGHTPARENTHESIS$1);

return {
    type: 'Function',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: name,
    children: children
};

};

var isNumber$3 = index$1.isNumber; var TYPE$16 = index$1.TYPE;

var IDENTIFIER$9 = TYPE$16.Identifier; var NUMBER$5 = TYPE$16.Number; var NUMBERSIGN$1 = TYPE$16.NumberSign; var PLUSSIGN$5 = TYPE$16.PlusSign; var HYPHENMINUS$5 = TYPE$16.HyphenMinus; var FULLSTOP$4 = TYPE$16.FullStop;

// # ident var HexColor = function HexColor() {

var start = this.scanner.tokenStart;

this.scanner.eat(NUMBERSIGN$1);

scan:
switch (this.scanner.tokenType) {
    case NUMBER$5:
        if (!isNumber$3(this.scanner.source.charCodeAt(this.scanner.tokenStart))) {
            this.scanner.error('Unexpected input', this.scanner.tokenStart);
        }

        for (var pos = this.scanner.tokenStart + 1; pos < this.scanner.tokenEnd; pos++) {
            var code = this.scanner.source.charCodeAt(pos);

            // break on fullstop or hyperminus/plussign after exponent
            if (code === FULLSTOP$4 || code === HYPHENMINUS$5 || code === PLUSSIGN$5) {
                // break token, exclude symbol
                this.scanner.tokenStart = pos;
                break scan;
            }
        }

        // number contains digits only, go to next token
        this.scanner.next();

        // if next token is identifier add it to result
        // TODO: consume hex only
        if (this.scanner.tokenType === IDENTIFIER$9) {
            this.scanner.next();
        }

        break;

    case IDENTIFIER$9:
        // TODO: consume hex only
        this.scanner.next(); // add token to result
        break;

    default:
        this.scanner.error('Number or identifier is expected');
}

return {
    type: 'HexColor',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: this.scanner.substrToCursor(start + 1) // skip #
};

};

var TYPE$17 = index$1.TYPE; var IDENTIFIER$10 = TYPE$17.Identifier;

var Identifier = function Identifier() {

return {
    type: 'Identifier',
    loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
    name: this.scanner.consume(IDENTIFIER$10)
};

};

var TYPE$18 = index$1.TYPE; var IDENTIFIER$11 = TYPE$18.Identifier; var NUMBERSIGN$2 = TYPE$18.NumberSign;

// '#' ident var IdSelector = function IdSelector() {

this.scanner.eat(NUMBERSIGN$2);

return {
    type: 'IdSelector',
    loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
    name: this.scanner.consume(IDENTIFIER$11)
};

};

var TYPE$19 = index$1.TYPE;

var IDENTIFIER$12 = TYPE$19.Identifier; var NUMBER$6 = TYPE$19.Number; var LEFTPARENTHESIS$2 = TYPE$19.LeftParenthesis; var RIGHTPARENTHESIS$2 = TYPE$19.RightParenthesis; var COLON$3 = TYPE$19.Colon; var SOLIDUS$4 = TYPE$19.Solidus;

var MediaFeature = function MediaFeature() {

var start = this.scanner.tokenStart;
var name;
var value = null;

this.scanner.eat(LEFTPARENTHESIS$2);
this.readSC();

name = this.scanner.consume(IDENTIFIER$12);
this.readSC();

if (this.scanner.tokenType !== RIGHTPARENTHESIS$2) {
    this.scanner.eat(COLON$3);
    this.readSC();

    switch (this.scanner.tokenType) {
        case NUMBER$6:
            if (this.scanner.lookupType(1) === IDENTIFIER$12) {
                value = this.Dimension();
            } else if (this.scanner.lookupNonWSType(1) === SOLIDUS$4) {
                value = this.Ratio();
            } else {
                value = this.Number();
            }

            break;

        case IDENTIFIER$12:
            value = this.Identifier();

            break;

        default:
            this.scanner.error('Number, dimension, ratio or identifier is expected');
    }

    this.readSC();
}

this.scanner.eat(RIGHTPARENTHESIS$2);

return {
    type: 'MediaFeature',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: name,
    value: value
};

};

var List$5 = list; var TYPE$20 = index$1.TYPE;

var WHITESPACE$6 = TYPE$20.Whitespace; var COMMENT$6 = TYPE$20.Comment; var IDENTIFIER$13 = TYPE$20.Identifier; var LEFTPARENTHESIS$3 = TYPE$20.LeftParenthesis;

var MediaQuery = function MediaQuery() {

this.readSC();

var children = new List$5();
var child = null;
var space = null;

scan:
while (!this.scanner.eof) {
    switch (this.scanner.tokenType) {
        case COMMENT$6:
            this.scanner.next();
            continue;

        case WHITESPACE$6:
            space = this.WhiteSpace();
            continue;

        case IDENTIFIER$13:
            child = this.Identifier();
            break;

        case LEFTPARENTHESIS$3:
            child = this.MediaFeature();
            break;

        default:
            break scan;
    }

    if (space !== null) {
        children.appendData(space);
        space = null;
    }

    children.appendData(child);
}

if (child === null) {
    this.scanner.error('Identifier or parenthesis is expected');
}

return {
    type: 'MediaQuery',
    loc: this.getLocationFromList(children),
    children: children
};

};

var List$6 = list; var COMMA$1 = index$1.TYPE.Comma;

var MediaQueryList = function MediaQueryList(relative) {

var children = new List$6();

this.readSC();

while (!this.scanner.eof) {
    children.appendData(this.MediaQuery(relative));

    if (this.scanner.tokenType !== COMMA$1) {
        break;
    }

    this.scanner.next();
}

return {
    type: 'MediaQueryList',
    loc: this.getLocationFromList(children),
    children: children
};

};

// drafts.csswg.org/css-syntax-3/#the-anb-type var Nth = function Nth(allowOfClause) {

this.readSC();

var start = this.scanner.tokenStart;
var end = start;
var selector = null;
var query;

if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
    query = this.Identifier();
} else {
    query = this.AnPlusB();
}

this.readSC();

if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
    this.scanner.next();

    selector = this.SelectorList();

    if (this.needPositions) {
        end = selector.children.last().loc.end.offset;
    }
} else {
    if (this.needPositions) {
        end = query.loc.end.offset;
    }
}

return {
    type: 'Nth',
    loc: this.getLocation(start, end),
    nth: query,
    selector: selector
};

};

var NUMBER$7 = index$1.TYPE.Number;

var _Number = function Number() {

return {
    type: 'Number',
    loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
    value: this.scanner.consume(NUMBER$7)
};

};

// '/' | '*' | ',' | ':' | '+' | '-' var Operator = function Operator() {

var start = this.scanner.tokenStart;

this.scanner.next();

return {
    type: 'Operator',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: this.scanner.substrToCursor(start)
};

};

var TYPE$21 = index$1.TYPE; var LEFTPARENTHESIS$4 = TYPE$21.LeftParenthesis; var RIGHTPARENTHESIS$3 = TYPE$21.RightParenthesis;

var Parentheses = function Parentheses(readSequence) {

var start = this.scanner.tokenStart;
var children = null;

this.scanner.eat(LEFTPARENTHESIS$4);
children = readSequence.call(this);
this.scanner.eat(RIGHTPARENTHESIS$3);

return {
    type: 'Parentheses',
    loc: this.getLocation(start, this.scanner.tokenStart),
    children: children
};

};

var TYPE$22 = index$1.TYPE;

var NUMBER$8 = TYPE$22.Number; var PERCENTSIGN$1 = TYPE$22.PercentSign;

var Percentage = function Percentage() {

var start = this.scanner.tokenStart;
var number = this.scanner.consume(NUMBER$8);

this.scanner.eat(PERCENTSIGN$1);

return {
    type: 'Percentage',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: number
};

};

var List$7 = list; var TYPE$23 = index$1.TYPE;

var IDENTIFIER$14 = TYPE$23.Identifier; var COLON$4 = TYPE$23.Colon; var LEFTPARENTHESIS$5 = TYPE$23.LeftParenthesis; var RIGHTPARENTHESIS$4 = TYPE$23.RightParenthesis; var BALANCED$2 = true;

// : ident [ '(' .. ')' ]? var PseudoClassSelector = function PseudoClassSelector() {

var start = this.scanner.tokenStart;
var name;
var children = null;

this.scanner.eat(COLON$4);

name = this.scanner.consume(IDENTIFIER$14);

if (this.scanner.tokenType === LEFTPARENTHESIS$5) {
    var nameLowerCase = name.toLowerCase();

    this.scanner.next();

    if (this.pseudo.hasOwnProperty(nameLowerCase)) {
        this.readSC();
        children = this.pseudo[nameLowerCase].call(this);
        this.readSC();
    } else {
        children = new List$7().appendData(this.Raw(BALANCED$2, 0, 0));
    }

    this.scanner.eat(RIGHTPARENTHESIS$4);
}

return {
    type: 'PseudoClassSelector',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: name,
    children: children
};

};

var List$8 = list; var TYPE$24 = index$1.TYPE;

var IDENTIFIER$15 = TYPE$24.Identifier; var COLON$5 = TYPE$24.Colon; var LEFTPARENTHESIS$6 = TYPE$24.LeftParenthesis; var RIGHTPARENTHESIS$5 = TYPE$24.RightParenthesis; var BALANCED$3 = true;

//

ident [ '(' .. ')' ]?

var PseudoElementSelector = function PseudoElementSelector() {

var start = this.scanner.tokenStart;
var name;
var children = null;

this.scanner.eat(COLON$5);
this.scanner.eat(COLON$5);

name = this.scanner.consume(IDENTIFIER$15);

if (this.scanner.tokenType === LEFTPARENTHESIS$6) {
    var nameLowerCase = name.toLowerCase();

    this.scanner.next();

    if (this.pseudo.hasOwnProperty(nameLowerCase)) {
        this.readSC();
        children = this.pseudo[nameLowerCase].call(this);
        this.readSC();
    } else {
        children = new List$8().appendData(this.Raw(BALANCED$3, 0, 0));
    }

    this.scanner.eat(RIGHTPARENTHESIS$5);
}

return {
    type: 'PseudoElementSelector',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: name,
    children: children
};

};

var isNumber$4 = index$1.isNumber; var TYPE$25 = index$1.TYPE; var NUMBER$9 = TYPE$25.Number; var SOLIDUS$5 = TYPE$25.Solidus;

function readPositiveInteger(scanner) {

var value = scanner.consumeNonWS(NUMBER$9);

for (var i = 0; i < value.length; i++) {
    if (!isNumber$4(value.charCodeAt(i))) {
        scanner.error('Positive integer is expected', scanner.tokenStart - value.length + i);
    }
}

return value;

}

// <positive-integer> S* '/' S* <positive-integer> var Ratio = function Ratio() {

var start = this.scanner.tokenStart;
var left = readPositiveInteger(this.scanner);
var right;

this.scanner.eatNonWS(SOLIDUS$5);
right = readPositiveInteger(this.scanner);

return {
    type: 'Ratio',
    loc: this.getLocation(start, this.scanner.tokenStart),
    left: left,
    right: right
};

};

var TYPE$26 = index$1.TYPE;

var WHITESPACE$7 = TYPE$26.Whitespace; var LEFTPARENTHESIS$7 = TYPE$26.LeftParenthesis; var RIGHTPARENTHESIS$6 = TYPE$26.RightParenthesis; var LEFTCURLYBRACKET$2 = TYPE$26.LeftCurlyBracket; var RIGHTCURLYBRACKET$3 = TYPE$26.RightCurlyBracket; var LEFTSQUAREBRACKET$3 = TYPE$26.LeftSquareBracket; var RIGHTSQUAREBRACKET$2 = TYPE$26.RightSquareBracket;

var Raw = function Raw(balanced, endTokenType1, endTokenType2) {

var start = this.scanner.tokenStart;
var stack = [];
var popType = 0;
var type = 0;

if (balanced) {
    scan:
    for (var i = 0; type = this.scanner.lookupType(i); i++) {
        if (popType === 0) {
            if (type === endTokenType1 ||
                type === endTokenType2) {
                break scan;
            }
        }

        switch (type) {
            case popType:
                popType = stack.pop();
                break;

            case RIGHTPARENTHESIS$6:
            case RIGHTCURLYBRACKET$3:
            case RIGHTSQUAREBRACKET$2:
                if (popType !== 0) {
                    this.scanner.skip(i);
                    this.scanner.error();
                }
                break scan;

            case LEFTPARENTHESIS$7:
                stack.push(popType);
                popType = RIGHTPARENTHESIS$6;
                break;

            case LEFTCURLYBRACKET$2:
                stack.push(popType);
                popType = RIGHTCURLYBRACKET$3;
                break;

            case LEFTSQUAREBRACKET$3:
                stack.push(popType);
                popType = RIGHTSQUAREBRACKET$2;
                break;
        }
    }
} else {
    for (var i = 0; type = this.scanner.lookupType(i); i++) {
        if (type === WHITESPACE$7 ||
            type === endTokenType1 ||
            type === endTokenType2) {
            break;
        }
    }
}

this.scanner.skip(i);

if (popType !== 0) {
    this.scanner.eat(popType);
}

return {
    type: 'Raw',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: this.scanner.substrToCursor(start)
};

};

var TYPE$27 = index$1.TYPE; var LEFTCURLYBRACKET$3 = TYPE$27.LeftCurlyBracket; var BALANCED$4 = true;

var Rule = function Rule() {

var start = this.scanner.tokenStart;
var selector = this.parseSelector ? this.SelectorList() : this.Raw(BALANCED$4, LEFTCURLYBRACKET$3, 0);
var block = this.Block(this.Declaration);

return {
    type: 'Rule',
    loc: this.getLocation(start, this.scanner.tokenStart),
    selector: selector,
    block: block
};

};

var Selector = function Selector() {

var children = this.readSelectorSequence();

return {
    type: 'Selector',
    loc: this.getLocationFromList(children),
    children: children
};

};

var List$9 = list; var TYPE$28 = index$1.TYPE;

var COMMA$2 = TYPE$28.Comma; var LEFTCURLYBRACKET$4 = TYPE$28.LeftCurlyBracket; var BALANCED$5 = true;

var SelectorList = function SelectorList() {

var children = new List$9();

while (!this.scanner.eof) {
    children.appendData(this.parseSelector
        ? this.Selector()
        : this.Raw(BALANCED$5, COMMA$2, LEFTCURLYBRACKET$4)
    );

    if (this.scanner.tokenType === COMMA$2) {
        this.scanner.next();
        continue;
    }

    break;
}

return {
    type: 'SelectorList',
    loc: this.getLocationFromList(children),
    children: children
};

};

var STRING$4 = index$1.TYPE.String;

var _String = function String() {

return {
    type: 'String',
    loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
    value: this.scanner.consume(STRING$4)
};

};

var List$10 = list; var TYPE$29 = index$1.TYPE;

var WHITESPACE$8 = TYPE$29.Whitespace; var COMMENT$7 = TYPE$29.Comment; var EXCLAMATIONMARK$1 = TYPE$29.ExclamationMark; var COMMERCIALAT$2 = TYPE$29.CommercialAt;

var StyleSheet = function StyleSheet() {

var start = this.scanner.tokenStart;
var children = new List$10();
var child;

scan:
while (!this.scanner.eof) {
    switch (this.scanner.tokenType) {
        case WHITESPACE$8:
            this.scanner.next();
            continue;

        case COMMENT$7:
            // ignore comments except exclamation comments (i.e. /*! .. */) on top level
            if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$1) {
                this.scanner.next();
                continue;
            }

            child = this.Comment();
            break;

        case COMMERCIALAT$2:
            child = this.Atrule();
            break;

        default:
            child = this.Rule();
    }

    children.appendData(child);
}

return {
    type: 'StyleSheet',
    loc: this.getLocation(start, this.scanner.tokenStart),
    children: children
};

};

var TYPE$30 = index$1.TYPE;

var IDENTIFIER$16 = TYPE$30.Identifier; var ASTERISK$4 = TYPE$30.Asterisk; var VERTICALLINE$2 = TYPE$30.VerticalLine;

function eatIdentifierOrAsterisk() {

if (this.scanner.tokenType !== IDENTIFIER$16 &&
    this.scanner.tokenType !== ASTERISK$4) {
    this.scanner.error('Identifier or asterisk is expected');
}

this.scanner.next();

}

// ident // ident|ident // ident|* // * // *|ident // *|* // |ident // |* var TypeSelector = function TypeSelector() {

var start = this.scanner.tokenStart;

if (this.scanner.tokenType === VERTICALLINE$2) {
    this.scanner.next();
    eatIdentifierOrAsterisk.call(this);
} else {
    eatIdentifierOrAsterisk.call(this);

    if (this.scanner.tokenType === VERTICALLINE$2) {
        this.scanner.next();
        eatIdentifierOrAsterisk.call(this);
    }
}

return {
    type: 'TypeSelector',
    loc: this.getLocation(start, this.scanner.tokenStart),
    name: this.scanner.substrToCursor(start)
};

};

var isHex$1 = index$1.isHex; var TYPE$31 = index$1.TYPE;

var IDENTIFIER$17 = TYPE$31.Identifier; var NUMBER$10 = TYPE$31.Number; var PLUSSIGN$6 = TYPE$31.PlusSign; var HYPHENMINUS$6 = TYPE$31.HyphenMinus; var FULLSTOP$5 = TYPE$31.FullStop; var QUESTIONMARK = TYPE$31.QuestionMark;

function scanUnicodeNumber(scanner) {

for (var pos = scanner.tokenStart + 1; pos < scanner.tokenEnd; pos++) {
    var code = scanner.source.charCodeAt(pos);

    // break on fullstop or hyperminus/plussign after exponent
    if (code === FULLSTOP$5 || code === PLUSSIGN$6) {
        // break token, exclude symbol
        scanner.tokenStart = pos;
        return false;
    }
}

return true;

}

// drafts.csswg.org/css-syntax-3/#urange function scanUnicodeRange(scanner) {

var hexStart = scanner.tokenStart + 1; // skip +
var hexLength = 0;

scan: {
    if (scanner.tokenType === NUMBER$10) {
        if (scanner.source.charCodeAt(scanner.tokenStart) !== FULLSTOP$5 && scanUnicodeNumber(scanner)) {
            scanner.next();
        } else if (scanner.source.charCodeAt(scanner.tokenStart) !== HYPHENMINUS$6) {
            break scan;
        }
    } else {
        scanner.next(); // PLUSSIGN
    }

    if (scanner.tokenType === HYPHENMINUS$6) {
        scanner.next();
    }

    if (scanner.tokenType === NUMBER$10) {
        scanner.next();
    }

    if (scanner.tokenType === IDENTIFIER$17) {
        scanner.next();
    }

    if (scanner.tokenStart === hexStart) {
        scanner.error('Unexpected input', hexStart);
    }
}

// validate for U+x{1,6} or U+x{1,6}-x{1,6}
// where x is [0-9a-fA-F]
for (var i = hexStart, wasHyphenMinus = false; i < scanner.tokenStart; i++) {
    var code = scanner.source.charCodeAt(i);

    if (isHex$1(code) === false && (code !== HYPHENMINUS$6 || wasHyphenMinus)) {
        scanner.error('Unexpected input', i);
    }

    if (code === HYPHENMINUS$6) {
        // hex sequence shouldn't be an empty
        if (hexLength === 0) {
            scanner.error('Unexpected input', i);
        }

        wasHyphenMinus = true;
        hexLength = 0;
    } else {
        hexLength++;

        // too long hex sequence
        if (hexLength > 6) {
            scanner.error('Too long hex sequence', i);
        }
    }

}

// check we have a non-zero sequence
if (hexLength === 0) {
    scanner.error('Unexpected input', i - 1);
}

// U+abc???
if (!wasHyphenMinus) {
    // consume as many U+003F QUESTION MARK (?) code points as possible
    for (; hexLength < 6 && !scanner.eof; scanner.next()) {
        if (scanner.tokenType !== QUESTIONMARK) {
            break;
        }

        hexLength++;
    }
}

}

var UnicodeRange = function UnicodeRange() {

var start = this.scanner.tokenStart;

this.scanner.next(); // U or u
scanUnicodeRange(this.scanner);

return {
    type: 'UnicodeRange',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: this.scanner.substrToCursor(start)
};

};

var TYPE$32 = index$1.TYPE;

var STRING$5 = TYPE$32.String; var LEFTPARENTHESIS$8 = TYPE$32.LeftParenthesis; var RIGHTPARENTHESIS$7 = TYPE$32.RightParenthesis; var NONBALANCED = false;

// url '(' S* (string | raw) S* ')' var Url = function Url() {

var start = this.scanner.tokenStart;
var value;

this.scanner.expectIdentifier('url');
this.scanner.eat(LEFTPARENTHESIS$8);
this.readSC();

if (this.scanner.tokenType === STRING$5) {
    value = this.String();
} else {
    value = this.Raw(NONBALANCED, LEFTPARENTHESIS$8, RIGHTPARENTHESIS$7);
}

this.readSC();
this.scanner.eat(RIGHTPARENTHESIS$7);

return {
    type: 'Url',
    loc: this.getLocation(start, this.scanner.tokenStart),
    value: value
};

};

var endsWith$1 = index$1.endsWith; var TYPE$33 = index$1.TYPE;

var WHITESPACE$9 = TYPE$33.Whitespace; var COMMENT$8 = TYPE$33.Comment; var LEFTPARENTHESIS$9 = TYPE$33.LeftParenthesis; var COLON$6 = TYPE$33.Colon; var SEMICOLON$4 = TYPE$33.Semicolon; var EXCLAMATIONMARK$2 = TYPE$33.ExclamationMark; var BALANCED$6 = true;

var Value = function Value(property) {

// special parser for filter property since it can contains non-standart syntax for old IE
if (property !== null && endsWith$1(property, 'filter') && checkProgid(this.scanner)) {
    this.readSC();
    return this.Raw(BALANCED$6, SEMICOLON$4, EXCLAMATIONMARK$2);
}

var start = this.scanner.tokenStart;
var children = this.readSequence(this.scopeValue);

return {
    type: 'Value',
    loc: this.getLocation(start, this.scanner.tokenStart),
    children: children
};

};

// 'progid:' ws* 'DXImageTransform.Microsoft.' ident ws* '(' .* ')' function checkProgid(scanner) {

var offset = 0;

for (var type; type = scanner.lookupType(offset); offset++) {
    if (type !== WHITESPACE$9 && type !== COMMENT$8) {
        break;
    }
}

if (scanner.lookupValue(offset, 'alpha') ||
    scanner.lookupValue(offset, 'dropshadow')) {
    if (scanner.lookupType(offset + 1) !== LEFTPARENTHESIS$9) {
        return false;
    }
} else {
    if (scanner.lookupValue(offset, 'progid') === false ||
        scanner.lookupType(offset + 1) !== COLON$6) {
        return false;
    }
}

return true;

}

var WHITESPACE$10 = index$1.TYPE.Whitespace; var SPACE$2 = Object.freeze({

type: 'WhiteSpace',
loc: null,
value: ' '

});

var WhiteSpace = function WhiteSpace() {

this.scanner.eat(WHITESPACE$10);
return SPACE$2;

// return {
//     type: 'WhiteSpace',
//     loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
//     value: this.scanner.consume(WHITESPACE)
// };

};

var List$11 = list;

// drafts.csswg.org/css-images-4/#element-notation // developer.mozilla.org/en-US/docs/Web/CSS/element var element = function() {

this.readSC();

var id = this.IdSelector();

this.readSC();

return new List$11().appendData(
    id
);

};

var List$12 = list; var BALANCED$7 = true;

// legacy IE function // expression '(' raw ')' var expression = function getOldIEExpression() {

return new List$12().appendData(
    this.Raw(BALANCED$7, 0, 0)
);

};

var List$13 = list; var TYPE$34 = index$1.TYPE;

var IDENTIFIER$18 = TYPE$34.Identifier; var COMMA$3 = TYPE$34.Comma; var HYPHENMINUS$7 = TYPE$34.HyphenMinus; var EXCLAMATIONMARK$3 = TYPE$34.ExclamationMark; var BALANCED$8 = true;

// var '(' ident (',' <value>? )? ')' var _var = function getVarFunction() {

var children = new List$13();

this.readSC();

var identStart = this.scanner.tokenStart;

this.scanner.eat(HYPHENMINUS$7);
if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== HYPHENMINUS$7) {
    this.scanner.error('HyphenMinus is expected');
}
this.scanner.eat(IDENTIFIER$18);

children.appendData({
    type: 'Identifier',
    loc: this.getLocation(identStart, this.scanner.tokenStart),
    name: this.scanner.substrToCursor(identStart)
});

this.readSC();

if (this.scanner.tokenType === COMMA$3) {
    children.appendData(this.Operator());
    children.appendData(this.parseCustomProperty
        ? this.Value(null)
        : this.Raw(BALANCED$8, HYPHENMINUS$7, EXCLAMATIONMARK$3)
    );
}

return children;

};

var List$14 = list; var TYPE$35 = index$1.TYPE;

var STRING$6 = TYPE$35.String; var IDENTIFIER$19 = TYPE$35.Identifier; var LEFTPARENTHESIS$10 = TYPE$35.LeftParenthesis;

var _import = {

expression: function() {
    var children = new List$14();

    this.readSC();

    switch (this.scanner.tokenType) {
        case STRING$6:
            children.appendData(this.String());
            break;

        case IDENTIFIER$19:
            children.appendData(this.Url());
            break;

        default:
            this.scanner.error('String or url() is expected');
    }

    if (this.scanner.lookupNonWSType(0) === IDENTIFIER$19 ||
        this.scanner.lookupNonWSType(0) === LEFTPARENTHESIS$10) {
        children.appendData(this.WhiteSpace());
        children.appendData(this.MediaQueryList());
    }

    return children;
},
block: false

};

var media = {

expression: function() {
    return this.MediaQueryList();
},
block: function() {
    return this.Block(this.Rule);
}

};

var TYPE$36 = index$1.TYPE; var LEFTCURLYBRACKET$5 = TYPE$36.LeftCurlyBracket;

var page = {

expression: function() {
    if (this.scanner.lookupNonWSType(0) === LEFTCURLYBRACKET$5) {
        return null;
    }

    return this.SelectorList();
},
block: function() {
    return this.Block(this.Declaration);
}

};

var List$15 = list; var TYPE$37 = index$1.TYPE;

var WHITESPACE$11 = TYPE$37.Whitespace; var COMMENT$9 = TYPE$37.Comment; var IDENTIFIER$20 = TYPE$37.Identifier; var LEFTPARENTHESIS$11 = TYPE$37.LeftParenthesis; var HYPHENMINUS$8 = TYPE$37.HyphenMinus; var COLON$7 = TYPE$37.Colon; var BALANCED$9 = true;

function readRaw() {

return new List$15().appendData(
    this.Raw(BALANCED$9, 0, 0)
);

}

function parentheses() {

var index = 0;

this.readSC();

// TODO: make it simplier
if (this.scanner.tokenType === IDENTIFIER$20) {
    index = 1;
} else if (this.scanner.tokenType === HYPHENMINUS$8 &&
           this.scanner.lookupType(1) === IDENTIFIER$20) {
    index = 2;
}

if (index !== 0 && this.scanner.lookupNonWSType(index) === COLON$7) {
    return new List$15().appendData(
        this.Declaration()
    );
}

return readSequence.call(this);

}

function readSequence() {

var children = new List$15();
var space = null;
var child;

this.readSC();

scan:
while (!this.scanner.eof) {
    switch (this.scanner.tokenType) {
        case WHITESPACE$11:
            space = this.WhiteSpace();
            continue;

        case COMMENT$9:
            this.scanner.next();
            continue;

        case IDENTIFIER$20:
            if (this.scanner.lookupType(1) === LEFTPARENTHESIS$11) {
                child = this.Function(this.scopeAtruleExpression, readRaw);
            } else {
                child = this.Identifier();
            }

            break;

        case LEFTPARENTHESIS$11:
            child = this.Parentheses(parentheses);
            break;

        default:
            break scan;
    }

    if (space !== null) {
        children.appendData(space);
        space = null;
    }

    children.appendData(child);
}

return children;

}

var supports = {

expression: function() {
    var children = readSequence.call(this);

    if (children.isEmpty()) {
        this.scanner.error('Condition is expected');
    }

    return children;
},
block: function() {
    return this.Block(this.Rule);
}

};

var Tokenizer = index$1;

var TYPE = Tokenizer.TYPE; var WHITESPACE = TYPE.Whitespace; var COMMENT = TYPE.Comment;

var sequence = sequence$1; var getAnPlusB = AnPlusB; var getAtrule = Atrule; var getAtruleExpression = AtruleExpression; var getAttributeSelector = AttributeSelector; var getBlock = Block; var getBrackets = Brackets; var getClassSelector = ClassSelector; var getCombinator = Combinator; var getComment = Comment; var getDeclaration = Declaration; var getDeclarationList = DeclarationList; var getDimension = Dimention; var getFunction = _Function; var getHexColor = HexColor; var getIdentifier = Identifier; var getIdSelector = IdSelector; var getMediaFeature = MediaFeature; var getMediaQuery = MediaQuery; var getMediaQueryList = MediaQueryList; var getNth = Nth; var getNumber = _Number; var getOperator = Operator; var getParentheses = Parentheses; var getPercentage = Percentage; var getPseudoClassSelector = PseudoClassSelector; var getPseudoElementSelector = PseudoElementSelector; var getRatio = Ratio; var getRaw = Raw; var getRule = Rule; var getSelector = Selector; var getSelectorList = SelectorList; var getString = _String; var getStyleSheet = StyleSheet; var getTypeSelector = TypeSelector; var getUnicodeRange = UnicodeRange; var getUrl = Url; var getValue = Value; var getWhiteSpace = WhiteSpace;

function readSC() {

while (this.scanner.tokenType === WHITESPACE || this.scanner.tokenType === COMMENT) {
    this.scanner.next();
}

}

var Parser$2 = function() {

this.scanner = new Tokenizer();
this.filename = '<unknown>';
this.needPositions = false;

};

Parser$2.prototype = {

scanner: null,
filename: '<unknown>',
needPositions: false,
parseAtruleExpression: true,
parseSelector: true,
parseValue: true,
parseCustomProperty: false,

scopeAtruleExpression: {},
scopeValue: {
    '-moz-element': element,
    'element': element,
    'expression': expression,
    'var': _var
},
atrule: {
    'import': _import,
    'media': media,
    'page': page,
    'supports': supports
},
pseudo: {
    'lang': sequence.singleIdentifier,
    'dir': sequence.singleIdentifier,
    'not': sequence.selectorList,
    'matches': sequence.selectorList,
    'has': sequence.selectorList,
    'nth-child': sequence.nthWithOfClause,
    'nth-last-child': sequence.nthWithOfClause,
    'nth-of-type': sequence.nth,
    'nth-last-of-type': sequence.nth,
    'slotted': sequence.compoundSelector
},
context: {
    stylesheet: getStyleSheet,
    atrule: getAtrule,
    atruleExpression: getAtruleExpression,
    rule: getRule,
    selectorList: getSelectorList,
    selector: getSelector,
    block: getBlock,
    declarationList: getDeclarationList,
    declaration: getDeclaration,
    value: getValue
},

// consumers
AnPlusB: getAnPlusB,
Atrule: getAtrule,
AtruleExpression: getAtruleExpression,
AttributeSelector: getAttributeSelector,
Block: getBlock,
Brackets: getBrackets,
ClassSelector: getClassSelector,
Combinator: getCombinator,
Comment: getComment,
Declaration: getDeclaration,
DeclarationList: getDeclarationList,
Dimension: getDimension,
Function: getFunction,
HexColor: getHexColor,
Identifier: getIdentifier,
IdSelector: getIdSelector,
MediaFeature: getMediaFeature,
MediaQuery: getMediaQuery,
MediaQueryList: getMediaQueryList,
Nth: getNth,
Number: getNumber,
Operator: getOperator,
Parentheses: getParentheses,
Percentage: getPercentage,
PseudoClassSelector: getPseudoClassSelector,
PseudoElementSelector: getPseudoElementSelector,
Ratio: getRatio,
Raw: getRaw,
Rule: getRule,
Selector: getSelector,
SelectorList: getSelectorList,
String: getString,
StyleSheet: getStyleSheet,
TypeSelector: getTypeSelector,
UnicodeRange: getUnicodeRange,
Url: getUrl,
Value: getValue,
WhiteSpace: getWhiteSpace,

readSC: readSC,
readSelectorSequence: sequence.selector,
readSelectorSequenceFallback: null,
readSequence: sequence.default,
readSequenceFallback: null,

getLocation: function(start, end) {
    if (this.needPositions) {
        return this.scanner.getLocationRange(
            start,
            end,
            this.filename
        );
    }

    return null;
},
getLocationFromList: function(list) {
    if (this.needPositions) {
        return this.scanner.getLocationRange(
            list.head !== null ? list.first().loc.start.offset - this.scanner.startOffset : this.scanner.tokenStart,
            list.head !== null ? list.last().loc.end.offset - this.scanner.startOffset : this.scanner.tokenStart,
            this.filename
        );
    }

    return null;
},

parse: function(source, options) {
    options = options || {};

    var context = options.context || 'stylesheet';
    var ast;

    this.scanner.setSource(source, options.offset, options.line, options.column);
    this.filename = options.filename || '<unknown>';
    this.needPositions = Boolean(options.positions);
    this.parseAtruleExpression = 'parseAtruleExpression' in options ? Boolean(options.parseAtruleExpression) : true;
    this.parseSelector = 'parseSelector' in options ? Boolean(options.parseSelector) : true;
    this.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
    this.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;

    switch (context) {
        case 'value':
            ast = this.Value(options.property ? String(options.property) : null);
            break;

        case 'atruleExpression':
            ast = this.AtruleExpression(options.atrule ? String(options.atrule) : null);
            break;

        default:
            if (!this.context.hasOwnProperty(context)) {
                throw new Error('Unknown context `' + context + '`');
            }

            ast = this.context[context].call(this);
    }

    if (!this.scanner.eof) {
        this.scanner.error();
    }

    // console.log(JSON.stringify(ast, null, 4));
    return ast;
}

};

// warm up parse to elimitate code branches that never execute // fix soft deoptimizations (insufficient type feedback) new Parser$2().parse(

'a.b#c:e:Not(a/**/):AFTER:Nth-child(2n+1)::g::slotted(a/**/),* b >c+d~e/deep/f,100%{' +
'v:U+123 1 2em t a(2%, var(--a)) -b() url(..) -foo-bar !important}'

);

var Parser_1 = Parser$2;

var Parser$1 = Parser_1; var parser = new Parser$1();

var index = parser.parse.bind(parser);

function walkRules(node, item, list) {

switch (node.type) {
    case 'StyleSheet':
        var oldStylesheet = this.stylesheet;
        this.stylesheet = node;

        node.children.each(walkRules, this);

        this.stylesheet = oldStylesheet;
        break;

    case 'Atrule':
        if (node.block !== null) {
            walkRules.call(this, node.block);
        }

        this.fn(node, item, list);
        break;

    case 'Rule':
        this.fn(node, item, list);

        var oldRule = this.rule;
        this.rule = node;

        walkRules.call(this, node.block);

        this.rule = oldRule;
        break;

    case 'Block':
        var oldBlock = this.block;
        this.block = node;

        node.children.each(walkRules, this);

        this.block = oldBlock;
        break;
}

}

function walkRulesRight(node, item, list) {

switch (node.type) {
    case 'StyleSheet':
        var oldStylesheet = this.stylesheet;
        this.stylesheet = node;

        node.children.eachRight(walkRulesRight, this);

        this.stylesheet = oldStylesheet;
        break;

    case 'Atrule':
        if (node.block !== null) {
            walkRulesRight.call(this, node.block);
        }

        this.fn(node, item, list);
        break;

    case 'Rule':
        var oldRule = this.rule;
        this.rule = node;

        walkRulesRight.call(this, node.block);

        this.rule = oldRule;

        this.fn(node, item, list);
        break;

    case 'Block':
        var oldBlock = this.block;
        this.block = node;

        node.children.eachRight(walkRulesRight, this);

        this.block = oldBlock;
        break;
}

}

function walkDeclarations(node) {

switch (node.type) {
    case 'StyleSheet':
        var oldStylesheet = this.stylesheet;
        this.stylesheet = node;

        node.children.each(walkDeclarations, this);

        this.stylesheet = oldStylesheet;
        break;

    case 'Atrule':
        if (node.block !== null) {
            walkDeclarations.call(this, node.block);
        }
        break;

    case 'Rule':
        var oldRule = this.rule;
        this.rule = node;

        if (node.block !== null) {
            walkDeclarations.call(this, node.block);
        }

        this.rule = oldRule;
        break;

    case 'Block':
        node.children.each(function(node, item, list) {
            if (node.type === 'Declaration') {
                this.fn(node, item, list);
            } else {
                walkDeclarations.call(this, node);
            }
        }, this);
        break;
}

}

function walkAll(node, item, list) {

this.fn(node, item, list);
walk.call(this, walkAll, node, item, list);

}

function walkAllUp(node, item, list) {

walk.call(this, walkAllUp, node, item, list);
this.fn(node, item, list);

}

function walk(walk, node) {

switch (node.type) {
    case 'StyleSheet':
        var oldStylesheet = this.stylesheet;
        this.stylesheet = node;

        node.children.each(walk, this);

        this.stylesheet = oldStylesheet;
        break;

    case 'Atrule':
        if (node.expression !== null) {
            walk.call(this, node.expression);
        }
        if (node.block !== null) {
            walk.call(this, node.block);
        }
        break;

    case 'Rule':
        this.rule = node;

        if (node.selector !== null) {
            walk.call(this, node.selector);
        }
        walk.call(this, node.block);

        this.rule = null;
        break;

    case 'SelectorList':
        var oldSelector = this.selector;
        this.selector = node;

        node.children.each(walk, this);

        this.selector = oldSelector;
        break;

    case 'Selector':
        node.children.each(walk, this);
        break;

    case 'Nth':
        walk.call(this, node.nth);
        if (node.selector !== null) {
            walk.call(this, node.selector);
        }
        break;

    case 'Block':
        var oldBlock = this.block;
        this.block = node;

        node.children.each(walk, this);

        this.block = oldBlock;
        break;

    case 'DeclarationList':
        node.children.each(walk, this);
        break;

    case 'Declaration':
        this.declaration = node;

        walk.call(this, node.value);

        this.declaration = null;
        break;

    case 'AttributeSelector':
        walk.call(this, node.name);
        if (node.value !== null) {
            walk.call(this, node.value);
        }
        break;

    case 'PseudoClassSelector':
        if (node.children !== null) {
            this['function'] = node;

            node.children.each(walk, this);

            this['function'] = null;
        }
        break;

    case 'PseudoElementSelector':
        if (node.children !== null) {
            this['function'] = node;

            node.children.each(walk, this);

            this['function'] = null;
        }
        break;

    case 'Function':
        this['function'] = node;

        node.children.each(walk, this);

        this['function'] = null;
        break;

    case 'AtruleExpression':
        this.atruleExpression = node;

        node.children.each(walk, this);

        this.atruleExpression = null;
        break;

    case 'MediaQueryList':
        node.children.each(walk, this);
        break;

    case 'MediaQuery':
        node.children.each(walk, this);
        break;

    case 'MediaFeature':
        if (node.value !== null) {
            walk.call(this, node.value);
        }
        break;

    case 'Value':
        node.children.each(walk, this);
        break;

    case 'Parentheses':
        node.children.each(walk, this);
        break;

    case 'Brackets':
        node.children.each(walk, this);
        break;

    case 'Url':
        walk.call(this, node.value);
        break;
}

}

function createContext(root, fn) {

var context = {
    fn: fn,
    root: root,
    stylesheet: null,
    atruleExpression: null,
    rule: null,
    selector: null,
    block: null,
    declaration: null,
    function: null
};

return context;

}

var walk_1 = {

all: function(root, fn) {
    walkAll.call(createContext(root, fn), root);
},
allUp: function(root, fn) {
    walkAllUp.call(createContext(root, fn), root);
},
rules: function(root, fn) {
    walkRules.call(createContext(root, fn), root);
},
rulesRight: function(root, fn) {
    walkRulesRight.call(createContext(root, fn), root);
},
declarations: function(root, fn) {
    walkDeclarations.call(createContext(root, fn), root);
}

};

function readStyle ( parser, start, attributes ) {

var contentStart = parser.index;
var styles = parser.readUntil( /<\/style>/ );
var contentEnd = parser.index;

var ast;

try {
        ast = index( styles, {
                positions: true,
                offset: contentStart
        });
} catch ( err ) {
        if ( err.name === 'CssSyntaxError' ) {
                parser.error( err.message, err.offset );
        } else {
                throw err;
        }
}

// tidy up AST
walk_1.all( ast, function (node) {
        if ( node.loc ) {
                node.start = node.loc.start.offset;
                node.end = node.loc.end.offset;
                delete node.loc;
        }
});

parser.eat( '</style>', true );
var end = parser.index;

return {
        start: start,
        end: end,
        attributes: attributes,
        children: JSON.parse( JSON.stringify( ast.children ) ),
        content: {
                start: contentStart,
                end: contentEnd,
                styles: styles
        }
};

}

function readEventHandlerDirective ( parser, start, name ) {

var quoteMark = (
        parser.eat( "'" ) ? "'" :
        parser.eat( "\"" ) ? "\"" :
        null
);

var expressionStart = parser.index;

var str = '';
var escaped = false;

for ( var i = expressionStart; i < parser.template.length; i += 1 ) {
        var char = parser.template[i];

        if ( quoteMark ) {
                if ( char === quoteMark ) {
                        if ( escaped ) {
                                str += quoteMark;
                        } else {
                                parser.index = i + 1;
                                break;
                        }
                } else if ( escaped ) {
                        str += '\\' + char;
                        escaped = false;
                } else if ( char === '\\' ) {
                        escaped = true;
                } else {
                        str += char;
                }
        }

        else if ( /\s/.test( char ) ) {
                parser.index = i;
                break;
        }

        else {
                str += char;
        }
}

var ast = parse$1( spaces( expressionStart ) + str );

if ( ast.body.length > 1 ) {
        parser.error( "Event handler should be a single call expression", ast.body[1].start );
}

var expression = ast.body[0].expression;

if ( expression.type !== 'CallExpression' ) {
        parser.error( "Expected call expression", expressionStart );
}

return {
        start: start,
        end: parser.index,
        type: 'EventHandler',
        name: name,
        expression: expression
};

}

function readBindingDirective ( parser, start, name ) {

var value;

if ( parser.eat( '=' ) ) {
        var quoteMark = (
                parser.eat( "'" ) ? "'" :
                parser.eat( "\"" ) ? "\"" :
                null
        );

        var a = parser.index;

        // this is a bit of a hack so that we can give Acorn something parseable
        var b;
        if ( quoteMark ) {
                b = parser.index = parser.template.indexOf( quoteMark, parser.index );
        } else {
                parser.readUntil( /[\s\r\n\/>]/ );
                b = parser.index;
        }

        var source = spaces( a ) + parser.template.slice( a, b );
        value = parseExpressionAt( source, a );

        if ( value.type !== 'Identifier' && value.type !== 'MemberExpression' ) {
                parser.error( "Expected valid property name" );
        }

        parser.allowWhitespace();

        if ( quoteMark ) {
                parser.eat( quoteMark, true );
        }
} else {
        // shorthand – bind:foo equivalent to bind:foo='foo'
        value = {
                type: 'Identifier',
                start: start + 5,
                end: parser.index,
                name: name
        };
}

return {
        start: start,
        end: parser.index,
        type: 'Binding',
        name: name,
        value: value
};

}

var whitespace = /[ trn]/;

function trimStart ( str ) {

var i = 0;
while ( whitespace.test( str[i] ) ) { i += 1; }

return str.slice( i );

}

function trimEnd ( str ) {

var i = str.length;
while ( whitespace.test( str[ i - 1 ] ) ) { i -= 1; }

return str.slice( 0, i );

}

// borrowed from Ractive – github.com/ractivejs/ractive/blob/faf93cbd33c3fedfd8d6dd48340990540bde4a94/src/utils/html.js var htmlEntities = { quot: 34, amp: 38, apos: 39, lt: 60, gt: 62, nbsp: 160, iexcl: 161, cent: 162, pound: 163, curren: 164, yen: 165, brvbar: 166, sect: 167, uml: 168, copy: 169, ordf: 170, laquo: 171, not: 172, shy: 173, reg: 174, macr: 175, deg: 176, plusmn: 177, sup2: 178, sup3: 179, acute: 180, micro: 181, para: 182, middot: 183, cedil: 184, sup1: 185, ordm: 186, raquo: 187, frac14: 188, frac12: 189, frac34: 190, iquest: 191, Agrave: 192, Aacute: 193, Acirc: 194, Atilde: 195, Auml: 196, Aring: 197, AElig: 198, Ccedil: 199, Egrave: 200, Eacute: 201, Ecirc: 202, Euml: 203, Igrave: 204, Iacute: 205, Icirc: 206, Iuml: 207, ETH: 208, Ntilde: 209, Ograve: 210, Oacute: 211, Ocirc: 212, Otilde: 213, Ouml: 214, times: 215, Oslash: 216, Ugrave: 217, Uacute: 218, Ucirc: 219, Uuml: 220, Yacute: 221, THORN: 222, szlig: 223, agrave: 224, aacute: 225, acirc: 226, atilde: 227, auml: 228, aring: 229, aelig: 230, ccedil: 231, egrave: 232, eacute: 233, ecirc: 234, euml: 235, igrave: 236, iacute: 237, icirc: 238, iuml: 239, eth: 240, ntilde: 241, ograve: 242, oacute: 243, ocirc: 244, otilde: 245, ouml: 246, divide: 247, oslash: 248, ugrave: 249, uacute: 250, ucirc: 251, uuml: 252, yacute: 253, thorn: 254, yuml: 255, OElig: 338, oelig: 339, Scaron: 352, scaron: 353, Yuml: 376, fnof: 402, circ: 710, tilde: 732, Alpha: 913, Beta: 914, Gamma: 915, Delta: 916, Epsilon: 917, Zeta: 918, Eta: 919, Theta: 920, Iota: 921, Kappa: 922, Lambda: 923, Mu: 924, Nu: 925, Xi: 926, Omicron: 927, Pi: 928, Rho: 929, Sigma: 931, Tau: 932, Upsilon: 933, Phi: 934, Chi: 935, Psi: 936, Omega: 937, alpha: 945, beta: 946, gamma: 947, delta: 948, epsilon: 949, zeta: 950, eta: 951, theta: 952, iota: 953, kappa: 954, lambda: 955, mu: 956, nu: 957, xi: 958, omicron: 959, pi: 960, rho: 961, sigmaf: 962, sigma: 963, tau: 964, upsilon: 965, phi: 966, chi: 967, psi: 968, omega: 969, thetasym: 977, upsih: 978, piv: 982, ensp: 8194, emsp: 8195, thinsp: 8201, zwnj: 8204, zwj: 8205, lrm: 8206, rlm: 8207, ndash: 8211, mdash: 8212, lsquo: 8216, rsquo: 8217, sbquo: 8218, ldquo: 8220, rdquo: 8221, bdquo: 8222, dagger: 8224, Dagger: 8225, bull: 8226, hellip: 8230, permil: 8240, prime: 8242, Prime: 8243, lsaquo: 8249, rsaquo: 8250, oline: 8254, frasl: 8260, euro: 8364, image: 8465, weierp: 8472, real: 8476, trade: 8482, alefsym: 8501, larr: 8592, uarr: 8593, rarr: 8594, darr: 8595, harr: 8596, crarr: 8629, lArr: 8656, uArr: 8657, rArr: 8658, dArr: 8659, hArr: 8660, forall: 8704, part: 8706, exist: 8707, empty: 8709, nabla: 8711, isin: 8712, notin: 8713, ni: 8715, prod: 8719, sum: 8721, minus: 8722, lowast: 8727, radic: 8730, prop: 8733, infin: 8734, ang: 8736, and: 8743, or: 8744, cap: 8745, cup: 8746, int: 8747, there4: 8756, sim: 8764, cong: 8773, asymp: 8776, ne: 8800, equiv: 8801, le: 8804, ge: 8805, sub: 8834, sup: 8835, nsub: 8836, sube: 8838, supe: 8839, oplus: 8853, otimes: 8855, perp: 8869, sdot: 8901, lceil: 8968, rceil: 8969, lfloor: 8970, rfloor: 8971, lang: 9001, rang: 9002, loz: 9674, spades: 9824, clubs: 9827, hearts: 9829, diams: 9830 }; var controlCharacters = [ 8364, 129, 8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249, 338, 141, 381, 143, 144, 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8482, 353, 8250, 339, 157, 382, 376 ]; var entityPattern = new RegExp( '&(#?(?:x+|\d+|' + Object.keys( htmlEntities ).join( '|' ) + '));?', 'g' );

function decodeCharacterReferences ( html ) {

return html.replace( entityPattern, function ( match, entity ) {
        var code;

        // Handle named entities
        if ( entity[0] !== '#' ) {
                code = htmlEntities[ entity ];
        } else if ( entity[1] === 'x' ) {
                code = parseInt( entity.substring( 2 ), 16 );
        } else {
                code = parseInt( entity.substring( 1 ), 10 );
        }

        if ( !code ) {
                return match;
        }

        return String.fromCodePoint( validateCode( code ) );
});

} var invalid = 65533;

// some code points are verboten. If we were inserting HTML, the browser would replace the illegal // code points with alternatives in some cases - since we're bypassing that mechanism, we need // to replace them ourselves // // Source: en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters function validateCode ( code ) {

if ( !code ) {
        return invalid;
}

// line feed becomes generic whitespace
if ( code === 10 ) {
        return 32;
}

// ASCII range. (Why someone would use HTML entities for ASCII characters I don't know, but...)
if ( code < 128 ) {
        return code;
}

// code points 128-159 are dealt with leniently by browsers, but they're incorrect. We need
// to correct the mistake or we'll end up with missing € signs and so on
if ( code <= 159 ) {
        return controlCharacters[ code - 128 ];
}

// basic multilingual plane
if ( code < 55296 ) {
        return code;
}

// UTF-16 surrogate halves
if ( code <= 57343 ) {
        return invalid;
}

// rest of the basic multilingual plane
if ( code <= 65535 ) {
        return code;
}

// supplementary multilingual plane 0x10000 - 0x1ffff
if ( code >= 65536 && code <= 131071 ) {
        return code;
}

// supplementary ideographic plane 0x20000 - 0x2ffff
if ( code >= 131072 && code <= 196607 ) {
        return code;
}

return invalid;

}

var voidElementNames = /^(?:area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/;

function isVoidElementName ( name ) {

return voidElementNames.test( name ) || name.toLowerCase() === '!doctype';

}

var validTagName = /^!?[a-zA-Z]{1,}:?[a-zA-Z0-9-]*/; var invalidUnquotedAttributeCharacters = /[s“'=<>/`]/;

var SELF = ':Self';

var specials = {

script: {
        read: readScript,
        property: 'js'
},

style: {
        read: readStyle,
        property: 'css'
}

};

// based on developers.whatwg.org/syntax.html#syntax-tag-omission var disallowedContents = {

li: [ 'li' ],
dt: [ 'dt', 'dd' ],
dd: [ 'dt', 'dd' ],
p: 'address article aside blockquote div dl fieldset footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav ol p pre section table ul'.split( ' ' ),
rt: [ 'rt', 'rp' ],
rp: [ 'rt', 'rp' ],
optgroup: [ 'optgroup' ],
option: [ 'option', 'optgroup' ],
thead: [ 'tbody', 'tfoot' ],
tbody: [ 'tbody', 'tfoot' ],
tfoot: [ 'tbody' ],
tr: [ 'tr', 'tbody' ],
td: [ 'td', 'th', 'tr' ],
th: [ 'td', 'th', 'tr' ]

};

function stripWhitespace ( element ) {

if ( element.children.length ) {
        var firstChild = element.children[0];
        var lastChild = element.children[ element.children.length - 1 ];

        if ( firstChild.type === 'Text' ) {
                firstChild.data = trimStart( firstChild.data );
                if ( !firstChild.data ) { element.children.shift(); }
        }

        if ( lastChild.type === 'Text' ) {
                lastChild.data = trimEnd( lastChild.data );
                if ( !lastChild.data ) { element.children.pop(); }
        }
}

}

function tag ( parser ) {

var start = parser.index++;

var parent = parser.current();

if ( parser.eat( '!--' ) ) {
        var data = parser.readUntil( /-->/ );
        parser.eat( '-->' );

        parser.current().children.push({
                start: start,
                end: parser.index,
                type: 'Comment',
                data: data
        });

        return null;
}

var isClosingTag = parser.eat( '/' );

var name = readTagName( parser );

parser.allowWhitespace();

if ( isClosingTag ) {
        if ( isVoidElementName( name ) ) {
                parser.error( ("<" + name + "> is a void element and cannot have children, or a closing tag"), start );
        }

        if ( !parser.eat( '>' ) ) { parser.error( "Expected '>'" ); }

        // close any elements that don't have their own closing tags, e.g. <div><p></div>
        while ( parent.name !== name ) {
                if ( parent.type !== 'Element' ) { parser.error( ("</" + name + "> attempted to close an element that was not open"), start ); }

                parent.end = start;
                parser.stack.pop();

                parent = parser.current();
        }

        // strip leading/trailing whitespace as necessary
        stripWhitespace( parent );

        parent.end = parser.index;
        parser.stack.pop();

        return null;
} else if ( parent.name in disallowedContents ) {
        // can this be a child of the parent element, or does it implicitly
        // close it, like `<li>one<li>two`?
        var disallowed = disallowedContents[ parent.name ];
        if ( ~disallowed.indexOf( name ) ) {
                stripWhitespace( parent );

                parent.end = start;
                parser.stack.pop();
        }
}

var attributes = [];
var uniqueNames = new Set();

var attribute;
while ( attribute = readAttribute( parser, uniqueNames ) ) {
        attributes.push( attribute );
        parser.allowWhitespace();
}

parser.allowWhitespace();

// special cases – top-level <script> and <style>
if ( name in specials && parser.stack.length === 1 ) {
        var special = specials[ name ];

        if ( parser[ special.property ] ) {
                parser.index = start;
                parser.error( ("You can only have one top-level <" + name + "> tag per component") );
        }

        parser.eat( '>', true );
        parser[ special.property ] = special.read( parser, start, attributes );
        return;
}

var element = {
        start: start,
        end: null, // filled in later
        type: 'Element',
        name: name,
        attributes: attributes,
        children: []
};

parser.current().children.push( element );

var selfClosing = parser.eat( '/' ) || isVoidElementName( name );

parser.eat( '>', true );

if ( selfClosing ) {
        element.end = parser.index;
} else {
        // don't push self-closing elements onto the stack
        parser.stack.push( element );
}

return null;

}

function readTagName ( parser ) {

var start = parser.index;

if ( parser.eat( SELF ) ) {
        // check we're inside a block, otherwise this
        // will cause infinite recursion
        var i = parser.stack.length;
        var legal = false;

        while ( i-- ) {
                var fragment = parser.stack[i];
                if ( fragment.type === 'IfBlock' || fragment.type === 'EachBlock' ) {
                        legal = true;
                        break;
                }
        }

        if ( !legal ) {
                parser.error( ("<" + SELF + "> components can only exist inside if-blocks or each-blocks"), start );
        }

        return SELF;
}

var name = parser.readUntil( /(\s|\/|>)/ );
if ( !validTagName.test( name ) ) {
        parser.error( "Expected valid tag name", start );
}

return name;

}

function readAttribute ( parser, uniqueNames ) {

var start = parser.index;

var name = parser.readUntil( /(\s|=|\/|>)/ );
if ( !name ) { return null; }
if ( uniqueNames.has( name ) ) {
        parser.error( 'Attributes need to be unique', start );
}

uniqueNames.add( name );

parser.allowWhitespace();

if ( /^on:/.test( name ) ) {
        parser.eat( '=', true );
        return readEventHandlerDirective( parser, start, name.slice( 3 ) );
}

if ( /^bind:/.test( name ) ) {
        return readBindingDirective( parser, start, name.slice( 5 ) );
}

if ( /^ref:/.test( name ) ) {
        return {
                start: start,
                end: parser.index,
                type: 'Ref',
                name: name.slice( 4 )
        };
}

var value;

// :foo is shorthand for foo='{{foo}}'
if ( /^:\w+$/.test( name ) ) {
        name = name.slice( 1 );
        value = getShorthandValue( start + 1, name );
} else {
        value = parser.eat( '=' ) ? readAttributeValue( parser ) : true;
}

return {
        start: start,
        end: parser.index,
        type: 'Attribute',
        name: name,
        value: value
};

}

function readAttributeValue ( parser ) {

var quoteMark;

if ( parser.eat( "'" ) ) { quoteMark = "'"; }
if ( parser.eat( "\"" ) ) { quoteMark = "\""; }

var currentChunk = {
        start: parser.index,
        end: null,
        type: 'Text',
        data: ''
};

var done = quoteMark ?
        function (char) { return char === quoteMark; } :
        function (char) { return invalidUnquotedAttributeCharacters.test( char ); };

var chunks = [];

while ( parser.index < parser.template.length ) {
        var index = parser.index;

        if ( parser.eat( '{{' ) ) {
                if ( currentChunk.data ) {
                        currentChunk.end = index;
                        chunks.push( currentChunk );
                }

                var expression = readExpression( parser );
                parser.allowWhitespace();
                if ( !parser.eat( '}}' ) ) {
                        parser.error( "Expected }}" );
                }

                chunks.push({
                        start: index,
                        end: parser.index,
                        type: 'MustacheTag',
                        expression: expression
                });

                currentChunk = {
                        start: parser.index,
                        end: null,
                        type: 'Text',
                        data: ''
                };
        }

        else if ( done( parser.template[ parser.index ] ) ) {
                currentChunk.end = parser.index;
                if ( quoteMark ) { parser.index += 1; }

                if ( currentChunk.data ) { chunks.push( currentChunk ); }

                chunks.forEach( function (chunk) {
                        if ( chunk.type === 'Text' ) { chunk.data = decodeCharacterReferences( chunk.data ); }
                });

                return chunks;
        }

        else {
                currentChunk.data += parser.template[ parser.index++ ];
        }
}

parser.error( "Unexpected end of input" );

}

function getShorthandValue ( start, name ) {

var end = start + name.length;

return [{
        type: 'AttributeShorthand',
        start: start,
        end: end,
        expression: {
                type: 'Identifier',
                start: start,
                end: end,
                name: name
        }
}];

}

var validIdentifier = /[a-zA-Z_$]*/;

function trimWhitespace ( block, trimBefore, trimAfter ) {

var firstChild = block.children[0];
var lastChild = block.children[ block.children.length - 1 ];

if ( firstChild.type === 'Text' && trimBefore ) {
        firstChild.data = trimStart( firstChild.data );
        if ( !firstChild.data ) { block.children.shift(); }
}

if ( lastChild.type === 'Text' && trimAfter ) {
        lastChild.data = trimEnd( lastChild.data );
        if ( !lastChild.data ) { block.children.pop(); }
}

if ( block.else ) {
        trimWhitespace( block.else, trimBefore, trimAfter );
}

if ( firstChild.elseif ) {
        trimWhitespace( firstChild, trimBefore, trimAfter );
}

}

function mustache ( parser ) {

var start = parser.index;
parser.index += 2;

parser.allowWhitespace();

// {{/if}} or {{/each}}
if ( parser.eat( '/' ) ) {
        var block = parser.current();
        var expected;

        if ( block.type === 'ElseBlock' ) {
                block.end = start;
                parser.stack.pop();
                block = parser.current();
        }

        if ( block.type === 'IfBlock' ) {
                expected = 'if';
        } else if ( block.type === 'EachBlock' ) {
                expected = 'each';
        } else {
                parser.error( "Unexpected block closing tag" );
        }

        parser.eat( expected, true );
        parser.allowWhitespace();
        parser.eat( '}}', true );

        while ( block.elseif ) {
                block.end = parser.index;
                parser.stack.pop();
                block = parser.current();

                if ( block.else ) {
                        block.else.end = start;
                }
        }

        // strip leading/trailing whitespace as necessary
        if ( !block.children.length ) { parser.error( "Empty block", block.start ); }

        var charBefore = parser.template[ block.start - 1 ];
        var charAfter = parser.template[ parser.index ];
        var trimBefore = !charBefore || whitespace.test( charBefore );
        var trimAfter = !charAfter || whitespace.test( charAfter );

        trimWhitespace( block, trimBefore, trimAfter );

        block.end = parser.index;
        parser.stack.pop();
}

else if ( parser.eat( 'elseif' ) ) {
        var block$1 = parser.current();
        if ( block$1.type !== 'IfBlock' ) { parser.error( 'Cannot have an {{elseif ...}} block outside an {{#if ...}} block' ); }

        parser.requireWhitespace();

        var expression = readExpression( parser );

        parser.allowWhitespace();
        parser.eat( '}}', true );

        block$1.else = {
                start: parser.index,
                end: null,
                type: 'ElseBlock',
                children: [
                        {
                                start: parser.index,
                                end: null,
                                type: 'IfBlock',
                                elseif: true,
                                expression: expression,
                                children: []
                        }
                ]
        };

        parser.stack.push( block$1.else.children[0] );
}

else if ( parser.eat( 'else' ) ) {
        var block$2 = parser.current();
        if ( block$2.type !== 'IfBlock' && block$2.type !== 'EachBlock' ) {
                parser.error( 'Cannot have an {{else}} block outside an {{#if ...}} or {{#each ...}} block' );
        }

        parser.allowWhitespace();
        parser.eat( '}}', true );

        block$2.else = {
                start: parser.index,
                end: null,
                type: 'ElseBlock',
                children: []
        };

        parser.stack.push( block$2.else );
}

// {{#if foo}} or {{#each foo}}
else if ( parser.eat( '#' ) ) {
        var type;

        if ( parser.eat( 'if' ) ) {
                type = 'IfBlock';
        } else if ( parser.eat( 'each' ) ) {
                type = 'EachBlock';
        } else {
                parser.error( "Expected if or each" );
        }

        parser.requireWhitespace();

        var expression$1 = readExpression( parser );

        var block$3 = {
                start: start,
                end: null,
                type: type,
                expression: expression$1,
                children: []
        };

        parser.allowWhitespace();

        // {{#each}} blocks must declare a context – {{#each list as item}}
        if ( type === 'EachBlock' ) {
                parser.eat( 'as', true );
                parser.requireWhitespace();

                block$3.context = parser.read( validIdentifier ); // TODO check it's not a keyword
                if ( !block$3.context ) { parser.error( "Expected name" ); }

                parser.allowWhitespace();

                if ( parser.eat( ',' ) ) {
                        parser.allowWhitespace();
                        block$3.index = parser.read( validIdentifier );
                        if ( !block$3.index ) { parser.error( "Expected name" ); }
                        parser.allowWhitespace();
                }

                if ( parser.eat( '@' ) ) {
                        block$3.key = parser.read( validIdentifier );
                        if ( !block$3.key ) { parser.error( "Expected name" ); }
                        parser.allowWhitespace();
                }
        }

        parser.eat( '}}', true );

        parser.current().children.push( block$3 );
        parser.stack.push( block$3 );
}

// {{yield}}
else if ( parser.eat( 'yield' ) ) {

        parser.allowWhitespace();
        parser.eat( '}}', true );

        parser.current().children.push({
                start: start,
                end: parser.index,
                type: 'YieldTag'
        });
}

// {{{raw}}} mustache
else if ( parser.eat( '{' ) ) {
        var expression$2 = readExpression( parser );

        parser.allowWhitespace();
        parser.eat( '}}}', true );

        parser.current().children.push({
                start: start,
                end: parser.index,
                type: 'RawMustacheTag',
                expression: expression$2
        });
}

else {
        var expression$3 = readExpression( parser );

        parser.allowWhitespace();
        parser.eat( '}}', true );

        parser.current().children.push({
                start: start,
                end: parser.index,
                type: 'MustacheTag',
                expression: expression$3
        });
}

return null;

}

function text ( parser ) {

var start = parser.index;

var data = '';

while ( parser.index < parser.template.length && !parser.match( '<' ) && !parser.match( '{{' ) ) {
        data += parser.template[ parser.index++ ];
}

parser.current().children.push({
        start: start,
        end: parser.index,
        type: 'Text',
        data: decodeCharacterReferences( data )
});

return null;

}

function fragment ( parser ) {

if ( parser.match( '<' ) ) {
        return tag;
}

if ( parser.match( '{{' ) ) {
        return mustache;
}

return text;

}

function tabsToSpaces ( str ) {

return str.replace( /^\t+/, function (match) { return match.split( '\t' ).join( '  ' ); } );

}

function getCodeFrame ( source, line, column ) {

var lines = source.split( '\n' );

var frameStart = Math.max( 0, line - 2 );
var frameEnd = Math.min( line + 3, lines.length );

var digits = String( frameEnd + 1 ).length;

return lines
        .slice( frameStart, frameEnd )
        .map( function ( str, i ) {
                var isErrorLine = frameStart + i === line;

                var lineNum = String( i + frameStart + 1 );
                while ( lineNum.length < digits ) { lineNum = " " + lineNum; }

                if ( isErrorLine ) {
                        var indicator = spaces( digits + 2 + tabsToSpaces( str.slice( 0, column ) ).length ) + '^';
                        return (lineNum + ": " + (tabsToSpaces( str )) + "\n" + indicator);
                }

                return (lineNum + ": " + (tabsToSpaces( str )));
        })
        .join( '\n' );

}

// github.com/darkskyapp/string-hash/blob/master/index.js function hash ( str ) {

var hash = 5381;
var i = str.length;

while ( i-- ) { hash = ( hash * 33 ) ^ str.charCodeAt( i ); }
return hash >>> 0;

}

function ParseError ( message, template, index, filename ) {

var ref = locate( template, index );
var line = ref.line;
var column = ref.column;

this.name = 'ParseError';
this.message = message;
this.frame = getCodeFrame( template, line, column );

this.loc = { line: line + 1, column: column };
this.pos = index;
this.filename = filename;

}

ParseError.prototype.toString = function () {

return ((this.message) + " (" + (this.loc.line) + ":" + (this.loc.column) + ")\n" + (this.frame));

};

function parse ( template, options ) {

if ( options === void 0 ) options = {};

if ( typeof template !== 'string' ) {
        throw new TypeError( 'Template must be a string' );
}

template = template.replace( /\s+$/, '' );

var parser = {
        index: 0,
        template: template,
        stack: [],

        current: function current () {
                return this.stack[ this.stack.length - 1 ];
        },

        acornError: function acornError ( err ) {
                parser.error( err.message.replace( / \(\d+:\d+\)$/, '' ), err.pos );
        },

        error: function error ( message, index ) {
                if ( index === void 0 ) index = this.index;

                throw new ParseError( message, this.template, index, options.filename );
        },

        eat: function eat ( str, required ) {
                if ( this.match( str ) ) {
                        this.index += str.length;
                        return true;
                }

                if ( required ) {
                        this.error( ("Expected " + str) );
                }
        },

        match: function match ( str ) {
                return this.template.slice( this.index, this.index + str.length ) === str;
        },

        allowWhitespace: function allowWhitespace () {
                var this$1 = this;

                while ( this.index < this.template.length && whitespace.test( this.template[ this.index ] ) ) {
                        this$1.index++;
                }
        },

        read: function read ( pattern ) {
                var match = pattern.exec( this.template.slice( this.index ) );
                if ( !match || match.index !== 0 ) { return null; }

                parser.index += match[0].length;

                return match[0];
        },

        readUntil: function readUntil ( pattern ) {
                if ( this.index >= this.template.length ) { parser.error( 'Unexpected end of input' ); }

                var start = this.index;
                var match = pattern.exec( this.template.slice( start ) );

                if ( match ) {
                        var start$1 = this.index;
                        this.index = start$1 + match.index;
                        return this.template.slice( start$1, this.index );
                }

                this.index = this.template.length;
                return this.template.slice( start );
        },

        remaining: function remaining () {
                return this.template.slice( this.index );
        },

        requireWhitespace: function requireWhitespace () {
                if ( !whitespace.test( this.template[ this.index ] ) ) {
                        this.error( "Expected whitespace" );
                }

                this.allowWhitespace();
        },

        html: {
                start: null,
                end: null,
                type: 'Fragment',
                children: []
        },

        css: null,

        js: null
};

parser.stack.push( parser.html );

var state = fragment;

while ( parser.index < parser.template.length ) {
        state = state( parser ) || fragment;
}

if ( parser.stack.length > 1 ) {
        var current = parser.current();

        var type = current.type === 'Element' ? ("<" + (current.name) + ">") : 'Block';
        parser.error( (type + " was left open"), current.start );
}

if ( state !== fragment ) {
        parser.error( 'Unexpected end of input' );
}

// trim unnecessary whitespace
while ( parser.html.children.length ) {
        var firstChild = parser.html.children[0];
        parser.html.start = firstChild.start;

        if ( firstChild.type !== 'Text' ) { break; }

        var length = firstChild.data.length;
        firstChild.data = trimStart( firstChild.data );

        if ( firstChild.data === '' ) {
                parser.html.children.shift();
        } else {
                parser.html.start += length - firstChild.data.length;
                break;
        }
}

while ( parser.html.children.length ) {
        var lastChild = parser.html.children[ parser.html.children.length - 1 ];
        parser.html.end = lastChild.end;

        if ( lastChild.type !== 'Text' ) { break; }

        var length$1 = lastChild.data.length;
        lastChild.data = trimEnd( lastChild.data );

        if ( lastChild.data === '' ) {
                parser.html.children.pop();
        } else {
                parser.html.end -= length$1 - lastChild.data.length;
                break;
        }
}

return {
        hash: hash( template ),
        html: parser.html,
        css: parser.css,
        js: parser.js
};

}

var disallowed = {

Literal: true,
ObjectExpression: true,
ArrayExpression: true

};

function data ( validator, prop ) {

while ( prop.type === 'ParenthesizedExpression' ) { prop = prop.expression; }

// TODO should we disallow references and expressions as well?

if ( disallowed[ prop.value.type ] ) {
        validator.error( "'data' must be a function", prop.value.start );
}

}

function checkForDupes ( validator, properties ) {

var seen = Object.create( null );

properties.forEach( function (prop) {
        if ( seen[ prop.key.name ] ) {
                validator.error( ("Duplicate property '" + (prop.key.name) + "'"), prop.start );
        }

        seen[ prop.key.name ] = true;
});

}

function checkForComputedKeys ( validator, properties ) {

properties.forEach( function (prop) {
        if ( prop.key.computed ) {
                validator.error( "Cannot use computed keys", prop.start );
        }
});

}

var isFunctionExpression = {

FunctionExpression: true,
ArrowFunctionExpression: true

};

function computed ( validator, prop ) {

if ( prop.value.type !== 'ObjectExpression' ) {
        validator.error( "The 'computed' property must be an object literal", prop.start );
        return;
}

checkForDupes( validator, prop.value.properties );
checkForComputedKeys( validator, prop.value.properties );

prop.value.properties.forEach( function (computation) {
        if ( !isFunctionExpression[ computation.value.type ] ) {
                validator.error( "Computed properties can be function expressions or arrow function expressions", computation.value.start );
                return;
        }

        var params = computation.value.params;

        if ( params.length === 0 ) {
                validator.error( "A computed value must depend on at least one property", computation.value.start );
                return;
        }

        params.forEach( function (param) {
                var valid = param.type === 'Identifier' || param.type === 'AssignmentPattern' && param.left.type === 'Identifier';

                if ( !valid ) {
                        validator.error( "Computed properties cannot use destructuring in function parameters", param.start );
                }
        });
});

}

function walk$2 ( ast, ref) {

var enter = ref.enter;
var leave = ref.leave;

visit( ast, null, enter, leave );

}

var context = {

skip: function () { return context.shouldSkip = true; },
shouldSkip: false

};

var childKeys = {};

var toString = Object.prototype.toString;

function isArray$1 ( thing ) {

return toString.call( thing ) === '[object Array]';

}

function visit ( node, parent, enter, leave, prop, index ) {

if ( !node ) { return; }

if ( enter ) {
        context.shouldSkip = false;
        enter.call( context, node, parent, prop, index );
        if ( context.shouldSkip ) { return; }
}

var keys = childKeys[ node.type ] || (
        childKeys[ node.type ] = Object.keys( node ).filter( function (key) { return typeof node[ key ] === 'object'; } )
);

for ( var i = 0; i < keys.length; i += 1 ) {
        var key = keys[i];
        var value = node[ key ];

        if ( isArray$1( value ) ) {
                for ( var j = 0; j < value.length; j += 1 ) {
                        visit( value[j], node, enter, leave, key, j );
                }
        }

        else if ( value && value.type ) {
                visit( value, node, enter, leave, key, null );
        }
}

if ( leave ) {
        leave( node, parent, prop, index );
}

}

function isReference ( node, parent ) {

if ( node.type === 'MemberExpression' ) {
        return !node.computed && isReference( node.object, node );
}

if ( node.type === 'Identifier' ) {
        // the only time we could have an identifier node without a parent is
        // if it's the entire body of a function without a block statement –
        // i.e. an arrow function expression like `a => a`
        if ( !parent ) { return true; }

        // TODO is this right?
        if ( parent.type === 'MemberExpression' || parent.type === 'MethodDefinition' ) {
                return parent.computed || node === parent.object;
        }

        // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
        if ( parent.type === 'Property' ) { return parent.computed || node === parent.value; }

        // disregard the `bar` in `class Foo { bar () {...} }`
        if ( parent.type === 'MethodDefinition' ) { return false; }

        // disregard the `bar` in `export { foo as bar }`
        if ( parent.type === 'ExportSpecifier' && node !== parent.local ) { return; }

        return true;
}

}

function usesThisOrArguments ( node ) {

var result = false;

walk$2( node, {
        enter: function enter ( node ) {
                if ( result || node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' ) {
                        return this.skip();
                }

                if ( node.type === 'ThisExpression' ) {
                        result = true;
                }

                if ( node.type === 'Identifier' && isReference( node ) && node.name === 'arguments' ) {
                        result = true;
                }
        }
});

return result;

}

function oncreate ( validator, prop ) {

if ( prop.value.type === 'ArrowFunctionExpression' ) {
        if ( usesThisOrArguments( prop.value.body ) ) {
                validator.error( "'oncreate' should be a function expression, not an arrow function expression", prop.start );
        }
}

}

function ondestroy ( validator, prop ) {

if ( prop.value.type === 'ArrowFunctionExpression' ) {
        if ( usesThisOrArguments( prop.value.body ) ) {
                validator.error( "'ondestroy' should be a function expression, not an arrow function expression", prop.start );
        }
}

}

function onrender ( validator, prop ) {

validator.warn( "'onrender' has been deprecated in favour of 'oncreate', and will cause an error in Svelte 2.x", prop.start );
oncreate( validator, prop );

}

function onteardown ( validator, prop ) {

validator.warn( "'onteardown' has been deprecated in favour of 'ondestroy', and will cause an error in Svelte 2.x", prop.start );
ondestroy( validator, prop );

}

function helpers ( validator, prop ) {

if ( prop.value.type !== 'ObjectExpression' ) {
        validator.error( "The 'helpers' property must be an object literal", prop.start );
        return;
}

checkForDupes( validator, prop.value.properties );
checkForComputedKeys( validator, prop.value.properties );

}

var builtin = {

set: true,
get: true,
on: true,
fire: true,
observe: true,
teardown: true

};

function methods ( validator, prop ) {

if ( prop.value.type !== 'ObjectExpression' ) {
        validator.error( "The 'methods' property must be an object literal", prop.start );
        return;
}

checkForDupes( validator, prop.value.properties );
checkForComputedKeys( validator, prop.value.properties );

prop.value.properties.forEach( function (prop) {
        if ( builtin[ prop.key.name ] ) {
                validator.error( ("Cannot overwrite built-in method '" + (prop.key.name) + "'") );
        }

        if ( prop.value.type === 'ArrowFunctionExpression' ) {
                if ( usesThisOrArguments( prop.value.body ) ) {
                        validator.error( ("Method '" + (prop.key.name) + "' should be a function expression, not an arrow function expression"), prop.start );
                }
        }
});

}

function components ( validator, prop ) {

if ( prop.value.type !== 'ObjectExpression' ) {
        validator.error( "The 'components' property must be an object literal", prop.start );
        return;
}

checkForDupes( validator, prop.value.properties );
checkForComputedKeys( validator, prop.value.properties );

prop.value.properties.forEach( function (component) {
        var char = component.key.name[0];
        if ( char === char.toLowerCase() ) {
                validator.warn( "Component names should be capitalised", component.start );
        }
});

}

function events ( validator, prop ) {

if ( prop.value.type !== 'ObjectExpression' ) {
        validator.error( "The 'events' property must be an object literal", prop.start );
        return;
}

checkForDupes( validator, prop.value.properties );
checkForComputedKeys( validator, prop.value.properties );

}

function namespace ( validator, prop ) {

if ( prop.value.type !== 'Literal' || typeof prop.value.value !== 'string' ) {
        validator.error( "The 'namespace' property must be a string literal representing a valid namespace", prop.start );
}

}

var propValidators = {

data: data,
computed: computed,
oncreate: oncreate,
ondestroy: ondestroy,
onrender: onrender,
onteardown: onteardown,
helpers: helpers,
methods: methods,
components: components,
events: events,
namespace: namespace

};

// adapted from github.com/Glench/this.js/blob/master/lib/this.js // BSD Licensed

function FuzzySet (arr, useLevenshtein, gramSizeLower, gramSizeUpper) {

var this$1 = this;

// default options
arr = arr || [];
this.gramSizeLower = gramSizeLower || 2;
this.gramSizeUpper = gramSizeUpper || 3;
this.useLevenshtein = (typeof useLevenshtein !== 'boolean') ? true : useLevenshtein;

// define all the object functions and attributes
this.exactSet = {};
this.matchDict = {};
this.items = {};

// helper functions
function levenshtein ( str1, str2 ) {
        var current = [];
        var prev;
        var value;

        for (var i = 0; i <= str2.length; i++) {
                for (var j = 0; j <= str1.length; j++) {
                        if (i && j) {
                                if (str1.charAt(j - 1) === str2.charAt(i - 1)) {
                                        value = prev;
                                } else {
                                        value = Math.min(current[j], current[j - 1], prev) + 1;
                                }
                        } else {
                                value = i + j;
                        }

                        prev = current[j];
                        current[j] = value;
                }
        }

        return current.pop();
}

// return an edit distance from 0 to 1
function _distance (str1, str2) {
        if (str1 === null && str2 === null) { throw 'Trying to compare two null values'; }
        if (str1 === null || str2 === null) { return 0; }
        str1 = String(str1); str2 = String(str2);

        var distance = levenshtein(str1, str2);
        if (str1.length > str2.length) {
                return 1 - distance / str1.length;
        } else {
                return 1 - distance / str2.length;
        }
}

var _nonWordRe = /[^\w, ]+/;

function _iterateGrams (value, gramSize) {
        gramSize = gramSize || 2;
        var simplified = '-' + value.toLowerCase().replace(_nonWordRe, '') + '-';
        var lenDiff = gramSize - simplified.length;
        var results = [];

        if (lenDiff > 0) {
                for (var i = 0; i < lenDiff; ++i) {
                        value += '-';
                }
        }
        for (var i$1 = 0; i$1 < simplified.length - gramSize + 1; ++i$1) {
                results.push(simplified.slice(i$1, i$1 + gramSize));
        }
        return results;
}

function _gramCounter (value, gramSize) {
        // return an object where key=gram, value=number of occurrences
        gramSize = gramSize || 2;
        var result = {};
        var grams = _iterateGrams(value, gramSize);
        var i = 0;

        for (i; i < grams.length; ++i) {
                if (grams[i] in result) {
                        result[grams[i]] += 1;
                } else {
                        result[grams[i]] = 1;
                }
        }
        return result;
}

// the main functions
this.get = function (value, defaultValue) {
        // check for value in set, returning defaultValue or null if none found
        var result = this._get(value);
        if (!result && typeof defaultValue !== 'undefined') {
                return defaultValue;
        }
        return result;
};

this._get = function (value) {
        var this$1 = this;

        var normalizedValue = this._normalizeStr(value);
        var result = this.exactSet[normalizedValue];

        if (result) {
                return [[1, result]];
        }

        var results = [];
        // start with high gram size and if there are no results, go to lower gram sizes
        for (var gramSize = this.gramSizeUpper; gramSize >= this.gramSizeLower; --gramSize) {
                results = this$1.__get(value, gramSize);
                if (results) {
                        return results;
                }
        }
        return null;
};

this.__get = function (value, gramSize) {
        var this$1 = this;

        var normalizedValue = this._normalizeStr(value);
        var matches = {};
        var gramCounts = _gramCounter(normalizedValue, gramSize);
        var items = this.items[gramSize];
        var sumOfSquareGramCounts = 0;
        var gram;
        var gramCount;
        var i;
        var index;
        var otherGramCount;

        for (gram in gramCounts) {
                gramCount = gramCounts[gram];
                sumOfSquareGramCounts += Math.pow(gramCount, 2);
                if (gram in this$1.matchDict) {
                        for (i = 0; i < this.matchDict[gram].length; ++i) {
                                index = this$1.matchDict[gram][i][0];
                                otherGramCount = this$1.matchDict[gram][i][1];
                                if (index in matches) {
                                        matches[index] += gramCount * otherGramCount;
                                } else {
                                        matches[index] = gramCount * otherGramCount;
                                }
                        }
                }
        }

        function isEmptyObject ( obj ) {
                for ( var prop in obj ) {
                        if ( obj.hasOwnProperty( prop ) )
                                { return false; }
                }
                return true;
        }

        if (isEmptyObject(matches)) {
                return null;
        }

        var vectorNormal = Math.sqrt(sumOfSquareGramCounts);
        var results = [];
        var matchScore;

        // build a results list of [score, str]
        for (var matchIndex in matches) {
                matchScore = matches[matchIndex];
                results.push([matchScore / (vectorNormal * items[matchIndex][0]), items[matchIndex][1]]);
        }
        function sortDescending (a, b) {
                if (a[0] < b[0]) {
                        return 1;
                } else if (a[0] > b[0]) {
                        return -1;
                } else {
                        return 0;
                }
        }

        results.sort(sortDescending);
        if (this.useLevenshtein) {
                var newResults$1 = [];
                var endIndex = Math.min(50, results.length);
                // truncate somewhat arbitrarily to 50
                for (var i$1 = 0; i$1 < endIndex; ++i$1) {
                        newResults$1.push([_distance(results[i$1][1], normalizedValue), results[i$1][1]]);
                }
                results = newResults$1;
                results.sort(sortDescending);
        }
        var newResults = [];
        for (var i$2 = 0; i$2 < results.length; ++i$2) {
                if (results[i$2][0] == results[0][0]) {
                        newResults.push([results[i$2][0], this$1.exactSet[results[i$2][1]]]);
                }
        }
        return newResults;
};

this.add = function (value) {
        var this$1 = this;

        var normalizedValue = this._normalizeStr(value);
        if (normalizedValue in this.exactSet) {
                return false;
        }

        var i = this.gramSizeLower;
        for (i; i < this.gramSizeUpper + 1; ++i) {
                this$1._add(value, i);
        }
};

this._add = function (value, gramSize) {
        var this$1 = this;

        var normalizedValue = this._normalizeStr(value);
        var items = this.items[gramSize] || [];
        var index = items.length;

        items.push(0);
        var gramCounts = _gramCounter(normalizedValue, gramSize);
        var sumOfSquareGramCounts = 0;
        var gram;
        var gramCount;

        for (gram in gramCounts) {
                gramCount = gramCounts[gram];
                sumOfSquareGramCounts += Math.pow(gramCount, 2);
                if (gram in this$1.matchDict) {
                        this$1.matchDict[gram].push([index, gramCount]);
                } else {
                        this$1.matchDict[gram] = [[index, gramCount]];
                }
        }
        var vectorNormal = Math.sqrt(sumOfSquareGramCounts);
        items[index] = [vectorNormal, normalizedValue];
        this.items[gramSize] = items;
        this.exactSet[normalizedValue] = value;
};

this._normalizeStr = function (str) {
        if (Object.prototype.toString.call(str) !== '[object String]') { throw 'Must use a string as argument to FuzzySet functions'; }
        return str.toLowerCase();
};

// return length of items in set
this.length = function () {
        var this$1 = this;

        var count = 0;
        var prop;

        for (prop in this$1.exactSet) {
                if (this$1.exactSet.hasOwnProperty(prop)) {
                        count += 1;
                }
        }
        return count;
};

// return is set is empty
this.isEmpty = function () {
        var this$1 = this;

        for (var prop in this$1.exactSet) {
                if (this$1.exactSet.hasOwnProperty(prop)) {
                        return false;
                }
        }
        return true;
};

// return list of values loaded into set
this.values = function () {
        var this$1 = this;

        var values = [];

        for (var prop in this$1.exactSet) {
                if (this$1.exactSet.hasOwnProperty(prop)) {
                        values.push(this$1.exactSet[prop]);
                }
        }
        return values;
};

// initialization
var i = this.gramSizeLower;
for (i; i < this.gramSizeUpper + 1; ++i) {
        this$1.items[i] = [];
}
// add all the items to the set
for (i = 0; i < arr.length; ++i) {
        this$1.add(arr[i]);
}

return this;

}

var html = 'www.w3.org/1999/xhtml'; var mathml = 'www.w3.org/1998/Math/MathML'; var svg = 'www.w3.org/2000/svg'; var xlink = 'www.w3.org/1999/xlink'; var xml = 'www.w3.org/XML/1998/namespace'; var xmlns = 'www.w3.org/2000/xmlns';

var namespaces = { html: html, mathml: mathml, svg: svg, xlink: xlink, xml: xml, xmlns: xmlns };

var validPropList = Object.keys( propValidators );

var fuzzySet = new FuzzySet( validPropList );

function validateJs ( validator, js ) {

js.content.body.forEach( function (node) {
        // check there are no named exports
        if ( node.type === 'ExportNamedDeclaration' ) {
                validator.error( "A component can only have a default export", node.start );
        }

        if ( node.type === 'ExportDefaultDeclaration' ) {
                if ( node.declaration.type !== 'ObjectExpression' ) {
                        return validator.error( "Default export must be an object literal", node.declaration.start );
                }

                checkForComputedKeys( validator, node.declaration.properties );
                checkForDupes( validator, node.declaration.properties );

                var templateProperties = {};

                node.declaration.properties.forEach( function (prop) {
                        templateProperties[ prop.key.name ] = prop;
                });

                // Remove these checks in version 2
                if ( templateProperties.oncreate && templateProperties.onrender ) {
                        validator.error( 'Cannot have both oncreate and onrender', templateProperties.onrender.start );
                }

                if ( templateProperties.ondestroy && templateProperties.onteardown ) {
                        validator.error( 'Cannot have both ondestroy and onteardown', templateProperties.onteardown.start );
                }

                // ensure all exported props are valid
                node.declaration.properties.forEach( function (prop) {
                        var propValidator = propValidators[ prop.key.name ];

                        if ( propValidator ) {
                                propValidator( validator, prop );
                        } else {
                                var matches = fuzzySet.get( prop.key.name );
                                if ( matches && matches[0] && matches[0][0] > 0.7 ) {
                                        validator.error( ("Unexpected property '" + (prop.key.name) + "' (did you mean '" + (matches[0][1]) + "'?)"), prop.start );
                                } else if ( /FunctionExpression/.test( prop.value.type ) ) {
                                        validator.error( ("Unexpected property '" + (prop.key.name) + "' (did you mean to include it in 'methods'?)"), prop.start );
                                } else {
                                        validator.error( ("Unexpected property '" + (prop.key.name) + "'"), prop.start );
                                }
                        }
                });

                if ( templateProperties.namespace ) {
                        var ns = templateProperties.namespace.value.value;
                        validator.namespace = namespaces[ ns ] || ns;
                }

                validator.defaultExport = node;
        }
});

}

var svg$1 = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|switch|symbol|text|textPath|title|tref|tspan|unknown|use|view|vkern)$/;

function validateHtml ( validator, html$$1 ) {

var elementDepth = 0;

function visit ( node ) {
        if ( node.type === 'EachBlock' ) {
                if ( !~validator.names.indexOf( node.context ) ) { validator.names.push( node.context ); }
                if ( node.index && !~validator.names.indexOf( node.index ) ) { validator.names.push( node.index ); }
        }

        if ( node.type === 'Element' ) {
                if ( elementDepth === 0 && validator.namespace !== svg && svg$1.test( node.name ) ) {
                        validator.warn( ("<" + (node.name) + "> is an SVG element – did you forget to add { namespace: 'svg' } ?"), node.start );
                }

                elementDepth += 1;
        }

        if ( node.children ) {
                node.children.forEach( visit );
        }

        if (node.else ) {
                visit( node.else );
        }

        if ( node.type === 'Element' ) {
                elementDepth -= 1;
        }
}

html$$1.children.forEach( visit );

}

function validate ( parsed, source, ref ) {

var onerror = ref.onerror;
var onwarn = ref.onwarn;
var name = ref.name;
var filename = ref.filename;

var locator = getLocator( source );

var validator = {
        error: function ( message, pos ) {
                var ref = locator( pos );
                var line = ref.line;
                var column = ref.column;

                var error = new Error( message );
                error.frame = getCodeFrame( source, line, column );
                error.loc = { line: line + 1, column: column };
                error.pos = pos;
                error.filename = filename;

                error.toString = function () { return ((error.message) + " (" + (error.loc.line) + ":" + (error.loc.column) + ")\n" + (error.frame)); };

                onerror( error );
        },

        warn: function ( message, pos ) {
                var ref = locator( pos );
                var line = ref.line;
                var column = ref.column;

                var frame = getCodeFrame( source, line, column );

                onwarn({
                        message: message,
                        frame: frame,
                        loc: { line: line + 1, column: column },
                        pos: pos,
                        filename: filename,
                        toString: function () { return (message + " (" + (line + 1) + ":" + column + ")\n" + frame); }
                });
        },

        names: [],

        namespace: null
};

if ( name && !/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test( name ) ) {
        var error = new Error( "options.name must be a valid identifier" );
        onerror( error );
}

if ( parsed.js ) {
        validateJs( validator, parsed.js );
}

if ( parsed.html ) {
        validateHtml( validator, parsed.html );
}

return {
        names: validator.names
};

}

var start = /n(t+)/;

function deindent ( strings ) {

var values = [], len = arguments.length - 1;
while ( len-- > 0 ) values[ len ] = arguments[ len + 1 ];

var indentation = start.exec( strings[0] )[1];
var pattern = new RegExp( ("^" + indentation), 'gm' );

var result = strings[0].replace( start, '' ).replace( pattern, '' );

var trailingIndentation = getTrailingIndentation( result );

for ( var i = 1; i < strings.length; i += 1 ) {
        var value  = String( values[ i - 1 ] ).replace( /\n/g, ("\n" + trailingIndentation) );
        result += value + strings[i].replace( pattern, '' );

        trailingIndentation = getTrailingIndentation( result );
}

return result.trim();

}

function getTrailingIndentation ( str ) {

var i = str.length;
while ( str[ i - 1 ] === ' ' || str[ i - 1 ] === '\t' ) { i -= 1; }
return str.slice( i, str.length );

}

var LINE = {}; var BLOCK = {};

var CodeBuilder = function CodeBuilder () {

this.result = '';

this.first = null;
this.last = null;

};

CodeBuilder.prototype.addLine = function addLine ( line ) {

if ( this.last === BLOCK ) {
        this.result += "\n\n" + line;
} else if ( this.last === LINE ) {
        this.result += "\n" + line;
} else {
        this.result += line;
}

this.last = LINE;
if ( !this.first ) { this.first = LINE; }

};

CodeBuilder.prototype.addLineAtStart = function addLineAtStart ( line ) {

if ( this.first === BLOCK ) {
        this.result = line + "\n\n" + (this.result);
} else if ( this.first === LINE ) {
        this.result = line + "\n" + (this.result);
} else {
        this.result += line;
}

this.first = LINE;
if ( !this.last ) { this.last = LINE; }

};

CodeBuilder.prototype.addBlock = function addBlock ( block ) {

if ( this.result ) {
        this.result += "\n\n" + block;
} else {
        this.result += block;
}

this.last = BLOCK;
if ( !this.first ) { this.first = BLOCK; }

};

CodeBuilder.prototype.addBlockAtStart = function addBlockAtStart ( block ) {

if ( this.result ) {
        this.result = block + "\n\n" + (this.result);
} else {
        this.result += block;
}

this.first = BLOCK;
if ( !this.last ) { this.last = BLOCK; }

};

CodeBuilder.prototype.isEmpty = function isEmpty () {

return this.result === '';

};

CodeBuilder.prototype.toString = function toString () {

return this.result.trim();

};

function getBuilders () {

return {
        init: new CodeBuilder(),
        mount: new CodeBuilder(),
        update: new CodeBuilder(),
        detach: new CodeBuilder(),
        detachRaw: new CodeBuilder(),
        teardown: new CodeBuilder()
};

}

var commentsPattern = //*[sS]*?*//g;

function processCss ( parsed, code ) {

var css = parsed.css.content.styles;
var offset = parsed.css.content.start;

var attr = "[svelte-" + (parsed.hash) + "]";

var keyframes = new Map();

function walkKeyframes ( node ) {
        if ( node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes' ) {
                node.expression.children.forEach( function (expression) {
                        if ( expression.type === 'Identifier' ) {
                                var newName = "svelte-" + (parsed.hash) + "-" + (expression.name);
                                code.overwrite( expression.start, expression.end, newName );
                                keyframes.set( expression.name, newName );
                        }
                });
        } else if ( node.children ) {
                node.children.forEach( walkKeyframes );
        } else if ( node.block ) {
                walkKeyframes( node.block );
        }
}

parsed.css.children.forEach( walkKeyframes );

function transform ( rule ) {
        rule.selector.children.forEach( function (selector) {
                var start = selector.start - offset;
                var end = selector.end - offset;

                var selectorString = css.slice( start, end );

                var firstToken = selector.children[0];

                var transformed;

                if ( firstToken.type === 'TypeSelector' ) {
                        var insert = firstToken.end - offset;
                        var head = css.slice( start, insert );
                        var tail = css.slice( insert, end );

                        transformed = "" + head + attr + tail + ", " + attr + " " + selectorString;
                } else {
                        transformed = "" + attr + selectorString + ", " + attr + " " + selectorString;
                }

                code.overwrite( start + offset, end + offset, transformed );
        });

        rule.block.children.forEach( function (block) {
                if ( block.type === 'Declaration' ) {
                        var property = block.property.toLowerCase();
                        if ( property === 'animation' || property === 'animation-name' ) {
                                block.value.children.forEach( function (block) {
                                        if ( block.type === 'Identifier' ) {
                                                var name = block.name;
                                                if ( keyframes.has( name ) ) {
                                                        code.overwrite( block.start, block.end, keyframes.get( name ) );
                                                }
                                        }
                                });
                        }
                }
        });
}

function walk ( node ) {
        if ( node.type === 'Rule' ) {
                transform( node );
        } else if ( node.type === 'Atrule' && node.name.toLowerCase() === 'keyframes' ) {
                // these have already been processed
        } else if ( node.children ) {
                node.children.forEach( walk );
        } else if ( node.block ) {
                walk( node.block );
        }
}

parsed.css.children.forEach( walk );

// remove comments. TODO would be nice if this was exposed in css-tree
var match;
while ( match = commentsPattern.exec( css ) ) {
        var start = match.index + offset;
        var end = start + match[0].length;

        code.remove( start, end );
}

return code.slice( parsed.css.content.start, parsed.css.content.end );

}

function removeObjectKey ( generator, node, key ) {

if ( node.type !== 'ObjectExpression' ) { return; }
var properties = node.properties;
var index = properties.findIndex( function (property) { return property.key.type === 'Identifier' && property.key.name === key; } );
if ( index === -1 ) { return; }
var a = properties[ index ].start;
var b = index < properties.length - 1 ? properties[ index + 1 ].start : properties[ index ].end;
generator.code.remove( a, b );

}

var Comment$2 = {

// do nothing

};

var reserved = {

component: true,
root: true

};

var EachBlock = {

enter: function enter ( generator, node ) {
        var name = generator.getUniqueName( "eachBlock" );
        var renderer = generator.getUniqueName( "renderEachBlock" );
        var elseName = name + "_else";
        var iterations = name + "_iterations";
        var renderElse = renderer + "_else";
        var i = generator.current.getUniqueName( "i" );
        var ref = generator.current;
        var params = ref.params;

        var listName = name + "_value";

        var isToplevel = generator.current.localElementDepth === 0;

        generator.addSourcemapLocations( node.expression );

        var ref$1 = generator.contextualise( node.expression );
        var dependencies = ref$1.dependencies;
        var snippet = ref$1.snippet;

        var anchor = name + "_anchor";
        generator.createAnchor( anchor );

        generator.current.builders.init.addLine( ("var " + name + "_value = " + snippet + ";") );
        generator.current.builders.init.addLine( ("var " + iterations + " = [];") );
        if ( node.key ) { generator.current.builders.init.addLine( ("var " + name + "_lookup = Object.create( null );") ); }
        if ( node.else ) { generator.current.builders.init.addLine( ("var " + elseName + " = null;") ); }

        var initialRender = new CodeBuilder();

        var localVars = {};

        if ( node.key ) {
                localVars.fragment = generator.current.getUniqueName( 'fragment' );
                localVars.value = generator.current.getUniqueName( 'value' );
                localVars.key = generator.current.getUniqueName( 'key' );

                initialRender.addBlock( deindent(["\n\t\t\t\tvar ", " = ", "_value[", "].", ";\n\t\t\t\t", "_iterations[", "] = ", "_lookup[ ", " ] = ", "( ", ", ", ", ", "[", "], ", ", component", " );\n\t\t\t"], localVars.key, name, i, node.key, name, i, name, localVars.key, renderer, params, listName, listName, i, i, node.key ? (", " + (localVars.key)) : "") );
        } else {
                initialRender.addLine(
                        (name + "_iterations[" + i + "] = " + renderer + "( " + params + ", " + listName + ", " + listName + "[" + i + "], " + i + ", component );")
                );
        }

        if ( !isToplevel ) {
                initialRender.addLine(
                        (name + "_iterations[" + i + "].mount( " + anchor + ".parentNode, " + anchor + " );")
                );
        }

        generator.current.builders.init.addBlock( deindent(["\n\t\t\tfor ( var ", " = 0; ", " < ", "_value.length; ", " += 1 ) {\n\t\t\t\t", "\n\t\t\t}\n\t\t"], i, i, name, i, initialRender) );

        if ( node.else ) {
                generator.current.builders.init.addBlock( deindent(["\n\t\t\t\tif ( !", "_value.length ) {\n\t\t\t\t\t", " = ", "( ", ", component );\n\t\t\t\t\t", "\n\t\t\t\t}\n\t\t\t"], name, elseName, renderElse, params, !isToplevel ? (elseName + ".mount( " + anchor + ".parentNode, " + anchor + " );") : '') );
        }

        if ( isToplevel ) {
                generator.current.builders.mount.addBlock( deindent(["\n\t\t\t\tfor ( var ", " = 0; ", " < ", ".length; ", " += 1 ) {\n\t\t\t\t\t", "[", "].mount( ", ".parentNode, ", " );\n\t\t\t\t}\n\t\t\t"], i, i, iterations, i, iterations, i, anchor, anchor) );
                if ( node.else ) {
                        generator.current.builders.mount.addBlock( deindent(["\n\t\t\t\t\tif ( ", " ) {\n\t\t\t\t\t\t", ".mount( ", ".parentNode, ", " );\n\t\t\t\t\t}\n\t\t\t\t"], elseName, elseName, anchor, anchor) );
                }
        }

        if ( node.key ) {
                generator.current.builders.update.addBlock( deindent(["\n\t\t\t\tvar ", "_value = ", ";\n\t\t\t\tvar _", "_iterations = [];\n\t\t\t\tvar _", "_lookup = Object.create( null );\n\n\t\t\t\tvar ", " = document.createDocumentFragment();\n\n\t\t\t\t// create new iterations as necessary\n\t\t\t\tfor ( var ", " = 0; ", " < ", "_value.length; ", " += 1 ) {\n\t\t\t\t\tvar ", " = ", "_value[", "];\n\t\t\t\t\tvar ", " = ", ".", ";\n\n\t\t\t\t\tif ( ", "_lookup[ ", " ] ) {\n\t\t\t\t\t\t_", "_iterations[", "] = _", "_lookup[ ", " ] = ", "_lookup[ ", " ];\n\t\t\t\t\t\t_", "_lookup[ ", " ].update( changed, ", ", ", ", ", "[", "], ", " );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t_", "_iterations[", "] = _", "_lookup[ ", " ] = ", "( ", ", ", ", ", "[", "], ", ", component", " );\n\t\t\t\t\t}\n\n\t\t\t\t\t_", "_iterations[", "].mount( ", ", null );\n\t\t\t\t}\n\n\t\t\t\t// remove old iterations\n\t\t\t\tfor ( var ", " = 0; ", " < ", "_iterations.length; ", " += 1 ) {\n\t\t\t\t\tvar ", "_iteration = ", "_iterations[", "];\n\t\t\t\t\tif ( !_", "_lookup[ ", "_iteration.", " ] ) {\n\t\t\t\t\t\t", "_iteration.teardown( true );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t", "_anchor.parentNode.insertBefore( ", ", ", "_anchor );\n\n\t\t\t\t", "_iterations = _", "_iterations;\n\t\t\t\t", "_lookup = _", "_lookup;\n\t\t\t"], name, snippet, name, name, localVars.fragment, i, i, name, i, localVars.value, name, i, localVars.key, localVars.value, node.key, name, localVars.key, name, i, name, localVars.key, name, localVars.key, name, localVars.key, params, listName, listName, i, i, name, i, name, localVars.key, renderer, params, listName, listName, i, i, node.key ? (", " + (localVars.key)) : "", name, i, localVars.fragment, i, i, name, i, name, name, i, name, name, localVars.key, name, name, localVars.fragment, name, name, name, name, name) );
        } else {
                generator.current.builders.update.addBlock( deindent(["\n\t\t\t\tvar ", "_value = ", ";\n\n\t\t\t\tfor ( var ", " = 0; ", " < ", "_value.length; ", " += 1 ) {\n\t\t\t\t\tif ( !", "[", "] ) {\n\t\t\t\t\t\t", "[", "] = ", "( ", ", ", ", ", "[", "], ", ", component );\n\t\t\t\t\t\t", "[", "].mount( ", ".parentNode, ", " );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t", "[", "].update( changed, ", ", ", ", ", "[", "], ", " );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tteardownEach( ", ", true, ", "_value.length );\n\n\t\t\t\t", ".length = ", ".length;\n\t\t\t"], name, snippet, i, i, name, i, iterations, i, iterations, i, renderer, params, listName, listName, i, i, iterations, i, anchor, anchor, iterations, i, params, listName, listName, i, i, iterations, name, iterations, listName) );
        }

        if ( node.else ) {
                generator.current.builders.update.addBlock( deindent(["\n\t\t\t\tif ( !", "_value.length && ", " ) {\n\t\t\t\t\t", ".update( changed, ", " );\n\t\t\t\t} else if ( !", "_value.length ) {\n\t\t\t\t\t", " = ", "( ", ", component );\n\t\t\t\t\t", ".mount( ", ".parentNode, ", " );\n\t\t\t\t} else if ( ", " ) {\n\t\t\t\t\t", ".teardown( true );\n\t\t\t\t}\n\t\t\t"], name, elseName, elseName, params, name, elseName, renderElse, params, elseName, anchor, anchor, elseName, elseName) );
        }

        generator.current.builders.teardown.addBlock(
                ((generator.helper( 'teardownEach' )) + "( " + iterations + ", " + (isToplevel ? 'detach' : 'false') + " );") );

        if ( node.else ) {
                generator.current.builders.teardown.addBlock( deindent(["\n\t\t\t\tif ( ", " ) {\n\t\t\t\t\t", ".teardown( ", " );\n\t\t\t\t}\n\t\t\t"], elseName, elseName, isToplevel ? 'detach' : 'false') );
        }

        if ( node.else ) {
                generator.generateBlock( node.else, renderElse );
        }

        var indexNames = Object.assign( {}, generator.current.indexNames );
        var indexName = indexNames[ node.context ] = ( node.index || ((node.context) + "__index") );

        var listNames = Object.assign( {}, generator.current.listNames );
        listNames[ node.context ] = listName;

        // ensure that contexts like `root` or `component` don't blow up the whole show
        var context = node.context;
        var c = 1;

        while ( context in reserved || ~generator.current.params.indexOf( context ) ) {
                context = (node.context) + "$" + (c++);
        }

        var contexts = Object.assign( {}, generator.current.contexts );
        contexts[ node.context ] = context;

        var indexes = Object.assign( {}, generator.current.indexes );
        if ( node.index ) { indexes[ indexName ] = node.context; }

        var contextDependencies = Object.assign( {}, generator.current.contextDependencies );
        contextDependencies[ node.context ] = dependencies;

        var blockParams = generator.current.params.concat( listName, context, indexName );

        generator.push({
                name: renderer,
                target: 'target',
                expression: node.expression,
                context: node.context,
                key: node.key,
                localElementDepth: 0,

                contextDependencies: contextDependencies,
                contexts: contexts,
                indexes: indexes,

                indexNames: indexNames,
                listNames: listNames,
                params: blockParams,

                builders: getBuilders(),
                getUniqueName: generator.getUniqueNameMaker()
        });
},

leave: function leave ( generator ) {
        generator.addRenderer( generator.current );
        generator.pop();
}

};

// source: developer.mozilla.org/en-US/docs/Web/HTML/Attributes var lookup = {

accept: { appliesTo: [ 'form', 'input' ] },
'accept-charset': { propertyName: 'acceptCharset', appliesTo: [ 'form' ] },
accesskey: { propertyName: 'accessKey' },
action: { appliesTo: [ 'form' ] },
align: { appliesTo: [ 'applet', 'caption', 'col', 'colgroup', 'hr', 'iframe', 'img', 'table', 'tbody', 'td', 'tfoot' , 'th', 'thead', 'tr' ] },
allowfullscreen: { propertyName: 'allowFullscreen', appliesTo: [ 'iframe' ] },
alt: { appliesTo: [ 'applet', 'area', 'img', 'input' ] },
async: { appliesTo: [ 'script' ] },
autocomplete: { appliesTo: [ 'form', 'input' ] },
autofocus: { appliesTo: [ 'button', 'input', 'keygen', 'select', 'textarea' ] },
autoplay: { appliesTo: [ 'audio', 'video' ] },
autosave: { appliesTo: [ 'input' ] },
bgcolor: { propertyName: 'bgColor', appliesTo: [ 'body', 'col', 'colgroup', 'marquee', 'table', 'tbody', 'tfoot', 'td', 'th', 'tr' ] },
border: { appliesTo: [ 'img', 'object', 'table' ] },
buffered: { appliesTo: [ 'audio', 'video' ] },
challenge: { appliesTo: [ 'keygen' ] },
charset: { appliesTo: [ 'meta', 'script' ] },
checked: { appliesTo: [ 'command', 'input' ] },
cite: { appliesTo: [ 'blockquote', 'del', 'ins', 'q' ] },
class: { propertyName: 'className' },
code: { appliesTo: [ 'applet' ] },
codebase: { propertyName: 'codeBase', appliesTo: [ 'applet' ] },
color: { appliesTo: [ 'basefont', 'font', 'hr' ] },
cols: { appliesTo: [ 'textarea' ] },
colspan: { propertyName: 'colSpan', appliesTo: [ 'td', 'th' ] },
content: { appliesTo: [ 'meta' ] },
contenteditable: { propertyName: 'contentEditable' },
contextmenu: {},
controls: { appliesTo: [ 'audio', 'video' ] },
coords: { appliesTo: [ 'area' ] },
data: { appliesTo: [ 'object' ] },
datetime: { propertyName: 'dateTime', appliesTo: [ 'del', 'ins', 'time' ] },
default: { appliesTo: [ 'track' ] },
defer: { appliesTo: [ 'script' ] },
dir: {},
dirname: { propertyName: 'dirName', appliesTo: [ 'input', 'textarea' ] },
disabled: { appliesTo: [ 'button', 'command', 'fieldset', 'input', 'keygen', 'optgroup', 'option', 'select', 'textarea' ] },
download: { appliesTo: [ 'a', 'area' ] },
draggable: {},
dropzone: {},
enctype: { appliesTo: [ 'form' ] },
for: { propertyName: 'htmlFor', appliesTo: [ 'label', 'output' ] },
form: { appliesTo: [ 'button', 'fieldset', 'input', 'keygen', 'label', 'meter', 'object', 'output', 'progress', 'select', 'textarea' ] },
formaction: { appliesTo: [ 'input', 'button' ] },
headers: { appliesTo: [ 'td', 'th' ] },
height: { appliesTo: [ 'canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video' ] },
hidden: {},
high: { appliesTo: [ 'meter' ] },
href: { appliesTo: [ 'a', 'area', 'base', 'link' ] },
hreflang: { appliesTo: [ 'a', 'area', 'link' ] },
'http-equiv': { propertyName: 'httpEquiv', appliesTo: [ 'meta' ] },
icon: { appliesTo: [ 'command' ] },
id: {},
ismap: { propertyName: 'isMap', appliesTo: [ 'img' ] },
itemprop: {},
keytype: { appliesTo: [ 'keygen' ] },
kind: { appliesTo: [ 'track' ] },
label: { appliesTo: [ 'track' ] },
lang: {},
language: { appliesTo: [ 'script' ] },
loop: { appliesTo: [ 'audio', 'bgsound', 'marquee', 'video' ] },
low: { appliesTo: [ 'meter' ] },
manifest: { appliesTo: [ 'html' ] },
max: { appliesTo: [ 'input', 'meter', 'progress' ] },
maxlength: { propertyName: 'maxLength', appliesTo: [ 'input', 'textarea' ] },
media: { appliesTo: [ 'a', 'area', 'link', 'source', 'style' ] },
method: { appliesTo: [ 'form' ] },
min: { appliesTo: [ 'input', 'meter' ] },
multiple: { appliesTo: [ 'input', 'select' ] },
muted: { appliesTo: [ 'video' ] },
name: { appliesTo: [ 'button', 'form', 'fieldset', 'iframe', 'input', 'keygen', 'object', 'output', 'select', 'textarea', 'map', 'meta', 'param' ] },
novalidate: { propertyName: 'noValidate', appliesTo: [ 'form' ] },
open: { appliesTo: [ 'details' ] },
optimum: { appliesTo: [ 'meter' ] },
pattern: { appliesTo: [ 'input' ] },
ping: { appliesTo: [ 'a', 'area' ] },
placeholder: { appliesTo: [ 'input', 'textarea' ] },
poster: { appliesTo: [ 'video' ] },
preload: { appliesTo: [ 'audio', 'video' ] },
radiogroup: { appliesTo: [ 'command' ] },
readonly: { propertyName: 'readOnly', appliesTo: [ 'input', 'textarea' ] },
rel: { appliesTo: [ 'a', 'area', 'link' ] },
required: { appliesTo: [ 'input', 'select', 'textarea' ] },
reversed: { appliesTo: [ 'ol' ] },
rows: { appliesTo: [ 'textarea' ] },
rowspan: { propertyName: 'rowSpan', appliesTo: [ 'td', 'th' ] },
sandbox: { appliesTo: [ 'iframe' ] },
scope: { appliesTo: [ 'th' ] },
scoped: { appliesTo: [ 'style' ] },
seamless: { appliesTo: [ 'iframe' ] },
selected: { appliesTo: [ 'option' ] },
shape: { appliesTo: [ 'a', 'area' ] },
size: { appliesTo: [ 'input', 'select' ] },
sizes: { appliesTo: [ 'link', 'img', 'source' ] },
span: { appliesTo: [ 'col', 'colgroup' ] },
spellcheck: {},
src: { appliesTo: [ 'audio', 'embed', 'iframe', 'img', 'input', 'script', 'source', 'track', 'video' ] },
srcdoc: { appliesTo: [ 'iframe' ] },
srclang: { appliesTo: [ 'track' ] },
srcset: { appliesTo: [ 'img' ] },
start: { appliesTo: [ 'ol' ] },
step: { appliesTo: [ 'input' ] },
style: { propertyName: 'style.cssText' },
summary: { appliesTo: [ 'table' ] },
tabindex: { propertyName: 'tabIndex' },
target: { appliesTo: [ 'a', 'area', 'base', 'form' ] },
title: {},
type: { appliesTo: [ 'button', 'input', 'command', 'embed', 'object', 'script', 'source', 'style', 'menu' ] },
usemap: { propertyName: 'useMap', appliesTo: [ 'img', 'input', 'object' ] },
value: { appliesTo: [ 'button', 'option', 'input', 'li', 'meter', 'progress', 'param' ] },
width: { appliesTo: [ 'canvas', 'embed', 'iframe', 'img', 'input', 'object', 'video' ] },
wrap: { appliesTo: [ 'textarea' ] }

};

Object.keys( lookup ).forEach( function (name) {

var metadata = lookup[ name ];
if ( !metadata.propertyName ) { metadata.propertyName = name; }

});

function flatten ( node ) {

var parts = [];
while ( node.type === 'MemberExpression' ) {
        if ( node.computed ) { return null; }
        parts.unshift( node.property.name );

        node = node.object;
}

var name = node.type === 'Identifier' ? node.name : node.type === 'ThisExpression' ? 'this' : null;

if ( !name ) { return null; }

parts.unshift( name );
return { name: name, parts: parts, keypath: parts.join( '.' ) };

}

function getSetter (ref) {

var current = ref.current;
var name = ref.name;
var context = ref.context;
var attribute = ref.attribute;
var dependencies = ref.dependencies;
var snippet = ref.snippet;
var value = ref.value;

if ( name in current.contexts ) {
        var prop = dependencies[0];
        var tail = attribute.value.type === 'MemberExpression' ? getTailSnippet( attribute.value ) : '';

        return deindent(["\n\t\t\tvar list = this.", ".", ";\n\t\t\tvar index = this.", ".", ";\n\t\t\tlist[index]", " = ", ";\n\n\t\t\tcomponent._set({ ", ": component.get( '", "' ) });\n\t\t"], context, current.listNames[ name ], context, current.indexNames[ name ], tail, value, prop, prop);
}

if ( attribute.value.type === 'MemberExpression' ) {
        return deindent(["\n\t\t\tvar ", " = component.get( '", "' );\n\t\t\t", " = ", ";\n\t\t\tcomponent._set({ ", ": ", " });\n\t\t"], name, name, snippet, value, name, name);
}

return ("component._set({ " + name + ": " + value + " });");

}

function getTailSnippet ( node ) {

var end = node.end;
while ( node.type === 'MemberExpression' ) { node = node.object; }
var start = node.end;

return ("[✂" + start + "-" + end + "✂]");

}

function getStaticAttributeValue ( node, name ) {

var attribute = node.attributes.find( function (attr) { return attr.name.toLowerCase() === name; } );
if ( !attribute ) { return null; }

if ( attribute.value.length !== 1 || attribute.value[0].type !== 'Text' ) {
        // TODO catch this in validation phase, give a more useful error (with location etc)
        throw new Error( ("'" + name + " must be a static attribute") );
}

return attribute.value[0].data;

}

function createBinding ( generator, node, attribute, current, local ) {

var ref = flatten( attribute.value );
var name = ref.name;
var keypath = ref.keypath;
var ref$1 = generator.contextualise( attribute.value );
var snippet = ref$1.snippet;
var contexts = ref$1.contexts;
var dependencies = ref$1.dependencies;

if ( dependencies.length > 1 ) { throw new Error( 'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!' ); }

contexts.forEach( function (context) {
        if ( !~local.allUsedContexts.indexOf( context ) ) { local.allUsedContexts.push( context ); }
});

var handler = current.getUniqueName( ((local.name) + "ChangeHandler") );

var isMultipleSelect = node.name === 'select' && node.attributes.find( function (attr) { return attr.name.toLowerCase() === 'multiple'; } ); // TODO use getStaticAttributeValue
var type = getStaticAttributeValue( node, 'type' );
var bindingGroup = attribute.name === 'group' ? getBindingGroup( generator, current, attribute, keypath ) : null;
var value = getBindingValue( generator, local, node, attribute, isMultipleSelect, bindingGroup, type );
var eventName = getBindingEventName( node );

var setter = getSetter({ current: current, name: name, context: '__svelte', attribute: attribute, dependencies: dependencies, snippet: snippet, value: value });
var updateElement;

// <select> special case
if ( node.name === 'select' ) {
        if ( !isMultipleSelect ) {
                setter = "var selectedOption = " + (local.name) + ".selectedOptions[0] || " + (local.name) + ".options[0];\n" + setter;
        }

        var value$1 = generator.current.getUniqueName( 'value' );
        var i = generator.current.getUniqueName( 'i' );
        var option = generator.current.getUniqueName( 'option' );

        var ifStatement = isMultipleSelect ?
                deindent(["\n\t\t\t\t", ".selected = ~", ".indexOf( ", ".__value );"], option, value$1, option) :
                deindent(["\n\t\t\t\tif ( ", ".__value === ", " ) {\n\t\t\t\t\t", ".selected = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}"], option, value$1, option);

        updateElement = deindent(["\n\t\t\tvar ", " = ", ";\n\t\t\tfor ( var ", " = 0; ", " < ", ".options.length; ", " += 1 ) {\n\t\t\t\tvar ", " = ", ".options[", "];\n\n\t\t\t\t", "\n\t\t\t}\n\t\t"], value$1, snippet, i, i, local.name, i, option, local.name, i, ifStatement);
}

// <input type='checkbox|radio' bind:group='selected'> special case
else if ( attribute.name === 'group' ) {
        if ( type === 'radio' ) {
                setter = deindent(["\n\t\t\t\tif ( !", ".checked ) return;\n\t\t\t\t", "\n\t\t\t\tcomponent._bindingGroups[", "].forEach( function ( input ) {\n\t\t\t\t\tinput.checked = false;\n\t\t\t\t});"], local.name, setter, bindingGroup);
        }

        var condition = type === 'checkbox' ?
                ("~" + snippet + ".indexOf( " + (local.name) + ".__value )") :
                ((local.name) + ".__value === " + snippet);

        local.init.addLine(
                ("component._bindingGroups[" + bindingGroup + "].push( " + (local.name) + " );")
        );

        local.teardown.addBlock(
                ("component._bindingGroups[" + bindingGroup + "].splice( component._bindingGroups[" + bindingGroup + "].indexOf( " + (local.name) + " ), 1 );")
        );

        updateElement = (local.name) + ".checked = " + condition + ";";
}

// everything else
else {
        updateElement = (local.name) + "." + (attribute.name) + " = " + snippet + ";";
}

local.init.addBlock( deindent(["\n\t\tvar ", "_updating = false;\n\n\t\tfunction ", " () {\n\t\t\t", "_updating = true;\n\t\t\t", "\n\t\t\t", "_updating = false;\n\t\t}\n\n\t\t", "( ", ", '", "', ", " );\n\t"], local.name, handler, local.name, setter, local.name, generator.helper( 'addEventListener' ), local.name, eventName, handler) );

node.initialUpdate = updateElement;

local.update.addLine( deindent(["\n\t\tif ( !", "_updating ) {\n\t\t\t", "\n\t\t}\n\t"], local.name, updateElement) );

generator.current.builders.teardown.addLine( deindent(["\n\t\t", "( ", ", '", "', ", " );\n\t"], generator.helper( 'removeEventListener' ), local.name, eventName, handler) );

}

function getBindingEventName ( node ) {

if ( node.name === 'input' ) {
        var typeAttribute = node.attributes.find( function (attr) { return attr.type === 'Attribute' && attr.name === 'type'; } );
        var type = typeAttribute ? typeAttribute.value[0].data : 'text'; // TODO in validation, should throw if type attribute is not static

        return type === 'checkbox' || type === 'radio' ? 'change' : 'input';
}

if ( node.name === 'textarea' ) {
        return 'input';
}

return 'change';

}

function getBindingValue ( generator, local, node, attribute, isMultipleSelect, bindingGroup, type ) {

// <select multiple bind:value='selected>
if ( isMultipleSelect ) {
        return ("[].map.call( " + (local.name) + ".selectedOptions, function ( option ) { return option.__value; })");
}

// <select bind:value='selected>
if ( node.name === 'select' ) {
        return 'selectedOption && selectedOption.__value';
}

// <input type='checkbox' bind:group='foo'>
if ( attribute.name === 'group' ) {
        if ( type === 'checkbox' ) {
                return ((generator.helper( 'getBindingGroupValue' )) + "( component._bindingGroups[" + bindingGroup + "] )");
        }

        return ((local.name) + ".__value");
}

// everything else
return ((local.name) + "." + (attribute.name));

}

function getBindingGroup ( generator, current, attribute, keypath ) {

// TODO handle contextual bindings — `keypath` should include unique ID of
// each block that provides context
var index = generator.bindingGroups.indexOf( keypath );
if ( index === -1 ) {
        index = generator.bindingGroups.length;
        generator.bindingGroups.push( keypath );
}

return index;

}

function addElementAttributes ( generator, node, local ) {

node.attributes.forEach( function (attribute) {
        var name = attribute.name;

        if ( attribute.type === 'Attribute' ) {
                var metadata = local.namespace ? null : lookup[ name ];
                if ( metadata && metadata.appliesTo && !~metadata.appliesTo.indexOf( node.name ) ) { metadata = null; }

                var dynamic = false;

                var isIndirectlyBoundValue = name === 'value' && (
                        node.name === 'option' || // TODO check it's actually bound
                        node.name === 'input' && /^(checkbox|radio)$/.test( getStaticAttributeValue( node, 'type' ) )
                );

                var propertyName = isIndirectlyBoundValue ? '__value' : metadata && metadata.propertyName;

                var isXlink = name.slice( 0, 6 ) === 'xlink:';

                // xlink is a special case... we could maybe extend this to generic
                // namespaced attributes but I'm not sure that's applicable in
                // HTML5?
                var method = isXlink ? 'setXlinkAttribute' : 'setAttribute';

                if ( attribute.value === true ) {
                        // attributes without values, e.g. <textarea readonly>
                        if ( propertyName ) {
                                local.init.addLine(
                                        ((local.name) + "." + propertyName + " = true;")
                                );
                        } else {
                                local.init.addLine(
                                        ((generator.helper( method )) + "( " + (local.name) + ", '" + name + "', true );")
                                );
                        }

                        // special case – autofocus. has to be handled in a bit of a weird way
                        if ( name === 'autofocus' ) {
                                generator.current.autofocus = local.name;
                        }
                }

                else if ( attribute.value.length === 0 ) {
                        if ( propertyName ) {
                                local.init.addLine(
                                        ((local.name) + "." + propertyName + " = '';")
                                );
                        } else {
                                local.init.addLine(
                                        ((generator.helper( method )) + "( " + (local.name) + ", '" + name + "', '' );")
                                );
                        }
                }

                else if ( attribute.value.length === 1 ) {
                        var value = attribute.value[0];

                        var result = '';

                        if ( value.type === 'Text' ) {
                                // static attributes
                                result = JSON.stringify( value.data );

                                var addAttribute = false;
                                if ( name === 'xmlns' ) {
                                        // special case
                                        // TODO this attribute must be static – enforce at compile time
                                        local.namespace = value.data;
                                        addAttribute = true;
                                } else if ( propertyName ) {
                                        local.init.addLine(
                                                ((local.name) + "." + propertyName + " = " + result + ";")
                                        );
                                } else {
                                        addAttribute = true;
                                }

                                if ( addAttribute ) {
                                        local.init.addLine(
                                                ((generator.helper( method )) + "( " + (local.name) + ", '" + name + "', " + result + " );")
                                        );
                                }
                        }

                        else {
                                dynamic = true;

                                // dynamic – but potentially non-string – attributes
                                var ref = generator.contextualise( value.expression );
                                var snippet = ref.snippet;

                                var last = "last_" + (local.name) + "_" + (name.replace( /-/g, '_'));
                                local.init.addLine( ("var " + last + " = " + snippet + ";") );

                                var updater;
                                if ( propertyName ) {
                                        updater = (local.name) + "." + propertyName + " = " + last + ";";
                                } else {
                                        updater = (generator.helper( method )) + "( " + (local.name) + ", '" + name + "', " + last + " );";
                                }

                                local.init.addLine( updater );
                                local.update.addBlock( deindent(["\n\t\t\t\t\t\tif ( ( __tmp = ", " ) !== ", " ) {\n\t\t\t\t\t\t\t", " = __tmp;\n\t\t\t\t\t\t\t", "\n\t\t\t\t\t\t}\n\t\t\t\t\t"], snippet, last, last, updater) );
                        }
                }

                else {
                        dynamic = true;

                        var value$1 = ( attribute.value[0].type === 'Text' ? '' : "\"\" + " ) + (
                                attribute.value.map( function (chunk) {
                                        if ( chunk.type === 'Text' ) {
                                                return JSON.stringify( chunk.data );
                                        } else {
                                                var ref = generator.contextualise( chunk.expression );
                                                var snippet = ref.snippet;
                                                return ("( " + snippet + " )");
                                        }
                                }).join( ' + ' )
                        );

                        var updater$1;
                        if (propertyName) {
                                updater$1 = (local.name) + "." + propertyName + " = " + value$1 + ";";
                        } else {
                                updater$1 = (generator.helper( method )) + "( " + (local.name) + ", '" + name + "', " + value$1 + " );";
                        }

                        local.init.addLine( updater$1 );
                        local.update.addLine( updater$1 );
                }

                if ( isIndirectlyBoundValue ) {
                        var updateValue = (local.name) + ".value = " + (local.name) + ".__value;";

                        local.init.addLine( updateValue );
                        if ( dynamic ) { local.update.addLine( updateValue ); }
                }
        }

        else if ( attribute.type === 'EventHandler' ) {
                // TODO verify that it's a valid callee (i.e. built-in or declared method)
                generator.addSourcemapLocations( attribute.expression );

                var flattened = flatten( attribute.expression.callee );
                if ( flattened.name !== 'event' && flattened.name !== 'this' ) {
                        // allow event.stopPropagation(), this.select() etc
                        generator.code.prependRight( attribute.expression.start, 'component.' );
                }

                var usedContexts = [];
                attribute.expression.arguments.forEach( function (arg) {
                        var ref = generator.contextualise( arg, true );
                        var contexts = ref.contexts;

                        contexts.forEach( function (context) {
                                if ( !~usedContexts.indexOf( context ) ) { usedContexts.push( context ); }
                                if ( !~local.allUsedContexts.indexOf( context ) ) { local.allUsedContexts.push( context ); }
                        });
                });

                // TODO hoist event handlers? can do `this.__component.method(...)`
                var declarations = usedContexts.map( function (name) {
                        if ( name === 'root' ) { return 'var root = this.__svelte.root;'; }

                        var listName = generator.current.listNames[ name ];
                        var indexName = generator.current.indexNames[ name ];

                        return ("var " + listName + " = this.__svelte." + listName + ", " + indexName + " = this.__svelte." + indexName + ", " + name + " = " + listName + "[" + indexName + "]");
                });

                var handlerName = generator.current.getUniqueName( (name + "Handler") );
                var handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + "[✂" + (attribute.expression.start) + "-" + (attribute.expression.end) + "✂];";

                if ( name in generator.events ) {
                        local.init.addBlock( deindent(["\n\t\t\t\t\tvar ", " = template.events.", ".call( component, ", ", function ( event ) {\n\t\t\t\t\t\t", "\n\t\t\t\t\t});\n\t\t\t\t"], handlerName, name, local.name, handlerBody) );

                        generator.current.builders.teardown.addLine( deindent(["\n\t\t\t\t\t", ".teardown();\n\t\t\t\t"], handlerName) );
                } else {
                        local.init.addBlock( deindent(["\n\t\t\t\t\tfunction ", " ( event ) {\n\t\t\t\t\t\t", "\n\t\t\t\t\t}\n\n\t\t\t\t\t", "( ", ", '", "', ", " );\n\t\t\t\t"], handlerName, handlerBody, generator.helper( 'addEventListener' ), local.name, name, handlerName) );

                        generator.current.builders.teardown.addLine( deindent(["\n\t\t\t\t\t", "( ", ", '", "', ", " );\n\t\t\t\t"], generator.helper( 'removeEventListener' ), local.name, name, handlerName) );
                }
        }

        else if ( attribute.type === 'Binding' ) {
                createBinding( generator, node, attribute, generator.current, local );
        }

        else if ( attribute.type === 'Ref' ) {
                generator.usesRefs = true;

                local.init.addLine(
                        ("component.refs." + name + " = " + (local.name) + ";")
                );

                generator.current.builders.teardown.addLine( deindent(["\n\t\t\t\tif ( component.refs.", " === ", " ) component.refs.", " = null;\n\t\t\t"], name, local.name, name) );
        }

        else {
                throw new Error( ("Not implemented: " + (attribute.type)) );
        }
});

}

function createBinding$1 ( generator, node, attribute, current, local ) {

var ref = flatten( attribute.value );
var name = ref.name;
var ref$1 = generator.contextualise( attribute.value );
var snippet = ref$1.snippet;
var contexts = ref$1.contexts;
var dependencies = ref$1.dependencies;

if ( dependencies.length > 1 ) { throw new Error( 'An unexpected situation arose. Please raise an issue at https://github.com/sveltejs/svelte/issues — thanks!' ); }

contexts.forEach( function (context) {
        if ( !~local.allUsedContexts.indexOf( context ) ) { local.allUsedContexts.push( context ); }
});

var contextual = name in current.contexts;

var obj;
var prop;

if ( contextual ) {
        obj = current.listNames[ name ];
        prop = current.indexNames[ name ];
} else if ( attribute.value.type === 'MemberExpression' ) {
        prop = "'[✂" + (attribute.value.property.start) + "-" + (attribute.value.property.end) + "✂]}'";
        obj = "root.[✂" + (attribute.value.object.start) + "-" + (attribute.value.object.end) + "✂]}";
} else {
        obj = 'root';
        prop = "'" + name + "'";
}

local.bindings.push({
        name: attribute.name,
        value: snippet,
        obj: obj,
        prop: prop
});

var setter = getSetter({ current: current, name: name, context: '_context', attribute: attribute, dependencies: dependencies, snippet: snippet, value: 'value' });

generator.hasComplexBindings = true;

local.init.addBlock( deindent(["\n\t\tvar ", "_updating = false;\n\n\t\tcomponent._bindings.push( function () {\n\t\t\tif ( ", "._torndown ) return;\n\t\t\t", ".observe( '", "', function ( value ) {\n\t\t\t\t", "_updating = true;\n\t\t\t\t", "\n\t\t\t\t", "_updating = false;\n\t\t\t});\n\t\t});\n\t"], local.name, local.name, local.name, attribute.name, local.name, setter, local.name) );

local.update.addBlock( deindent(["\n\t\tif ( !", "_updating && ", " ) {\n\t\t\t", "._set({ ", ": ", " });\n\t\t}\n\t"], local.name, dependencies.map( function (dependency) { return ("'" + dependency + "' in changed"); } ).join( '||' ), local.name, attribute.name, snippet) );

}

function addComponentAttributes ( generator, node, local ) {

local.staticAttributes = [];
local.dynamicAttributes = [];
local.bindings = [];

node.attributes.forEach( function (attribute) {
        if ( attribute.type === 'Attribute' ) {
                if ( attribute.value === true ) {
                        // attributes without values, e.g. <textarea readonly>
                        local.staticAttributes.push({
                                name: attribute.name,
                                value: true
                        });
                }

                else if ( attribute.value.length === 0 ) {
                        local.staticAttributes.push({
                                name: attribute.name,
                                value: "''"
                        });
                }

                else if ( attribute.value.length === 1 ) {
                        var value = attribute.value[0];

                        if ( value.type === 'Text' ) {
                                // static attributes
                                var result = isNaN( value.data ) ? JSON.stringify( value.data ) : value.data;
                                local.staticAttributes.push({
                                        name: attribute.name,
                                        value: result
                                });
                        }

                        else {
                                // simple dynamic attributes
                                var ref = generator.contextualise( value.expression );
                                var dependencies = ref.dependencies;
                                var string = ref.string;

                                // TODO only update attributes that have changed
                                local.dynamicAttributes.push({
                                        name: attribute.name,
                                        value: string,
                                        dependencies: dependencies
                                });
                        }
                }

                else {
                        // complex dynamic attributes
                        var allDependencies = [];

                        var value$1 = ( attribute.value[0].type === 'Text' ? '' : "\"\" + " ) + (
                                attribute.value.map( function (chunk) {
                                        if ( chunk.type === 'Text' ) {
                                                return JSON.stringify( chunk.data );
                                        } else {
                                                var ref = generator.contextualise( chunk.expression );
                                                var dependencies = ref.dependencies;
                                                var string = ref.string;
                                                dependencies.forEach( function (dependency) {
                                                        if ( !~allDependencies.indexOf( dependency ) ) { allDependencies.push( dependency ); }
                                                });

                                                return ("( " + string + " )");
                                        }
                                }).join( ' + ' )
                        );

                        local.dynamicAttributes.push({
                                name: attribute.name,
                                value: value$1,
                                dependencies: allDependencies
                        });
                }
        }

        else if ( attribute.type === 'EventHandler' ) {
                // TODO verify that it's a valid callee (i.e. built-in or declared method)
                generator.addSourcemapLocations( attribute.expression );
                generator.code.prependRight( attribute.expression.start, 'component.' );

                var usedContexts = [];
                attribute.expression.arguments.forEach( function (arg) {
                        var ref = generator.contextualise( arg, true );
                        var contexts = ref.contexts;

                        contexts.forEach( function (context) {
                                if ( !~usedContexts.indexOf( context ) ) { usedContexts.push( context ); }
                                if ( !~local.allUsedContexts.indexOf( context ) ) { local.allUsedContexts.push( context ); }
                        });
                });

                // TODO hoist event handlers? can do `this.__component.method(...)`
                var declarations = usedContexts.map( function (name) {
                        if ( name === 'root' ) { return 'var root = this._context.root;'; }

                        var listName = generator.current.listNames[ name ];
                        var indexName = generator.current.indexNames[ name ];

                        return ("var " + listName + " = this._context." + listName + ", " + indexName + " = this._context." + indexName + ", " + name + " = " + listName + "[" + indexName + "]");
                });

                var handlerBody = ( declarations.length ? declarations.join( '\n' ) + '\n\n' : '' ) + "[✂" + (attribute.expression.start) + "-" + (attribute.expression.end) + "✂];";

                local.init.addBlock( deindent(["\n\t\t\t\t", ".on( '", "', function ( event ) {\n\t\t\t\t\t", "\n\t\t\t\t});\n\t\t\t"], local.name, attribute.name, handlerBody) );
        }

        else if ( attribute.type === 'Binding' ) {
                createBinding$1( generator, node, attribute, generator.current, local );
        }

        else if ( attribute.type === 'Ref' ) {
                generator.usesRefs = true;

                local.init.addLine(
                        ("component.refs." + (attribute.name) + " = " + (local.name) + ";")
                );

                generator.current.builders.teardown.addLine( deindent(["\n\t\t\t\tif ( component.refs.", " === ", " ) component.refs.", " = null;\n\t\t\t"], attribute.name, local.name, attribute.name) );
        }

        else {
                throw new Error( ("Not implemented: " + (attribute.type)) );
        }
});

}

function capDown ( name ) {

return ("" + (name[0].toLowerCase()) + (name.slice( 1 )));

}

var Component = {

enter: function enter ( generator, node ) {
        var hasChildren = node.children.length > 0;
        var name = generator.current.getUniqueName( capDown( node.name === ':Self' ? generator.name : node.name ) );

        var local = {
                name: name,
                namespace: generator.current.namespace,
                isComponent: true,

                allUsedContexts: [],

                init: new CodeBuilder(),
                update: new CodeBuilder()
        };

        var isToplevel = generator.current.localElementDepth === 0;

        generator.hasComponents = true;

        addComponentAttributes( generator, node, local );

        if ( local.allUsedContexts.length ) {
                var initialProps = local.allUsedContexts.map( function (contextName) {
                        if ( contextName === 'root' ) { return "root: root"; }

                        var listName = generator.current.listNames[ contextName ];
                        var indexName = generator.current.indexNames[ contextName ];

                        return (listName + ": " + listName + ",\n" + indexName + ": " + indexName);
                }).join( ',\n' );

                var updates = local.allUsedContexts.map( function (contextName) {
                        if ( contextName === 'root' ) { return (name + "._context.root = root;"); }

                        var listName = generator.current.listNames[ contextName ];
                        var indexName = generator.current.indexNames[ contextName ];

                        return (name + "._context." + listName + " = " + listName + ";\n" + name + "._context." + indexName + " = " + indexName + ";");
                }).join( '\n' );

                local.init.addBlock( deindent(["\n\t\t\t\t", "._context = {\n\t\t\t\t\t", "\n\t\t\t\t};\n\t\t\t"], name, initialProps) );

                local.update.addBlock( updates );
        }

        var componentInitProperties = [
                ("target: " + (!isToplevel ? generator.current.target: 'null')),
                '_root: component._root || component'
        ];

        // Component has children, put them in a separate {{yield}} block
        if ( hasChildren ) {
                var yieldName = generator.getUniqueName( ("render" + name + "YieldFragment") );
                var params = generator.current.params.join( ', ' );

                generator.generateBlock( node, yieldName );

                generator.current.builders.init.addLine(
                        ("var " + name + "_yieldFragment = " + yieldName + "( " + params + ", component );")
                );

                generator.current.builders.update.addLine(
                        (name + "_yieldFragment.update( changed, " + params + " );")
                );

                componentInitProperties.push( ("_yield: " + name + "_yieldFragment"));
        }

        var statements = [];

        if ( local.staticAttributes.length || local.dynamicAttributes.length || local.bindings.length ) {
                var initialProps$1 = local.staticAttributes
                        .concat( local.dynamicAttributes )
                        .map( function (attribute) { return ((attribute.name) + ": " + (attribute.value)); } );

                if ( initialProps$1.length ) {
                        statements.push( deindent(["\n\t\t\t\t\tvar ", "_initialData = {\n\t\t\t\t\t\t", "\n\t\t\t\t\t};\n\t\t\t\t"], name, initialProps$1.join( ',\n' )) );
                } else {
                        statements.push( ("var " + name + "_initialData = {};") );
                }

                if ( local.bindings.length ) {
                        var bindings = local.bindings.map( function (binding) {
                                return ("if ( " + (binding.prop) + " in " + (binding.obj) + " ) " + name + "_initialData." + (binding.name) + " = " + (binding.value) + ";");
                        });

                        statements.push( bindings.join( '\n' ) );
                }
                componentInitProperties.push(("data: " + name + "_initialData"));
        }

        var expression = node.name === ':Self' ? generator.name : generator.importedComponents[ node.name ] || ("template.components." + (node.name));

        local.init.addBlockAtStart( deindent(["\n\t\t\t", "\n\t\t\tvar ", " = new ", "({\n\t\t\t\t", "\n\t\t\t});\n\t\t"], statements.join( '\n\n' ), name, expression, componentInitProperties.join(',\n')) );

        if ( isToplevel ) {
                generator.current.builders.mount.addLine( (name + "._fragment.mount( target, anchor );") );
        }

        if ( local.dynamicAttributes.length ) {
                var updates$1 = local.dynamicAttributes.map( function (attribute) {
                        if ( attribute.dependencies.length ) {
                                return deindent(["\n\t\t\t\t\t\tif ( ", " ) ", "_changes.", " = ", ";\n\t\t\t\t\t"], attribute.dependencies.map( function (dependency) { return ("'" + dependency + "' in changed"); } ).join( '||' ), name, attribute.name, attribute.value);
                        }

                        // TODO this is an odd situation to encounter – I *think* it should only happen with
                        // each block indices, in which case it may be possible to optimise this
                        return (name + "_changes." + (attribute.name) + " = " + (attribute.value) + ";");
                });

                local.update.addBlock( deindent(["\n\t\t\t\tvar ", "_changes = {};\n\n\t\t\t\t", "\n\n\t\t\t\tif ( Object.keys( ", "_changes ).length ) ", ".set( ", "_changes );\n\t\t\t"], name, updates$1.join( '\n' ), name, name, name) );
        }

        generator.current.builders.teardown.addLine( (name + ".destroy( " + (isToplevel ? 'detach' : 'false') + " );") );

        generator.current.builders.init.addBlock( local.init );
        if ( !local.update.isEmpty() ) { generator.current.builders.update.addBlock( local.update ); }

        generator.push({
                namespace: local.namespace,
                target: name,
                parent: generator.current,
                localElementDepth: generator.current.localElementDepth + 1,
                key: null
        });
},

leave: function leave ( generator ) {
        generator.pop();
}

};

var Element = {

enter: function enter ( generator, node ) {
        var isComponent = node.name in generator.components || node.name === ':Self';
        if ( isComponent ) {
                return Component.enter( generator, node );
        }

        var name = generator.current.getUniqueName( node.name );

        var local = {
                name: name,
                namespace: node.name === 'svg' ? 'http://www.w3.org/2000/svg' : generator.current.namespace,
                isComponent: false,

                allUsedContexts: [],

                init: new CodeBuilder(),
                update: new CodeBuilder(),
                teardown: new CodeBuilder()
        };

        var isToplevel = generator.current.localElementDepth === 0;

        addElementAttributes( generator, node, local );

        if ( local.allUsedContexts.length ) {
                var initialProps = local.allUsedContexts.map( function (contextName) {
                        if ( contextName === 'root' ) { return "root: root"; }

                        var listName = generator.current.listNames[ contextName ];
                        var indexName = generator.current.indexNames[ contextName ];

                        return (listName + ": " + listName + ",\n" + indexName + ": " + indexName);
                }).join( ',\n' );

                var updates = local.allUsedContexts.map( function (contextName) {
                        if ( contextName === 'root' ) { return (name + ".__svelte.root = root;"); }

                        var listName = generator.current.listNames[ contextName ];
                        var indexName = generator.current.indexNames[ contextName ];

                        return (name + ".__svelte." + listName + " = " + listName + ";\n" + name + ".__svelte." + indexName + " = " + indexName + ";");
                }).join( '\n' );

                local.init.addBlock( deindent(["\n\t\t\t\t", ".__svelte = {\n\t\t\t\t\t", "\n\t\t\t\t};\n\t\t\t"], name, initialProps) );

                local.update.addBlock( updates );
        }

        var render;

        if ( local.namespace ) {
                if ( local.namespace === 'http://www.w3.org/2000/svg' ) {
                        render = "var " + name + " = " + (generator.helper( 'createSvgElement' )) + "( '" + (node.name) + "' )";
                } else {
                        render = "var " + name + " = document.createElementNS( '" + (local.namespace) + "', '" + (node.name) + "' );";
                }
        } else {
                render = "var " + name + " = " + (generator.helper( 'createElement' )) + "( '" + (node.name) + "' );";
        }

        if ( generator.cssId && !generator.elementDepth ) {
                render += "\n" + (generator.helper( 'setAttribute' )) + "( " + name + ", '" + (generator.cssId) + "', '' );";
        }

        local.init.addLineAtStart( render );
        if ( isToplevel ) {
                generator.current.builders.detach.addLine( ((generator.helper( 'detachNode' )) + "( " + name + " );") );
        }

        // special case – bound <option> without a value attribute
        if ( node.name === 'option' && !node.attributes.find( function (attribute) { return attribute.type === 'Attribute' && attribute.name === 'value'; } ) ) {       // TODO check it's bound
                var statement = name + ".__value = " + name + ".textContent;";
                local.update.addLine( statement );
                node.initialUpdate = statement;
        }

        generator.current.builders.init.addBlock( local.init );
        if ( !local.update.isEmpty() ) { generator.current.builders.update.addBlock( local.update ); }
        if ( !local.teardown.isEmpty() ) { generator.current.builders.teardown.addBlock( local.teardown ); }

        generator.createMountStatement( name );

        generator.push({
                namespace: local.namespace,
                target: name,
                parent: generator.current,
                localElementDepth: generator.current.localElementDepth + 1,
                key: null
        });
},

leave: function leave ( generator, node ) {
        var isComponent = node.name in generator.components;
        if ( isComponent ) {
                return Component.leave( generator, node );
        }

        if ( node.initialUpdate ) {
                generator.current.builders.init.addBlock( node.initialUpdate );
        }

        generator.pop();
}

};

function getConditionsAndBlocks ( generator, node, _name, i ) {

if ( i === void 0 ) i = 0;

generator.addSourcemapLocations( node.expression );
var name = _name + "_" + i;

var conditionsAndBlocks = [{
        condition: generator.contextualise( node.expression ).snippet,
        block: name
}];

generator.generateBlock( node, name );

if ( node.else && node.else.children.length === 1 &&
        node.else.children[0].type === 'IfBlock' ) {
        conditionsAndBlocks.push.apply(
                conditionsAndBlocks, getConditionsAndBlocks( generator, node.else.children[0], _name, i + 1 )
        );
} else {
        var name$1 = _name + "_" + (i + 1);
        conditionsAndBlocks.push({
                condition: null,
                block: node.else ? name$1 : null,
        });

        if ( node.else ) {
                generator.generateBlock( node.else, name$1 );
        }
}
return conditionsAndBlocks;

}

var IfBlock = {

enter: function enter ( generator, node ) {
        var params = generator.current.params.join( ', ' );
        var name = generator.getUniqueName( "ifBlock" );
        var getBlock = generator.getUniqueName( "getBlock" );
        var currentBlock = generator.getUniqueName( "currentBlock" );

        var isToplevel = generator.current.localElementDepth === 0;
        var conditionsAndBlocks = getConditionsAndBlocks( generator, node, generator.getUniqueName( "renderIfBlock" ) );

        var anchor = name + "_anchor";
        generator.createAnchor( anchor );

        generator.current.builders.init.addBlock( deindent(["\n\t\t\tfunction ", " ( ", " ) {\n\t\t\t\t", "\n\t\t\t}\n\n\t\t\tvar ", " = ", "( ", " );\n\t\t\tvar ", " = ", " && ", "( ", ", component );\n\t\t"], getBlock, params, conditionsAndBlocks.map( function (ref) {
                                var condition = ref.condition;
                                var block = ref.block;

                                return ((condition ? ("if ( " + condition + " ) ") : '') + "return " + block + ";");
                        } ).join( '\n' ), currentBlock, getBlock, params, name, currentBlock, currentBlock, params) );

        var mountStatement = "if ( " + name + " ) " + name + ".mount( " + anchor + ".parentNode, " + anchor + " );";
        if ( isToplevel ) {
                generator.current.builders.mount.addLine( mountStatement );
        } else {
                generator.current.builders.init.addLine( mountStatement );
        }

        generator.current.builders.update.addBlock( deindent(["\n\t\t\tvar _", " = ", ";\n\t\t\t", " = ", "( ", " );\n\t\t\tif ( _", " === ", " && ", ") {\n\t\t\t\t", ".update( changed, ", " );\n\t\t\t} else {\n\t\t\t\tif ( ", " ) ", ".teardown( true );\n\t\t\t\t", " = ", " && ", "( ", ", component );\n\t\t\t\tif ( ", " ) ", ".mount( ", ".parentNode, ", " );\n\t\t\t}\n\t\t"], currentBlock, currentBlock, currentBlock, getBlock, params, currentBlock, currentBlock, name, name, params, name, name, name, currentBlock, currentBlock, params, name, name, anchor, anchor) );

        generator.current.builders.teardown.addLine(
                ("if ( " + name + " ) " + name + ".teardown( " + (isToplevel ? 'detach' : 'false') + " );")
        );
}

};

var MustacheTag = {

enter: function enter ( generator, node ) {
        var name = generator.current.getUniqueName( 'text' );

        var ref = generator.contextualise( node.expression );
        var snippet = ref.snippet;

        generator.current.builders.init.addLine( ("var last_" + name + " = " + snippet) );
        generator.addElement( name, ((generator.helper( 'createText' )) + "( last_" + name + " )"), true );

        generator.current.builders.update.addBlock( deindent(["\n\t\t\tif ( ( __tmp = ", " ) !== last_", " ) {\n\t\t\t\t", ".data = last_", " = __tmp;\n\t\t\t}\n\t\t"], snippet, name, name, name) );
}

};

var RawMustacheTag = {

enter: function enter ( generator, node ) {
        var name = generator.current.getUniqueName( 'raw' );

        var ref = generator.contextualise( node.expression );
        var snippet = ref.snippet;

        // we would have used comments here, but the `insertAdjacentHTML` api only
        // exists for `Element`s.
        var before = name + "_before";
        generator.addElement( before, ((generator.helper( 'createElement' )) + "( 'noscript' )"), true );

        var after = name + "_after";
        generator.addElement( after, ((generator.helper( 'createElement' )) + "( 'noscript' )"), true );

        var isToplevel = generator.current.localElementDepth === 0;

        generator.current.builders.init.addLine( ("var last_" + name + " = " + snippet + ";") );
        var mountStatement = before + ".insertAdjacentHTML( 'afterend', last_" + name + " );";
        var detachStatement = (generator.helper( 'detachBetween' )) + "( " + before + ", " + after + " );";

        if ( isToplevel ) {
                generator.current.builders.mount.addLine( mountStatement );
        } else {
                generator.current.builders.init.addLine( mountStatement );
        }

        generator.current.builders.update.addBlock( deindent(["\n\t\t\tif ( ( __tmp = ", " ) !== last_", " ) {\n\t\t\t\tlast_", " = __tmp;\n\t\t\t\t", "\n\t\t\t\t", "\n\t\t\t}\n\t\t"], snippet, name, name, detachStatement, mountStatement) );

        generator.current.builders.detachRaw.addBlock( detachStatement );
}

};

var Text = {

enter: function enter ( generator, node ) {
        if ( generator.current.namespace && !/\S/.test( node.data ) ) {
                return;
        }

        var name = generator.current.getUniqueName( "text" );
        generator.addElement( name, ((generator.helper( 'createText' )) + "( " + (JSON.stringify( node.data )) + " )"), false );
}

};

var YieldTag = {

enter: function enter ( generator ) {
        var anchor = "yield_anchor";
        generator.createAnchor( anchor );

        generator.current.builders.mount.addLine(
                ("component._yield && component._yield.mount( " + (generator.current.target) + ", " + anchor + " );")
        );

        generator.current.builders.teardown.addLine(
                "component._yield && component._yield.teardown( detach );"
        );
}

};

var visitors = {

Comment: Comment$2,
EachBlock: EachBlock,
Element: Element,
IfBlock: IfBlock,
MustacheTag: MustacheTag,
RawMustacheTag: RawMustacheTag,
Text: Text,
YieldTag: YieldTag

};

var charToInteger = {}; var integerToChar = {};

'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split( '' ).forEach( function ( char, i ) {

charToInteger[ char ] = i;
integerToChar[ i ] = char;

});

function encode ( value ) {

var result, i;

if ( typeof value === 'number' ) {
        result = encodeInteger( value );
} else {
        result = '';
        for ( i = 0; i < value.length; i += 1 ) {
                result += encodeInteger( value[i] );
        }
}

return result;

}

function encodeInteger ( num ) {

var result = '', clamped;

if ( num < 0 ) {
        num = ( -num << 1 ) | 1;
} else {
        num <<= 1;
}

do {
        clamped = num & 31;
        num >>= 5;

        if ( num > 0 ) {
                clamped |= 32;
        }

        result += integerToChar[ clamped ];
} while ( num > 0 );

return result;

}

function Chunk ( start, end, content ) {

this.start = start;
this.end = end;
this.original = content;

this.intro = '';
this.outro = '';

this.content = content;
this.storeName = false;
this.edited = false;

// we make these non-enumerable, for sanity while debugging
Object.defineProperties( this, {
        previous: { writable: true, value: null },
        next: { writable: true, value: null }
});

}

Chunk.prototype = {

appendLeft: function appendLeft ( content ) {
        this.outro += content;
},

appendRight: function appendRight ( content ) {
        this.intro = this.intro + content;
},

clone: function clone () {
        var chunk = new Chunk( this.start, this.end, this.original );

        chunk.intro = this.intro;
        chunk.outro = this.outro;
        chunk.content = this.content;
        chunk.storeName = this.storeName;
        chunk.edited = this.edited;

        return chunk;
},

contains: function contains ( index ) {
        return this.start < index && index < this.end;
},

eachNext: function eachNext ( fn ) {
        var chunk = this;
        while ( chunk ) {
                fn( chunk );
                chunk = chunk.next;
        }
},

eachPrevious: function eachPrevious ( fn ) {
        var chunk = this;
        while ( chunk ) {
                fn( chunk );
                chunk = chunk.previous;
        }
},

edit: function edit ( content, storeName ) {
        this.content = content;
        this.intro = '';
        this.outro = '';
        this.storeName = storeName;

        this.edited = true;

        return this;
},

prependLeft: function prependLeft ( content ) {
        this.outro = content + this.outro;
},

prependRight: function prependRight ( content ) {
        this.intro = content + this.intro;
},

split: function split ( index ) {
        var sliceIndex = index - this.start;

        var originalBefore = this.original.slice( 0, sliceIndex );
        var originalAfter = this.original.slice( sliceIndex );

        this.original = originalBefore;

        var newChunk = new Chunk( index, this.end, originalAfter );
        newChunk.outro = this.outro;
        this.outro = '';

        this.end = index;

        if ( this.edited ) {
                // TODO is this block necessary?...
                newChunk.edit( '', false );
                this.content = '';
        } else {
                this.content = originalBefore;
        }

        newChunk.next = this.next;
        if ( newChunk.next ) { newChunk.next.previous = newChunk; }
        newChunk.previous = this;
        this.next = newChunk;

        return newChunk;
},

toString: function toString () {
        return this.intro + this.content + this.outro;
},

trimEnd: function trimEnd ( rx ) {
        this.outro = this.outro.replace( rx, '' );
        if ( this.outro.length ) { return true; }

        var trimmed = this.content.replace( rx, '' );

        if ( trimmed.length ) {
                if ( trimmed !== this.content ) {
                        this.split( this.start + trimmed.length ).edit( '', false );
                }

                return true;
        } else {
                this.edit( '', false );

                this.intro = this.intro.replace( rx, '' );
                if ( this.intro.length ) { return true; }
        }
},

trimStart: function trimStart ( rx ) {
        this.intro = this.intro.replace( rx, '' );
        if ( this.intro.length ) { return true; }

        var trimmed = this.content.replace( rx, '' );

        if ( trimmed.length ) {
                if ( trimmed !== this.content ) {
                        this.split( this.end - trimmed.length );
                        this.edit( '', false );
                }

                return true;
        } else {
                this.edit( '', false );

                this.outro = this.outro.replace( rx, '' );
                if ( this.outro.length ) { return true; }
        }
}

};

var _btoa;

if ( typeof window !== 'undefined' && typeof window.btoa === 'function' ) {

_btoa = window.btoa;

} else if ( typeof Buffer === 'function' ) {

_btoa = function (str) { return new Buffer( str ).toString( 'base64' ); };

} else {

_btoa = function () {
        throw new Error( 'Unsupported environment: `window.btoa` or `Buffer` should be supported.' );
};

}

var btoa = _btoa;

function SourceMap ( properties ) {

this.version = 3;

this.file           = properties.file;
this.sources        = properties.sources;
this.sourcesContent = properties.sourcesContent;
this.names          = properties.names;
this.mappings       = properties.mappings;

}

SourceMap.prototype = {

toString: function toString () {
        return JSON.stringify( this );
},

toUrl: function toUrl () {
        return 'data:application/json;charset=utf-8;base64,' + btoa( this.toString() );
}

};

function guessIndent ( code ) {

var lines = code.split( '\n' );

var tabbed = lines.filter( function (line) { return /^\t+/.test( line ); } );
var spaced = lines.filter( function (line) { return /^ {2,}/.test( line ); } );

if ( tabbed.length === 0 && spaced.length === 0 ) {
        return null;
}

// More lines tabbed than spaced? Assume tabs, and
// default to tabs in the case of a tie (or nothing
// to go on)
if ( tabbed.length >= spaced.length ) {
        return '\t';
}

// Otherwise, we need to guess the multiple
var min = spaced.reduce( function ( previous, current ) {
        var numSpaces = /^ +/.exec( current )[0].length;
        return Math.min( numSpaces, previous );
}, Infinity );

return new Array( min + 1 ).join( ' ' );

}

function getRelativePath ( from, to ) {

var fromParts = from.split( /[\/\\]/ );
var toParts = to.split( /[\/\\]/ );

fromParts.pop(); // get dirname

while ( fromParts[0] === toParts[0] ) {
        fromParts.shift();
        toParts.shift();
}

if ( fromParts.length ) {
        var i = fromParts.length;
        while ( i-- ) { fromParts[i] = '..'; }
}

return fromParts.concat( toParts ).join( '/' );

}

var toString$1 = Object.prototype.toString;

function isObject ( thing ) {

return toString$1.call( thing ) === '[object Object]';

}

function getLocator$1 ( source ) {

var originalLines = source.split( '\n' );

var start = 0;
var lineRanges = originalLines.map( function ( line, i ) {
        var end = start + line.length + 1;
        var range = { start: start, end: end, line: i };

        start = end;
        return range;
});

var i = 0;

function rangeContains ( range, index ) {
        return range.start <= index && index < range.end;
}

function getLocation ( range, index ) {
        return { line: range.line, column: index - range.start };
}

return function locate ( index ) {
        var range = lineRanges[i];

        var d = index >= range.end ? 1 : -1;

        while ( range ) {
                if ( rangeContains( range, index ) ) { return getLocation( range, index ); }

                i += d;
                range = lineRanges[i];
        }
};

}

function Mappings ( hires ) {

var this$1 = this;

var offsets = {
        generatedCodeColumn: 0,
        sourceIndex: 0,
        sourceCodeLine: 0,
        sourceCodeColumn: 0,
        sourceCodeName: 0
};

var generatedCodeLine = 0;
var generatedCodeColumn = 0;

this.raw = [];
var rawSegments = this.raw[ generatedCodeLine ] = [];

var pending = null;

this.addEdit = function ( sourceIndex, content, original, loc, nameIndex ) {
        if ( content.length ) {
                rawSegments.push([
                        generatedCodeColumn,
                        sourceIndex,
                        loc.line,
                        loc.column,
                        nameIndex ]);
        } else if ( pending ) {
                rawSegments.push( pending );
        }

        this$1.advance( content );
        pending = null;
};

this.addUneditedChunk = function ( sourceIndex, chunk, original, loc, sourcemapLocations ) {
        var originalCharIndex = chunk.start;
        var first = true;

        while ( originalCharIndex < chunk.end ) {
                if ( hires || first || sourcemapLocations[ originalCharIndex ] ) {
                        rawSegments.push([
                                generatedCodeColumn,
                                sourceIndex,
                                loc.line,
                                loc.column,
                                -1
                        ]);
                }

                if ( original[ originalCharIndex ] === '\n' ) {
                        loc.line += 1;
                        loc.column = 0;
                        generatedCodeLine += 1;
                        this$1.raw[ generatedCodeLine ] = rawSegments = [];
                        generatedCodeColumn = 0;
                } else {
                        loc.column += 1;
                        generatedCodeColumn += 1;
                }

                originalCharIndex += 1;
                first = false;
        }

        pending = [
                generatedCodeColumn,
                sourceIndex,
                loc.line,
                loc.column,
                -1 ];
};

this.advance = function (str) {
        if ( !str ) { return; }

        var lines = str.split( '\n' );
        var lastLine = lines.pop();

        if ( lines.length ) {
                generatedCodeLine += lines.length;
                this$1.raw[ generatedCodeLine ] = rawSegments = [];
                generatedCodeColumn = lastLine.length;
        } else {
                generatedCodeColumn += lastLine.length;
        }
};

this.encode = function () {
        return this$1.raw.map( function (segments) {
                var generatedCodeColumn = 0;

                return segments.map( function (segment) {
                        var arr = [
                                segment[0] - generatedCodeColumn,
                                segment[1] - offsets.sourceIndex,
                                segment[2] - offsets.sourceCodeLine,
                                segment[3] - offsets.sourceCodeColumn
                        ];

                        generatedCodeColumn = segment[0];
                        offsets.sourceIndex = segment[1];
                        offsets.sourceCodeLine = segment[2];
                        offsets.sourceCodeColumn = segment[3];

                        if ( ~segment[4] ) {
                                arr.push( segment[4] - offsets.sourceCodeName );
                                offsets.sourceCodeName = segment[4];
                        }

                        return encode( arr );
                }).join( ',' );
        }).join( ';' );
};

}

var Stats = function Stats () {

Object.defineProperties( this, {
        startTimes: { value: {} }
});

};

Stats.prototype.time = function time ( label ) {

this.startTimes[ label ] = process.hrtime();

};

Stats.prototype.timeEnd = function timeEnd ( label ) {

var elapsed = process.hrtime( this.startTimes[ label ] );

if ( !this[ label ] ) { this[ label ] = 0; }
this[ label ] += elapsed[0] * 1e3 + elapsed[1] * 1e-6;

};

var warned = {

insertLeft: false,
insertRight: false

};

function MagicString$1 ( string, options ) {

if ( options === void 0 ) options = {};

var chunk = new Chunk( 0, string.length, string );

Object.defineProperties( this, {
        original:              { writable: true, value: string },
        outro:                 { writable: true, value: '' },
        intro:                 { writable: true, value: '' },
        firstChunk:            { writable: true, value: chunk },
        lastChunk:             { writable: true, value: chunk },
        lastSearchedChunk:     { writable: true, value: chunk },
        byStart:               { writable: true, value: {} },
        byEnd:                 { writable: true, value: {} },
        filename:              { writable: true, value: options.filename },
        indentExclusionRanges: { writable: true, value: options.indentExclusionRanges },
        sourcemapLocations:    { writable: true, value: {} },
        storedNames:           { writable: true, value: {} },
        indentStr:             { writable: true, value: guessIndent( string ) }
});

this.byStart[ 0 ] = chunk;
this.byEnd[ string.length ] = chunk;

}

MagicString$1.prototype = {

addSourcemapLocation: function addSourcemapLocation ( char ) {
        this.sourcemapLocations[ char ] = true;
},

append: function append ( content ) {
        if ( typeof content !== 'string' ) { throw new TypeError( 'outro content must be a string' ); }

        this.outro += content;
        return this;
},

appendLeft: function appendLeft ( index, content ) {
        if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }

        this._split( index );

        var chunk = this.byEnd[ index ];

        if ( chunk ) {
                chunk.appendLeft( content );
        } else {
                this.intro += content;
        }

        return this;
},

appendRight: function appendRight ( index, content ) {
        if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }

        this._split( index );

        var chunk = this.byStart[ index ];

        if ( chunk ) {
                chunk.appendRight( content );
        } else {
                this.outro += content;
        }

        return this;
},

clone: function clone () {
        var cloned = new MagicString$1( this.original, { filename: this.filename });

        var originalChunk = this.firstChunk;
        var clonedChunk = cloned.firstChunk = cloned.lastSearchedChunk = originalChunk.clone();

        while ( originalChunk ) {
                cloned.byStart[ clonedChunk.start ] = clonedChunk;
                cloned.byEnd[ clonedChunk.end ] = clonedChunk;

                var nextOriginalChunk = originalChunk.next;
                var nextClonedChunk = nextOriginalChunk && nextOriginalChunk.clone();

                if ( nextClonedChunk ) {
                        clonedChunk.next = nextClonedChunk;
                        nextClonedChunk.previous = clonedChunk;

                        clonedChunk = nextClonedChunk;
                }

                originalChunk = nextOriginalChunk;
        }

        cloned.lastChunk = clonedChunk;

        if ( this.indentExclusionRanges ) {
                cloned.indentExclusionRanges = typeof this.indentExclusionRanges[0] === 'number' ?
                        [ this.indentExclusionRanges[0], this.indentExclusionRanges[1] ] :
                        this.indentExclusionRanges.map( function (range) { return [ range.start, range.end ]; } );
        }

        Object.keys( this.sourcemapLocations ).forEach( function (loc) {
                cloned.sourcemapLocations[ loc ] = true;
        });

        return cloned;
},

generateMap: function generateMap ( options ) {
        var this$1 = this;

        options = options || {};

        var sourceIndex = 0;
        var names = Object.keys( this.storedNames );
        var mappings = new Mappings( options.hires );

        var locate = getLocator$1( this.original );

        if ( this.intro ) {
                mappings.advance( this.intro );
        }

        this.firstChunk.eachNext( function (chunk) {
                var loc = locate( chunk.start );

                if ( chunk.intro.length ) { mappings.advance( chunk.intro ); }

                if ( chunk.edited ) {
                        mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 );
                } else {
                        mappings.addUneditedChunk( sourceIndex, chunk, this$1.original, loc, this$1.sourcemapLocations );
                }

                if ( chunk.outro.length ) { mappings.advance( chunk.outro ); }
        });

        var map = new SourceMap({
                file: ( options.file ? options.file.split( /[\/\\]/ ).pop() : null ),
                sources: [ options.source ? getRelativePath( options.file || '', options.source ) : null ],
                sourcesContent: options.includeContent ? [ this.original ] : [ null ],
                names: names,
                mappings: mappings.encode()
        });
        return map;
},

getIndentString: function getIndentString () {
        return this.indentStr === null ? '\t' : this.indentStr;
},

indent: function indent ( indentStr, options ) {
        var this$1 = this;

        var pattern = /^[^\r\n]/gm;

        if ( isObject( indentStr ) ) {
                options = indentStr;
                indentStr = undefined;
        }

        indentStr = indentStr !== undefined ? indentStr : ( this.indentStr || '\t' );

        if ( indentStr === '' ) { return this; } // noop

        options = options || {};

        // Process exclusion ranges
        var isExcluded = {};

        if ( options.exclude ) {
                var exclusions = typeof options.exclude[0] === 'number' ? [ options.exclude ] : options.exclude;
                exclusions.forEach( function (exclusion) {
                        for ( var i = exclusion[0]; i < exclusion[1]; i += 1 ) {
                                isExcluded[i] = true;
                        }
                });
        }

        var shouldIndentNextCharacter = options.indentStart !== false;
        var replacer = function (match) {
                if ( shouldIndentNextCharacter ) { return ("" + indentStr + match); }
                shouldIndentNextCharacter = true;
                return match;
        };

        this.intro = this.intro.replace( pattern, replacer );

        var charIndex = 0;

        var chunk = this.firstChunk;

        while ( chunk ) {
                var end = chunk.end;

                if ( chunk.edited ) {
                        if ( !isExcluded[ charIndex ] ) {
                                chunk.content = chunk.content.replace( pattern, replacer );

                                if ( chunk.content.length ) {
                                        shouldIndentNextCharacter = chunk.content[ chunk.content.length - 1 ] === '\n';
                                }
                        }
                } else {
                        charIndex = chunk.start;

                        while ( charIndex < end ) {
                                if ( !isExcluded[ charIndex ] ) {
                                        var char = this$1.original[ charIndex ];

                                        if ( char === '\n' ) {
                                                shouldIndentNextCharacter = true;
                                        } else if ( char !== '\r' && shouldIndentNextCharacter ) {
                                                shouldIndentNextCharacter = false;

                                                if ( charIndex === chunk.start ) {
                                                        chunk.prependRight( indentStr );
                                                } else {
                                                        var rhs = chunk.split( charIndex );
                                                        rhs.prependRight( indentStr );

                                                        this$1.byStart[ charIndex ] = rhs;
                                                        this$1.byEnd[ charIndex ] = chunk;

                                                        chunk = rhs;
                                                }
                                        }
                                }

                                charIndex += 1;
                        }
                }

                charIndex = chunk.end;
                chunk = chunk.next;
        }

        this.outro = this.outro.replace( pattern, replacer );

        return this;
},

insert: function insert () {
        throw new Error( 'magicString.insert(...) is deprecated. Use insertRight(...) or insertLeft(...)' );
},

insertLeft: function insertLeft ( index, content ) {
        if ( !warned.insertLeft ) {
                console.warn( 'magicString.insertLeft(...) is deprecated. Use magicString.appendLeft(...) instead' ); // eslint-disable-line no-console
                warned.insertLeft = true;
        }

        return this.appendLeft( index, content );
},

insertRight: function insertRight ( index, content ) {
        if ( !warned.insertRight ) {
                console.warn( 'magicString.insertRight(...) is deprecated. Use magicString.prependRight(...) instead' ); // eslint-disable-line no-console
                warned.insertRight = true;
        }

        return this.prependRight( index, content );
},

move: function move ( start, end, index ) {
        if ( index >= start && index <= end ) { throw new Error( 'Cannot move a selection inside itself' ); }

        this._split( start );
        this._split( end );
        this._split( index );

        var first = this.byStart[ start ];
        var last = this.byEnd[ end ];

        var oldLeft = first.previous;
        var oldRight = last.next;

        var newRight = this.byStart[ index ];
        if ( !newRight && last === this.lastChunk ) { return this; }
        var newLeft = newRight ? newRight.previous : this.lastChunk;

        if ( oldLeft ) { oldLeft.next = oldRight; }
        if ( oldRight ) { oldRight.previous = oldLeft; }

        if ( newLeft ) { newLeft.next = first; }
        if ( newRight ) { newRight.previous = last; }

        if ( !first.previous ) { this.firstChunk = last.next; }
        if ( !last.next ) {
                this.lastChunk = first.previous;
                this.lastChunk.next = null;
        }

        first.previous = newLeft;
        last.next = newRight;

        if ( !newLeft ) { this.firstChunk = first; }
        if ( !newRight ) { this.lastChunk = last; }

        return this;
},

overwrite: function overwrite ( start, end, content, storeName ) {
        var this$1 = this;

        if ( typeof content !== 'string' ) { throw new TypeError( 'replacement content must be a string' ); }

        while ( start < 0 ) { start += this$1.original.length; }
        while ( end < 0 ) { end += this$1.original.length; }

        if ( end > this.original.length ) { throw new Error( 'end is out of bounds' ); }
        if ( start === end ) { throw new Error( 'Cannot overwrite a zero-length range – use insertLeft or insertRight instead' ); }

        this._split( start );
        this._split( end );

        if ( storeName ) {
                var original = this.original.slice( start, end );
                this.storedNames[ original ] = true;
        }

        var first = this.byStart[ start ];
        var last = this.byEnd[ end ];

        if ( first ) {
                first.edit( content, storeName );

                if ( last ) {
                        first.next = last.next;
                } else {
                        first.next = null;
                        this.lastChunk = first;
                }

                first.original = this.original.slice( start, end );
                first.end = end;
        }

        else {
                // must be inserting at the end
                var newChunk = new Chunk( start, end, '' ).edit( content, storeName );

                // TODO last chunk in the array may not be the last chunk, if it's moved...
                last.next = newChunk;
                newChunk.previous = last;
        }

        return this;
},

prepend: function prepend ( content ) {
        if ( typeof content !== 'string' ) { throw new TypeError( 'outro content must be a string' ); }

        this.intro = content + this.intro;
        return this;
},

prependLeft: function prependLeft ( index, content ) {
        if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }

        this._split( index );

        var chunk = this.byEnd[ index ];

        if ( chunk ) {
                chunk.prependLeft( content );
        } else {
                this.intro = content + this.intro;
        }

        return this;
},

prependRight: function prependRight ( index, content ) {
        if ( typeof content !== 'string' ) { throw new TypeError( 'inserted content must be a string' ); }

        this._split( index );

        var chunk = this.byStart[ index ];

        if ( chunk ) {
                chunk.prependRight( content );
        } else {
                this.outro = content + this.outro;
        }

        return this;
},

remove: function remove ( start, end ) {
        var this$1 = this;

        while ( start < 0 ) { start += this$1.original.length; }
        while ( end < 0 ) { end += this$1.original.length; }

        if ( start === end ) { return this; }

        if ( start < 0 || end > this.original.length ) { throw new Error( 'Character is out of bounds' ); }
        if ( start > end ) { throw new Error( 'end must be greater than start' ); }

        return this.overwrite( start, end, '', false );
},

slice: function slice ( start, end ) {
        var this$1 = this;
        if ( start === void 0 ) start = 0;
        if ( end === void 0 ) end = this.original.length;

        while ( start < 0 ) { start += this$1.original.length; }
        while ( end < 0 ) { end += this$1.original.length; }

        var result = '';

        // find start chunk
        var chunk = this.firstChunk;
        while ( chunk && ( chunk.start > start || chunk.end <= start ) ) {

                // found end chunk before start
                if ( chunk.start < end && chunk.end >= end ) {
                        return result;
                }

                chunk = chunk.next;
        }

        if ( chunk && chunk.edited && chunk.start !== start ) { throw new Error(("Cannot use replaced character " + start + " as slice start anchor.")); }

        var startChunk = chunk;
        while ( chunk ) {
                if ( chunk.intro && ( startChunk !== chunk || chunk.start === start ) ) {
                        result += chunk.intro;
                }

                var containsEnd = chunk.start < end && chunk.end >= end;
                if ( containsEnd && chunk.edited && chunk.end !== end ) { throw new Error(("Cannot use replaced character " + end + " as slice end anchor.")); }

                var sliceStart = startChunk === chunk ? start - chunk.start : 0;
                var sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length;

                result += chunk.content.slice( sliceStart, sliceEnd );

                if ( chunk.outro && ( !containsEnd || chunk.end === end ) ) {
                        result += chunk.outro;
                }

                if ( containsEnd ) {
                        break;
                }

                chunk = chunk.next;
        }

        return result;
},

// TODO deprecate this? not really very useful
snip: function snip ( start, end ) {
        var clone = this.clone();
        clone.remove( 0, start );
        clone.remove( end, clone.original.length );

        return clone;
},

_split: function _split ( index ) {
        var this$1 = this;

        if ( this.byStart[ index ] || this.byEnd[ index ] ) { return; }

        var chunk = this.lastSearchedChunk;
        var searchForward = index > chunk.end;

        while ( true ) {
                if ( chunk.contains( index ) ) { return this$1._splitChunk( chunk, index ); }

                chunk = searchForward ?
                        this$1.byStart[ chunk.end ] :
                        this$1.byEnd[ chunk.start ];
        }
},

_splitChunk: function _splitChunk ( chunk, index ) {
        if ( chunk.edited && chunk.content.length ) { // zero-length edited chunks are a special case (overlapping replacements)
                var loc = getLocator$1( this.original )( index );
                throw new Error( ("Cannot split a chunk that has already been edited (" + (loc.line) + ":" + (loc.column) + " – \"" + (chunk.original) + "\")") );
        }

        var newChunk = chunk.split( index );

        this.byEnd[ index ] = chunk;
        this.byStart[ index ] = newChunk;
        this.byEnd[ newChunk.end ] = newChunk;

        if ( chunk === this.lastChunk ) { this.lastChunk = newChunk; }

        this.lastSearchedChunk = chunk;
        return true;
},

toString: function toString () {
        var str = this.intro;

        var chunk = this.firstChunk;
        while ( chunk ) {
                str += chunk.toString();
                chunk = chunk.next;
        }

        return str + this.outro;
},

trimLines: function trimLines () {
        return this.trim('[\\r\\n]');
},

trim: function trim ( charType ) {
        return this.trimStart( charType ).trimEnd( charType );
},

trimEnd: function trimEnd ( charType ) {
        var this$1 = this;

        var rx = new RegExp( ( charType || '\\s' ) + '+$' );

        this.outro = this.outro.replace( rx, '' );
        if ( this.outro.length ) { return this; }

        var chunk = this.lastChunk;

        do {
                var end = chunk.end;
                var aborted = chunk.trimEnd( rx );

                // if chunk was trimmed, we have a new lastChunk
                if ( chunk.end !== end ) {
                        this$1.lastChunk = chunk.next;

                        this$1.byEnd[ chunk.end ] = chunk;
                        this$1.byStart[ chunk.next.start ] = chunk.next;
                }

                if ( aborted ) { return this$1; }
                chunk = chunk.previous;
        } while ( chunk );

        return this;
},

trimStart: function trimStart ( charType ) {
        var this$1 = this;

        var rx = new RegExp( '^' + ( charType || '\\s' ) + '+' );

        this.intro = this.intro.replace( rx, '' );
        if ( this.intro.length ) { return this; }

        var chunk = this.firstChunk;

        do {
                var end = chunk.end;
                var aborted = chunk.trimStart( rx );

                if ( chunk.end !== end ) {
                        // special case...
                        if ( chunk === this$1.lastChunk ) { this$1.lastChunk = chunk.next; }

                        this$1.byEnd[ chunk.end ] = chunk;
                        this$1.byStart[ chunk.next.start ] = chunk.next;
                }

                if ( aborted ) { return this$1; }
                chunk = chunk.next;
        } while ( chunk );

        return this;
}

};

var hasOwnProp = Object.prototype.hasOwnProperty;

function Bundle ( options ) {

if ( options === void 0 ) options = {};

this.intro = options.intro || '';
this.separator = options.separator !== undefined ? options.separator : '\n';

this.sources = [];

this.uniqueSources = [];
this.uniqueSourceIndexByFilename = {};

}

Bundle.prototype = {

addSource: function addSource ( source ) {
        if ( source instanceof MagicString$1 ) {
                return this.addSource({
                        content: source,
                        filename: source.filename,
                        separator: this.separator
                });
        }

        if ( !isObject( source ) || !source.content ) {
                throw new Error( 'bundle.addSource() takes an object with a `content` property, which should be an instance of MagicString, and an optional `filename`' );
        }

        [ 'filename', 'indentExclusionRanges', 'separator' ].forEach( function (option) {
                if ( !hasOwnProp.call( source, option ) ) { source[ option ] = source.content[ option ]; }
        });

        if ( source.separator === undefined ) { // TODO there's a bunch of this sort of thing, needs cleaning up
                source.separator = this.separator;
        }

        if ( source.filename ) {
                if ( !hasOwnProp.call( this.uniqueSourceIndexByFilename, source.filename ) ) {
                        this.uniqueSourceIndexByFilename[ source.filename ] = this.uniqueSources.length;
                        this.uniqueSources.push({ filename: source.filename, content: source.content.original });
                } else {
                        var uniqueSource = this.uniqueSources[ this.uniqueSourceIndexByFilename[ source.filename ] ];
                        if ( source.content.original !== uniqueSource.content ) {
                                throw new Error( ("Illegal source: same filename (" + (source.filename) + "), different contents") );
                        }
                }
        }

        this.sources.push( source );
        return this;
},

append: function append ( str, options ) {
        this.addSource({
                content: new MagicString$1( str ),
                separator: ( options && options.separator ) || ''
        });

        return this;
},

clone: function clone () {
        var bundle = new Bundle({
                intro: this.intro,
                separator: this.separator
        });

        this.sources.forEach( function (source) {
                bundle.addSource({
                        filename: source.filename,
                        content: source.content.clone(),
                        separator: source.separator
                });
        });

        return bundle;
},

generateMap: function generateMap ( options ) {
        var this$1 = this;
        if ( options === void 0 ) options = {};

        var names = [];
        this.sources.forEach( function (source) {
                Object.keys( source.content.storedNames ).forEach( function (name) {
                        if ( !~names.indexOf( name ) ) { names.push( name ); }
                });
        });

        var mappings = new Mappings( options.hires );

        if ( this.intro ) {
                mappings.advance( this.intro );
        }

        this.sources.forEach( function ( source, i ) {
                if ( i > 0 ) {
                        mappings.advance( this$1.separator );
                }

                var sourceIndex = source.filename ? this$1.uniqueSourceIndexByFilename[ source.filename ] : -1;
                var magicString = source.content;
                var locate = getLocator$1( magicString.original );

                if ( magicString.intro ) {
                        mappings.advance( magicString.intro );
                }

                magicString.firstChunk.eachNext( function (chunk) {
                        var loc = locate( chunk.start );

                        if ( chunk.intro.length ) { mappings.advance( chunk.intro ); }

                        if ( source.filename ) {
                                if ( chunk.edited ) {
                                        mappings.addEdit( sourceIndex, chunk.content, chunk.original, loc, chunk.storeName ? names.indexOf( chunk.original ) : -1 );
                                } else {
                                        mappings.addUneditedChunk( sourceIndex, chunk, magicString.original, loc, magicString.sourcemapLocations );
                                }
                        }

                        else {
                                mappings.advance( chunk.content );
                        }

                        if ( chunk.outro.length ) { mappings.advance( chunk.outro ); }
                });

                if ( magicString.outro ) {
                        mappings.advance( magicString.outro );
                }
        });

        return new SourceMap({
                file: ( options.file ? options.file.split( /[\/\\]/ ).pop() : null ),
                sources: this.uniqueSources.map( function (source) {
                        return options.file ? getRelativePath( options.file, source.filename ) : source.filename;
                }),
                sourcesContent: this.uniqueSources.map( function (source) {
                        return options.includeContent ? source.content : null;
                }),
                names: names,
                mappings: mappings.encode()
        });
},

getIndentString: function getIndentString () {
        var indentStringCounts = {};

        this.sources.forEach( function (source) {
                var indentStr = source.content.indentStr;

                if ( indentStr === null ) { return; }

                if ( !indentStringCounts[ indentStr ] ) { indentStringCounts[ indentStr ] = 0; }
                indentStringCounts[ indentStr ] += 1;
        });

        return ( Object.keys( indentStringCounts ).sort( function ( a, b ) {
                return indentStringCounts[a] - indentStringCounts[b];
        })[0] ) || '\t';
},

indent: function indent ( indentStr ) {
        var this$1 = this;

        if ( !arguments.length ) {
                indentStr = this.getIndentString();
        }

        if ( indentStr === '' ) { return this; } // noop

        var trailingNewline = !this.intro || this.intro.slice( -1 ) === '\n';

        this.sources.forEach( function ( source, i ) {
                var separator = source.separator !== undefined ? source.separator : this$1.separator;
                var indentStart = trailingNewline || ( i > 0 && /\r?\n$/.test( separator ) );

                source.content.indent( indentStr, {
                        exclude: source.indentExclusionRanges,
                        indentStart: indentStart//: trailingNewline || /\r?\n$/.test( separator )  //true///\r?\n/.test( separator )
                });

                // TODO this is a very slow way to determine this
                trailingNewline = source.content.toString().slice( 0, -1 ) === '\n';
        });

        if ( this.intro ) {
                this.intro = indentStr + this.intro.replace( /^[^\n]/gm, function ( match, index ) {
                        return index > 0 ? indentStr + match : match;
                });
        }

        return this;
},

prepend: function prepend ( str ) {
        this.intro = str + this.intro;
        return this;
},

toString: function toString () {
        var this$1 = this;

        var body = this.sources.map( function ( source, i ) {
                var separator = source.separator !== undefined ? source.separator : this$1.separator;
                var str = ( i > 0 ? separator : '' ) + source.content.toString();

                return str;
        }).join( '' );

        return this.intro + body;
},

trimLines: function trimLines () {
        return this.trim('[\\r\\n]');
},

trim: function trim ( charType ) {
        return this.trimStart( charType ).trimEnd( charType );
},

trimStart: function trimStart ( charType ) {
        var this$1 = this;

        var rx = new RegExp( '^' + ( charType || '\\s' ) + '+' );
        this.intro = this.intro.replace( rx, '' );

        if ( !this.intro ) {
                var source;
                var i = 0;

                do {
                        source = this$1.sources[i];

                        if ( !source ) {
                                break;
                        }

                        source.content.trimStart( charType );
                        i += 1;
                } while ( source.content.toString() === '' ); // TODO faster way to determine non-empty source?
        }

        return this;
},

trimEnd: function trimEnd ( charType ) {
        var this$1 = this;

        var rx = new RegExp( ( charType || '\\s' ) + '+$' );

        var source;
        var i = this.sources.length - 1;

        do {
                source = this$1.sources[i];

                if ( !source ) {
                        this$1.intro = this$1.intro.replace( rx, '' );
                        break;
                }

                source.content.trimEnd( charType );
                i -= 1;
        } while ( source.content.toString() === '' ); // TODO faster way to determine non-empty source?

        return this;
}

};

function counter ( used ) {

var counts = {};

used.forEach( function (name) { return counts[ name ] = 1; } );

return function ( name ) {
        if ( name in counts ) {
                return ("" + name + (counts[ name ]++));
        }

        counts[ name ] = 1;
        return name;
};

}

var globalWhitelist = {

Array: true,
Boolean: true,
console: true,
Date: true,
decodeURI: true,
decodeURIComponent: true,
encodeURI: true,
encodeURIComponent: true,
Infinity: true,
Intl: true,
isFinite: true,
isNaN: true,
JSON: true,
Map: true,
Math: true,
NaN: true,
Number: true,
Object: true,
parseFloat: true,
parseInt: true,
RegExp: true,
Set: true,
String: true,
undefined: true,

};

function getGlobals ( imports, ref ) {

var globals = ref.globals;
var onerror = ref.onerror;
var onwarn = ref.onwarn;

var globalFn = getGlobalFn( globals );

return imports.map( function (x) {
        var name = globalFn( x.source.value );

        if ( !name ) {
                if ( x.name.startsWith( '__import' ) ) {
                        var error = new Error( ("Could not determine name for imported module '" + (x.source.value) + "' – use options.globals") );
                        if ( onerror ) {
                                onerror( error );
                        } else {
                                throw error;
                        }
                }

                else {
                        var warning = {
                                message: ("No name was supplied for imported module '" + (x.source.value) + "'. Guessing '" + (x.name) + "', but you should use options.globals")
                        };

                        if ( onwarn ) {
                                onwarn( warning );
                        } else {
                                console.warn( warning ); // eslint-disable-line no-console
                        }
                }

                name = x.name;
        }

        return name;
});

}

function getGlobalFn ( globals ) {

if ( typeof globals === 'function' ) { return globals; }
if ( typeof globals === 'object' ) {
        return function (id) { return globals[ id ]; };
}

return function () { return undefined; };

}

function getIntro ( format, options, imports ) {

if ( format === 'es' ) { return ''; }
if ( format === 'amd' ) { return getAmdIntro( options, imports ); }
if ( format === 'cjs' ) { return getCjsIntro( options, imports ); }
if ( format === 'iife' ) { return getIifeIntro( options, imports ); }
if ( format === 'umd' ) { return getUmdIntro( options, imports ); }
if ( format === 'eval' ) { return getEvalIntro( options, imports ); }

throw new Error( ("Not implemented: " + format) );

}

function getAmdIntro ( options, imports ) {

var sourceString = imports.length ?
        ("[ " + (imports.map( function (declaration) { return ("'" + (removeExtension( declaration.source.value )) + "'"); } ).join( ', ' )) + " ], ") :
        '';

var id = options.amd && options.amd.id;

return ("define(" + (id ? (" '" + id + "', ") : '') + sourceString + "function (" + (paramString( imports )) + ") { 'use strict';\n\n");

}

function getCjsIntro ( options, imports ) {

var requireBlock = imports
        .map( function (declaration) { return ("var " + (declaration.name) + " = require( '" + (declaration.source.value) + "' );"); } )
        .join( '\n\n' );

if ( requireBlock ) {
        return ("'use strict';\n\n" + requireBlock + "\n\n");
}

return "'use strict';\n\n";

}

function getIifeIntro ( options, imports ) {

if ( !options.name ) {
        throw new Error( "Missing required 'name' option for IIFE export" );
}

return ("var " + (options.name) + " = (function (" + (paramString( imports )) + ") { 'use strict';\n\n");

}

function getUmdIntro ( options, imports ) {

if ( !options.name ) {
        throw new Error( "Missing required 'name' option for UMD export" );
}

var amdId = options.amd && options.amd.id ? ("'" + (options.amd.id) + "', ") : '';

var amdDeps = imports.length ? ("[" + (imports.map( function (declaration) { return ("'" + (removeExtension( declaration.source.value )) + "'"); } ).join( ', ')) + "], ") : '';
var cjsDeps = imports.map( function (declaration) { return ("require('" + (declaration.source.value) + "')"); } ).join( ', ' );
var globalDeps = getGlobals( imports, options );

return deindent(["\n\t\t(function ( global, factory ) {\n\t\t\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(", ") :\n\t\t\ttypeof define === 'function' && define.amd ? define(", "", "factory) :\n\t\t\t(global.", " = factory(", "));\n\t\t}(this, (function (", ") { 'use strict';"], cjsDeps, amdId, amdDeps, options.name, globalDeps, paramString( imports )) + '\n\n';

}

function getEvalIntro ( options, imports ) {

return ("(function (" + (paramString( imports )) + ") { 'use strict';\n\n");

}

function paramString ( imports ) {

return imports.length ? (" " + (imports.map( function (dep) { return dep.name; } ).join( ', ' )) + " ") : '';

}

function removeExtension ( file ) {

var index = file.lastIndexOf( '.' );
return ~index ? file.slice( 0, index ) : file;

}

function getOutro ( format, name, options, imports ) {

if ( format === 'es' ) {
        return ("export default " + name + ";");
}

if ( format === 'amd' ) {
        return ("return " + name + ";\n\n});");
}

if ( format === 'cjs' ) {
        return ("module.exports = " + name + ";");
}

if ( format === 'iife' ) {
        var globals = getGlobals( imports, options );
        return ("return " + name + ";\n\n}(" + (globals.join( ', ' )) + "));");
}

if ( format === 'eval' ) {
        var globals$1 = getGlobals( imports, options );
        return ("return " + name + ";\n\n}(" + (globals$1.join( ', ' )) + "));");
}

if ( format === 'umd' ) {
        return ("return " + name + ";\n\n})));");
}

throw new Error( ("Not implemented: " + format) );

}

function annotateWithScopes ( expression ) {

var scope = new Scope( null, false );

walk$2( expression, {
        enter: function enter ( node ) {
                if ( /Function/.test( node.type ) ) {
                        if ( node.type === 'FunctionDeclaration' ) {
                                scope.declarations[ node.id.name ] = true;
                        } else {
                                node._scope = scope = new Scope( scope, false );
                                if ( node.id ) { scope.declarations[ node.id.name ] = true; }
                        }

                        node.params.forEach( function (param) {
                                extractNames( param ).forEach( function (name) {
                                        scope.declarations[ name ] = true;
                                });
                        });
                }

                else if ( /For(?:In|Of)Statement/.test( node.type ) ) {
                        node._scope = scope = new Scope( scope, true );
                }

                else if ( node.type === 'BlockStatement' ) {
                        node._scope = scope = new Scope( scope, true );
                }

                else if ( /Declaration/.test( node.type ) ) {
                        scope.addDeclaration( node );
                }
        },

        leave: function leave ( node ) {
                if ( node._scope ) {
                        scope = scope.parent;
                }
        }
});

return scope;

}

var Scope = function Scope ( parent, block ) {

this.parent = parent;
this.block = block;
this.declarations = Object.create( null );

};

Scope.prototype.addDeclaration = function addDeclaration ( node ) {

        var this$1 = this;

if ( node.kind === 'var' && !this.block && this.parent ) {
        this.parent.addDeclaration( node );
} else if ( node.type === 'VariableDeclaration' ) {
        node.declarators.forEach( function (declarator) {
                extractNames( declarator.id ).forEach( function (name) {
                        this$1.declarations[ name ] = true;
                });
        });
} else {
        this.declarations[ node.id.name ] = true;
}

};

Scope.prototype.has = function has ( name ) {

return name in this.declarations || this.parent && this.parent.has( name );

};

function extractNames ( param ) {

var names = [];
extractors[ param.type ]( names, param );
return names;

}

var extractors = {

Identifier: function Identifier ( names, param ) {
        names.push( param.name );
},

ObjectPattern: function ObjectPattern ( names, param ) {
        param.properties.forEach( function (prop) {
                extractors[ prop.value.type ]( names, prop.value );
        });
},

ArrayPattern: function ArrayPattern ( names, param ) {
        param.elements.forEach( function (element) {
                if ( element ) { extractors[ element.type ]( names, element ); }
        });
},

RestElement: function RestElement ( names, param ) {
        extractors[ param.argument.type ]( names, param.argument );
},

AssignmentPattern: function AssignmentPattern ( names, param ) {
        extractors[ param.left.type ]( names, param.left );
}

};

var Generator = function Generator ( parsed, source, name, names, visitors, options ) {

this.parsed = parsed;
this.source = source;
this.name = name;
this.names = names;
this.visitors = visitors;
this.options = options;

this.imports = [];
this.helpers = {};
this.components = {};
this.events = {};

this.bindingGroups = [];

// track which properties are needed, so we can provide useful info
// in dev mode
this.expectedProperties = {};

this.elementDepth = 0;

this.code = new MagicString$1( source );
this.getUniqueName = counter( names );
this.cssId = parsed.css ? ("svelte-" + (parsed.hash)) : '';
this.usesRefs = false;

this._callbacks = {};

};

Generator.prototype.addSourcemapLocations = function addSourcemapLocations ( node ) {

        var this$1 = this;

walk$2( node, {
        enter: function (node) {
                this$1.code.addSourcemapLocation( node.start );
                this$1.code.addSourcemapLocation( node.end );
        }
});

};

Generator.prototype.contextualise = function contextualise ( expression, isEventHandler ) {

        var this$1 = this;

this.addSourcemapLocations( expression );

var usedContexts = [];
var dependencies = [];

var ref = this;
        var code = ref.code;
        var helpers = ref.helpers;
var ref$1 = this.current;
        var contextDependencies = ref$1.contextDependencies;
        var contexts = ref$1.contexts;
        var indexes = ref$1.indexes;

var scope = annotateWithScopes( expression );

walk$2( expression, {
        enter: function enter ( node, parent, key ) {
                if ( node._scope ) {
                        scope = node._scope;
                        return;
                }

                if ( isReference( node, parent ) ) {
                        var ref = flatten( node );
                                var name = ref.name;
                        if ( scope.has( name ) ) { return; }

                        if ( parent && parent.type === 'CallExpression' && node === parent.callee && helpers[ name ] ) {
                                code.prependRight( node.start, "template.helpers." );
                        }

                        else if ( name === 'event' && isEventHandler ) {
                                // noop
                        }

                        else if ( name in contexts ) {
                                var context = contexts[ name ];
                                if ( context !== name ) {
                                        // this is true for 'reserved' names like `root` and `component`
                                        code.overwrite( node.start, node.start + name.length, context, true );
                                }

                                dependencies.push.apply( dependencies, contextDependencies[ name ] );
                                if ( !~usedContexts.indexOf( name ) ) { usedContexts.push( name ); }
                        }

                        else if ( indexes[ name ] ) {
                                var context$1 = indexes[ name ];
                                if ( !~usedContexts.indexOf( context$1 ) ) { usedContexts.push( context$1 ); }
                        }

                        else {
                                // handle shorthand properties
                                if ( parent && parent.type === 'Property' && parent.shorthand ) {
                                        if ( key === 'key' ) {
                                                code.appendLeft( node.start, (name + ": ") );
                                                return;
                                        }
                                }

                                if ( globalWhitelist[ name ] ) {
                                        code.prependRight( node.start, ("( '" + name + "' in root ? root.") );
                                        code.appendLeft( node.object ? node.object.end : node.end, (" : " + name + " )") );
                                } else {
                                        code.prependRight( node.start, "root." );
                                }

                                dependencies.push( name );
                                if ( !~usedContexts.indexOf( 'root' ) ) { usedContexts.push( 'root' ); }
                        }

                        this.skip();
                }
        },

        leave: function leave ( node ) {
                if ( node._scope ) { scope = scope.parent; }
        }
});

dependencies.forEach( function (name) {
        this$1.expectedProperties[ name ] = true;
});

return {
        dependencies: dependencies,
        contexts: usedContexts,
        snippet: ("[✂" + (expression.start) + "-" + (expression.end) + "✂]"),
        string: this.code.slice( expression.start, expression.end )
};

};

Generator.prototype.fire = function fire ( eventName, data ) {

        var this$1 = this;

var handlers = eventName in this._callbacks && this._callbacks[ eventName ].slice();
if ( !handlers ) { return; }

for ( var i = 0; i < handlers.length; i += 1 ) {
        handlers[i].call( this$1, data );
}

};

Generator.prototype.generate = function generate ( result, options, ref ) {

        var this$1 = this;
        var name = ref.name;
        var format = ref.format;

if ( this.imports.length ) {
        var statements = [];

        this.imports.forEach( function ( declaration, i ) {
                if ( format === 'es' ) {
                        statements.push( this$1.source.slice( declaration.start, declaration.end ) );
                        return;
                }

                var defaultImport = declaration.specifiers.find( function (x) { return x.type === 'ImportDefaultSpecifier' || x.type === 'ImportSpecifier' && x.imported.name === 'default'; } );
                var namespaceImport = declaration.specifiers.find( function (x) { return x.type === 'ImportNamespaceSpecifier'; } );
                var namedImports = declaration.specifiers.filter( function (x) { return x.type === 'ImportSpecifier' && x.imported.name !== 'default'; } );

                var name = ( defaultImport || namespaceImport ) ? ( defaultImport || namespaceImport ).local.name : ("__import" + i);
                declaration.name = name; // hacky but makes life a bit easier later

                namedImports.forEach( function (specifier) {
                        statements.push( ("var " + (specifier.local.name) + " = " + name + "." + (specifier.imported.name)) );
                });

                if ( defaultImport ) {
                        statements.push( (name + " = ( " + name + " && " + name + ".__esModule ) ? " + name + "['default'] : " + name + ";") );
                }
        });

        result = (statements.join( '\n' )) + "\n\n" + result;
}

var pattern = /\[✂(\d+)-(\d+)$/;

var parts = result.split( '✂]' );
var finalChunk = parts.pop();

var compiled = new Bundle({ separator: '' });

function addString ( str ) {
        compiled.addSource({
                content: new MagicString$1( str )
        });
}

var intro = getIntro( format, options, this.imports );
if ( intro ) { addString( intro ); }

var filename = options.filename;

// special case — the source file doesn't actually get used anywhere. we need
// to add an empty file to populate map.sources and map.sourcesContent
if ( !parts.length ) {
        compiled.addSource({
                filename: filename,
                content: new MagicString$1( this.source ).remove( 0, this.source.length )
        });
}

parts.forEach( function (str) {
        var chunk = str.replace( pattern, '' );
        if ( chunk ) { addString( chunk ); }

        var match = pattern.exec( str );

        var snippet = this$1.code.snip( +match[1], +match[2] );

        compiled.addSource({
                filename: filename,
                content: snippet
        });
});

addString( finalChunk );
addString( '\n\n' + getOutro( format, name, options, this.imports ) );

return {
        code: compiled.toString(),
        map: compiled.generateMap({ includeContent: true, file: options.outputFilename })
};

};

Generator.prototype.getUniqueNameMaker = function getUniqueNameMaker () {

return counter( this.names );

};

Generator.prototype.parseJs = function parseJs () {

        var this$1 = this;

var ref = this;
        var source = ref.source;
var ref$1 = this.parsed;
        var js = ref$1.js;

var imports = this.imports;
var computations = [];
var defaultExport = null;
var templateProperties = {};

if ( js ) {
        this.addSourcemapLocations( js.content );

        // imports need to be hoisted out of the IIFE
        for ( var i = 0; i < js.content.body.length; i += 1 ) {
                var node = js.content.body[i];
                if ( node.type === 'ImportDeclaration' ) {
                        var a = node.start;
                        var b = node.end;
                        while ( /[ \t]/.test( source[ a - 1 ] ) ) { a -= 1; }
                        while ( source[b] === '\n' ) { b += 1; }

                        imports.push( node );
                        this$1.code.remove( a, b );
                }
        }

        defaultExport = js.content.body.find( function (node) { return node.type === 'ExportDefaultDeclaration'; } );

        if ( defaultExport ) {
                var finalNode = js.content.body[ js.content.body.length - 1 ];
                if ( defaultExport === finalNode ) {
                        // export is last property, we can just return it
                        this.code.overwrite( defaultExport.start, defaultExport.declaration.start, "return " );
                } else {
                        // TODO ensure `template` isn't already declared
                        this.code.overwrite( defaultExport.start, defaultExport.declaration.start, "var template = " );

                        var i$1 = defaultExport.start;
                        while ( /\s/.test( source[ i$1 - 1 ] ) ) { i$1--; }

                        var indentation = source.slice( i$1, defaultExport.start );
                        this.code.appendLeft( finalNode.end, ("\n\n" + indentation + "return template;") );
                }

                defaultExport.declaration.properties.forEach( function (prop) {
                        templateProperties[ prop.key.name ] = prop;
                });

                this.code.prependRight( js.content.start, 'var template = (function () {' );
        } else {
                this.code.prependRight( js.content.start, '(function () {' );
        }

        this.code.appendLeft( js.content.end, '}());' );

        [ 'helpers', 'events', 'components' ].forEach( function (key) {
                if ( templateProperties[ key ] ) {
                        templateProperties[ key ].value.properties.forEach( function (prop) {
                                this$1[ key ][ prop.key.name ] = prop.value;
                        });
                }
        });

        if ( templateProperties.computed ) {
                var dependencies = new Map();

                templateProperties.computed.value.properties.forEach( function (prop) {
                        var key = prop.key.name;
                        var value = prop.value;

                        var deps = value.params.map( function (param) { return param.type === 'AssignmentPattern' ? param.left.name : param.name; } );
                        dependencies.set( key, deps );
                });

                var visited = new Set();

                function visit ( key ) {
                        if ( !dependencies.has( key ) ) { return; } // not a computation

                        if ( visited.has( key ) ) { return; }
                        visited.add( key );

                        var deps = dependencies.get( key );
                        deps.forEach( visit );

                        computations.push({ key: key, deps: deps });
                }

                templateProperties.computed.value.properties.forEach( function (prop) { return visit( prop.key.name ); } );
        }
}

return {
        computations: computations,
        defaultExport: defaultExport,
        templateProperties: templateProperties
};

};

Generator.prototype.on = function on ( eventName, handler ) {

var handlers = this._callbacks[ eventName ] || ( this._callbacks[ eventName ] = [] );
handlers.push( handler );

};

Generator.prototype.pop = function pop () {

var tail = this.current;
this.current = tail.parent;

return tail;

};

Generator.prototype.push = function push ( fragment ) {

var newFragment = Object.assign( {}, this.current, fragment, {
        parent: this.current
});

this.current = newFragment;

};

Generator.prototype.visit = function visit ( node ) {

        var this$1 = this;

var visitor = this.visitors[ node.type ];
if ( !visitor ) { throw new Error( ("Not implemented: " + (node.type)) ); }

if ( visitor.enter ) { visitor.enter( this, node ); }

if ( visitor.type === 'Element' ) {
        this.elementDepth += 1;
}

if ( node.children ) {
        node.children.forEach( function (child) {
                this$1.visit( child );
        });
}

if ( visitor.type === 'Element' ) {
        this.elementDepth -= 1;
}

if ( visitor.leave ) { visitor.leave( this, node ); }

};

function appendNode ( node, target ) {

target.appendChild( node );

}

function insertNode ( node, target, anchor ) {

target.insertBefore( node, anchor );

}

function detachNode ( node ) {

node.parentNode.removeChild( node );

}

function detachBetween ( before, after ) {

while ( before.nextSibling && before.nextSibling !== after ) {
        before.parentNode.removeChild( before.nextSibling );
}

}

function teardownEach ( iterations, detach, start ) {

for ( var i = ( start || 0 ); i < iterations.length; i += 1 ) {
        iterations[i].teardown( detach );
}

}

function createElement ( name ) {

return document.createElement( name );

}

function createSvgElement ( name ) {

return document.createElementNS( 'http://www.w3.org/2000/svg', name );

}

function createText ( data ) {

return document.createTextNode( data );

}

function createComment () {

return document.createComment( '' );

}

function addEventListener ( node, event, handler ) {

node.addEventListener ( event, handler, false );

}

function removeEventListener ( node, event, handler ) {

node.removeEventListener ( event, handler, false );

}

function setAttribute ( node, attribute, value ) {

node.setAttribute ( attribute, value );

}

function setXlinkAttribute ( node, attribute, value ) {

node.setAttributeNS( 'http://www.w3.org/1999/xlink', attribute, value );

}

function getBindingGroupValue ( group ) {

var value = [];
for ( var i = 0; i < group.length; i += 1 ) {
        if ( group[i].checked ) value.push( group[i].__value );
}
return value;

}

function get ( key ) {

return key ? this._state[ key ] : this._state;

}

function fire ( eventName, data ) {

var handlers = eventName in this._handlers && this._handlers[ eventName ].slice();
if ( !handlers ) return;

for ( var i = 0; i < handlers.length; i += 1 ) {
        handlers[i].call( this, data );
}

}

function observe ( key, callback, options ) {

var group = ( options && options.defer ) ? this._observers.pre : this._observers.post;

( group[ key ] || ( group[ key ] = [] ) ).push( callback );

if ( !options || options.init !== false ) {
        callback.__calling = true;
        callback.call( this, this._state[ key ] );
        callback.__calling = false;
}

return {
        cancel: function () {
                var index = group[ key ].indexOf( callback );
                if ( ~index ) group[ key ].splice( index, 1 );
        }
};

}

function observeDev ( key, callback, options ) {

var c = ( key = '' + key ).search( /[^\w]/ );
if ( c > -1 ) {
        var message = "The first argument to component.observe(...) must be the name of a top-level property";
        if ( c > 0 ) message += ", i.e. '" + key.slice( 0, c ) + "' rather than '" + key + "'";

        throw new Error( message );
}

var group = ( options && options.defer ) ? this._observers.pre : this._observers.post;

( group[ key ] || ( group[ key ] = [] ) ).push( callback );

if ( !options || options.init !== false ) {
        callback.__calling = true;
        callback.call( this, this._state[ key ] );
        callback.__calling = false;
}

return {
        cancel: function () {
                var index = group[ key ].indexOf( callback );
                if ( ~index ) group[ key ].splice( index, 1 );
        }
};

}

function on ( eventName, handler ) {

if ( eventName === 'teardown' ) return this.on( 'destroy', handler );

var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
handlers.push( handler );

return {
        cancel: function () {
                var index = handlers.indexOf( handler );
                if ( ~index ) handlers.splice( index, 1 );
        }
};

}

function onDev ( eventName, handler ) {

if ( eventName === 'teardown' ) {
        console.warn( "Use component.on('destroy', ...) instead of component.on('teardown', ...) which has been deprecated and will be unsupported in Svelte 2" );
        return this.on( 'destroy', handler );
}

var handlers = this._handlers[ eventName ] || ( this._handlers[ eventName ] = [] );
handlers.push( handler );

return {
        cancel: function () {
                var index = handlers.indexOf( handler );
                if ( ~index ) handlers.splice( index, 1 );
        }
};

}

function set ( newState ) {

this._set( newState );
( this._root || this )._flush();

}

function _flush () {

if ( !this._renderHooks ) return;

while ( this._renderHooks.length ) {
        var hook = this._renderHooks.pop();
        hook.fn.call( hook.context );
}

}

var proto = {

get: get,
fire: fire,
observe: observe,
on: on,
set: set,
_flush: _flush

};

var protoDev = {

get: get,
fire: fire,
observe: observeDev,
on: onDev,
set: set,
_flush: _flush

};

function noop () {}

function dispatchObservers ( component, group, newState, oldState ) {

for ( var key in group ) {
        if ( !( key in newState ) ) continue;

        var newValue = newState[ key ];
        var oldValue = oldState[ key ];

        if ( newValue === oldValue && typeof newValue !== 'object' ) continue;

        var callbacks = group[ key ];
        if ( !callbacks ) continue;

        for ( var i = 0; i < callbacks.length; i += 1 ) {
                var callback = callbacks[i];
                if ( callback.__calling ) continue;

                callback.__calling = true;
                callback.call( component, newValue, oldValue );
                callback.__calling = false;
        }
}

}

var shared = Object.freeze({

noop: noop,
dispatchObservers: dispatchObservers,
appendNode: appendNode,
insertNode: insertNode,
detachNode: detachNode,
detachBetween: detachBetween,
teardownEach: teardownEach,
createElement: createElement,
createSvgElement: createSvgElement,
createText: createText,
createComment: createComment,
addEventListener: addEventListener,
removeEventListener: removeEventListener,
setAttribute: setAttribute,
setXlinkAttribute: setXlinkAttribute,
getBindingGroupValue: getBindingGroupValue,
get: get,
fire: fire,
observe: observe,
observeDev: observeDev,
on: on,
onDev: onDev,
set: set,
_flush: _flush,
proto: proto,
protoDev: protoDev

});

var DomGenerator = (function (Generator$$1) {

function DomGenerator ( parsed, source, name, names, visitors$$1, options ) {
        Generator$$1.call( this, parsed, source, name, names, visitors$$1, options );
        this.renderers = [];
        this.uses = {};

        // allow compiler to deconflict user's `import { get } from 'whatever'` and
        // Svelte's builtin `import { get, ... } from 'svelte/shared.js'`;
        this.importedNames = {};
        this.aliases = {};

        this.importedComponents = {};
}

if ( Generator$$1 ) DomGenerator.__proto__ = Generator$$1;
DomGenerator.prototype = Object.create( Generator$$1 && Generator$$1.prototype );
DomGenerator.prototype.constructor = DomGenerator;

DomGenerator.prototype.addElement = function addElement ( name, renderStatement, needsIdentifier ) {
        if ( needsIdentifier === void 0 ) needsIdentifier = false;

        var isToplevel = this.current.localElementDepth === 0;
        if ( needsIdentifier || isToplevel ) {
                this.current.builders.init.addLine(
                        ("var " + name + " = " + renderStatement + ";")
                );

                this.createMountStatement( name );
        } else {
                this.current.builders.init.addLine( ((this.helper( 'appendNode' )) + "( " + renderStatement + ", " + (this.current.target) + " );") );
        }

        if ( isToplevel ) {
                this.current.builders.detach.addLine( ((this.helper( 'detachNode' )) + "( " + name + " );") );
        }
};

DomGenerator.prototype.addRenderer = function addRenderer ( fragment ) {
        if ( fragment.autofocus ) {
                fragment.builders.init.addLine( ((fragment.autofocus) + ".focus();") );
        }

        // minor hack – we need to ensure that any {{{triples}}} are detached
        // first, so we append normal detach statements to detachRaw
        fragment.builders.detachRaw.addBlock( fragment.builders.detach );

        if ( !fragment.builders.detachRaw.isEmpty() ) {
                fragment.builders.teardown.addBlock( deindent(["\n\t\t\t\tif ( detach ) {\n\t\t\t\t\t", "\n\t\t\t\t}\n\t\t\t"], fragment.builders.detachRaw) );
        }

        var properties = new CodeBuilder();

        if ( fragment.key ) { properties.addBlock( "key: key," ); }

        if ( fragment.builders.mount.isEmpty() ) {
                properties.addBlock( ("mount: " + (this.helper( 'noop' )) + ",") );
        } else {
                properties.addBlock( deindent(["\n\t\t\t\tmount: function ( target, anchor ) {\n\t\t\t\t\t", "\n\t\t\t\t},\n\t\t\t"], fragment.builders.mount) );
        }

        if ( fragment.builders.update.isEmpty() ) {
                properties.addBlock( ("update: " + (this.helper( 'noop' )) + ",") );
        } else {
                properties.addBlock( deindent(["\n\t\t\t\tupdate: function ( changed, ", " ) {\n\t\t\t\t\tvar __tmp;\n\n\t\t\t\t\t", "\n\t\t\t\t},\n\t\t\t"], fragment.params.join( ', ' ), fragment.builders.update) );
        }

        if ( fragment.builders.teardown.isEmpty() ) {
                properties.addBlock( ("teardown: " + (this.helper( 'noop' )) + ",") );
        } else {
                properties.addBlock( deindent(["\n\t\t\t\tteardown: function ( detach ) {\n\t\t\t\t\t", "\n\t\t\t\t}\n\t\t\t"], fragment.builders.teardown) );
        }

        this.renderers.push( deindent(["\n\t\t\tfunction ", " ( ", ", component", " ) {\n\t\t\t\t", "\n\n\t\t\t\treturn {\n\t\t\t\t\t", "\n\t\t\t\t};\n\t\t\t}\n\t\t"], fragment.name, fragment.params.join( ', ' ), fragment.key ? ", key" : '', fragment.builders.init, properties) );
};

DomGenerator.prototype.createAnchor = function createAnchor ( name ) {
        var renderStatement = (this.helper( 'createComment' )) + "()";
        this.addElement( name, renderStatement, true );
};

DomGenerator.prototype.createMountStatement = function createMountStatement ( name ) {
        if ( this.current.target === 'target' ) {
                this.current.builders.mount.addLine( ((this.helper( 'insertNode' )) + "( " + name + ", target, anchor );") );
        } else {
                this.current.builders.init.addLine( ((this.helper( 'appendNode' )) + "( " + name + ", " + (this.current.target) + " );") );
        }
};

DomGenerator.prototype.generateBlock = function generateBlock ( node, name ) {
        var this$1 = this;

        this.push({
                name: name,
                target: 'target',
                localElementDepth: 0,
                builders: getBuilders(),
                getUniqueName: this.getUniqueNameMaker()
        });

        // walk the children here
        node.children.forEach( function (node) { return this$1.visit( node ); } );
        this.addRenderer( this.current );
        this.pop();

        // unset the children, to avoid them being visited again
        node.children = [];
};

DomGenerator.prototype.helper = function helper ( name ) {
        if ( this.options.dev && (name + "Dev") in shared ) {
                name = name + "Dev";
        }

        this.uses[ name ] = true;

        return this.alias( name );
};

DomGenerator.prototype.alias = function alias ( name ) {
        if ( !( name in this.aliases ) ) {
                var alias = name;
                var i = 1;
                while ( alias in this.importedNames ) {
                        alias = name + "$" + (i++);
                }

                this.aliases[ name ] = alias;
        }

        return this.aliases[ name ];
};

return DomGenerator;

}(Generator));

function dom ( parsed, source, options, names ) {

var format = options.format || 'es';
var name = options.name || 'SvelteComponent';

var generator = new DomGenerator( parsed, source, name, names, visitors, options );

var ref = generator.parseJs();
var computations = ref.computations;
var defaultExport = ref.defaultExport;
var templateProperties = ref.templateProperties;

// Remove these after version 2
if ( templateProperties.onrender ) {
        var ref$1 = templateProperties.onrender;
        var key = ref$1.key;
        generator.code.overwrite( key.start, key.end, 'oncreate', true );
        templateProperties.oncreate = templateProperties.onrender;
}

if ( templateProperties.onteardown ) {
        var ref$2 = templateProperties.onteardown;
        var key$1 = ref$2.key;
        generator.code.overwrite( key$1.start, key$1.end, 'ondestroy', true );
        templateProperties.ondestroy = templateProperties.onteardown;
}

generator.imports.forEach( function (node) {
        node.specifiers.forEach( function (specifier) {
                generator.importedNames[ specifier.local.name ] = true;
        });
});

var namespace = null;
if ( templateProperties.namespace ) {
        var ns = templateProperties.namespace.value.value;
        namespace = namespaces[ ns ] || ns;

        removeObjectKey( generator, defaultExport.declaration, 'namespace' );
}

if ( templateProperties.components ) {
        var hasNonImportedComponent = false;
        templateProperties.components.value.properties.forEach( function (property) {
                var key = property.key.name;
                var value = source.slice( property.value.start, property.value.end );
                if ( generator.importedNames[ value ] ) {
                        generator.importedComponents[ key ] = value;
                } else {
                        hasNonImportedComponent = true;
                }
        });
        if ( hasNonImportedComponent ) {
                // remove the specific components which were imported, as we'll refer to them directly
                Object.keys( generator.importedComponents ).forEach ( function (key) {
                        removeObjectKey( generator, templateProperties.components.value, key );
                });
        } else {
                // remove the entire components portion of the export
                removeObjectKey( generator, defaultExport.declaration, 'components' );
        }
}

generator.push({
        name: generator.alias( 'renderMainFragment' ),
        namespace: namespace,
        target: 'target',
        localElementDepth: 0,
        key: null,

        contexts: {},
        indexes: {},

        params: [ 'root' ],
        indexNames: {},
        listNames: {},

        builders: getBuilders(),
        getUniqueName: generator.getUniqueNameMaker()
});

parsed.html.children.forEach( function (node) { return generator.visit( node ); } );

generator.addRenderer( generator.pop() );

var builders = {
        main: new CodeBuilder(),
        init: new CodeBuilder(),
        _set: new CodeBuilder()
};

if ( options.dev ) {
        builders._set.addBlock ( deindent(["\n\t\t\tif ( typeof newState !== 'object' ) {\n\t\t\t\tthrow new Error( 'Component .set was called without an object of data key-values to update.' );\n\t\t\t}\n\t\t"]));
}

builders._set.addLine( 'var oldState = this._state;' );
builders._set.addLine( 'this._state = Object.assign( {}, oldState, newState );' );

if ( computations.length ) {
        var builder = new CodeBuilder();

        computations.forEach( function (ref) {
                var key = ref.key;
                var deps = ref.deps;

                builder.addBlock( deindent(["\n\t\t\t\tif ( isInitial || ", " ) {\n\t\t\t\t\tstate.", " = newState.", " = template.computed.", "( ", " );\n\t\t\t\t}\n\t\t\t"], deps.map( function (dep) { return ("( '" + dep + "' in newState && typeof state." + dep + " === 'object' || state." + dep + " !== oldState." + dep + " )"); } ).join( ' || ' ), key, key, key, deps.map( function (dep) { return ("state." + dep); } ).join( ', ' )) );
        });

        builders.main.addBlock( deindent(["\n\t\t\tfunction ", " ( state, newState, oldState, isInitial ) {\n\t\t\t\t", "\n\t\t\t}\n\t\t"], generator.alias( 'applyComputations' ), builder) );

        builders._set.addLine( ((generator.alias( 'applyComputations' )) + "( this._state, newState, oldState, false )") );
}

// TODO is the `if` necessary?
builders._set.addBlock( deindent(["\n\t\t", "( this, this._observers.pre, newState, oldState );\n\t\tif ( this._fragment ) this._fragment.update( newState, this._state );\n\t\t", "( this, this._observers.post, newState, oldState );\n\t"], generator.helper( 'dispatchObservers' ), generator.helper( 'dispatchObservers' )) );

if ( parsed.js ) {
        builders.main.addBlock( ("[✂" + (parsed.js.content.start) + "-" + (parsed.js.content.end) + "✂]") );
}

 if ( parsed.css && options.css !== false ) {
        builders.main.addBlock( deindent(["\n\t\t\tvar ", " = false;\n\t\t\tfunction ", " () {\n\t\t\t\tvar style = ", "( 'style' );\n\t\t\t\tstyle.textContent = ", ";\n\t\t\t\t", "( style, document.head );\n\n\t\t\t\t", " = true;\n\t\t\t}\n\t\t"], generator.alias( 'addedCss' ), generator.alias( 'addCss' ), generator.helper( 'createElement' ), JSON.stringify( processCss( parsed, generator.code ) ), generator.helper( 'appendNode' ), generator.alias( 'addedCss' )) );
}

var i = generator.renderers.length;
while ( i-- ) { builders.main.addBlock( generator.renderers[i] ); }

builders.init.addLine( "this._torndown = false;" );

if ( parsed.css && options.css !== false ) {
        builders.init.addLine( ("if ( !" + (generator.alias( 'addedCss' )) + " ) " + (generator.alias( 'addCss' )) + "();") );
}

if ( generator.hasComponents ) {
        builders.init.addLine( "this._renderHooks = [];" );
}

if ( generator.hasComplexBindings ) {
        builders.init.addBlock( deindent(["\n\t\t\tthis._bindings = [];\n\t\t\tthis._fragment = ", "( this._state, this );\n\t\t\tif ( options.target ) this._fragment.mount( options.target, null );\n\t\t\twhile ( this._bindings.length ) this._bindings.pop()();\n\t\t"], generator.alias( 'renderMainFragment' )) );

        builders._set.addLine( "while ( this._bindings.length ) this._bindings.pop()();" );
} else {
        builders.init.addBlock( deindent(["\n\t\t\tthis._fragment = ", "( this._state, this );\n\t\t\tif ( options.target ) this._fragment.mount( options.target, null );\n\t\t"], generator.alias( 'renderMainFragment' )) );
}

if ( generator.hasComponents ) {
        var statement = "this._flush();";

        builders.init.addBlock( statement );
        builders._set.addBlock( statement );
}

if ( templateProperties.oncreate ) {
        builders.init.addBlock( deindent(["\n\t\t\tif ( options._root ) {\n\t\t\t\toptions._root._renderHooks.push({ fn: template.oncreate, context: this });\n\t\t\t} else {\n\t\t\t\ttemplate.oncreate.call( this );\n\t\t\t}\n\t\t"]) );
}

var constructorBlock = new CodeBuilder();

constructorBlock.addLine( "options = options || {};" );
if ( generator.usesRefs ) { constructorBlock.addLine( "this.refs = {};" ); }

constructorBlock.addLine(
        ("this._state = " + (templateProperties.data ? "Object.assign( template.data(), options.data )" : "options.data || {}") + ";")
);

if ( templateProperties.computed ) {
        constructorBlock.addLine(
                ((generator.alias( 'applyComputations' )) + "( this._state, this._state, {}, true );")
        );
}

if ( options.dev ) {
        Object.keys( generator.expectedProperties ).forEach( function (prop) {
                constructorBlock.addLine(
                        ("if ( !( '" + prop + "' in this._state ) ) throw new Error( \"Component was created without expected data property '" + prop + "'\" );")
                );
        });

        constructorBlock.addBlock(
                "if ( !options.target && !options._root ) throw new Error( \"'target' is a required option\" );"
        );
}

if ( generator.bindingGroups.length ) {
        constructorBlock.addLine( ("this._bindingGroups = [ " + (Array( generator.bindingGroups.length ).fill( '[]' ).join( ', ' )) + " ];") );
}

constructorBlock.addBlock( deindent(["\n\t\tthis._observers = {\n\t\t\tpre: Object.create( null ),\n\t\t\tpost: Object.create( null )\n\t\t};\n\n\t\tthis._handlers = Object.create( null );\n\n\t\tthis._root = options._root;\n\t\tthis._yield = options._yield;\n\n\t\t", "\n\t"], builders.init) );

builders.main.addBlock( deindent(["\n\t\tfunction ", " ( options ) {\n\t\t\t", "\n\t\t}\n\t"], name, constructorBlock) );

var sharedPath = options.shared === true ? 'svelte/shared.js' : options.shared;

if ( sharedPath ) {
        var base = templateProperties.methods ? "{}, template.methods" : "{}";
        builders.main.addBlock( (name + ".prototype = Object.assign( " + base + ", " + (generator.helper( 'proto' )) + " );") );
} else {
        if ( templateProperties.methods ) {
                builders.main.addBlock( (name + ".prototype = template.methods;") );
        }

        [ 'get', 'fire', 'observe', 'on', 'set', '_flush' ].forEach( function (methodName) {
                builders.main.addLine( (name + ".prototype." + methodName + " = " + (generator.helper( methodName )) + ";") );
        });
}

// TODO deprecate component.teardown()
builders.main.addBlock( deindent(["\n\t\t", ".prototype._set = function _set ( newState ) {\n\t\t\t", "\n\t\t};\n\n\t\t", ".prototype.teardown = ", ".prototype.destroy = function destroy ( detach ) {\n\t\t\tthis.fire( 'destroy' );", "\n\n\t\t\tthis._fragment.teardown( detach !== false );\n\t\t\tthis._fragment = null;\n\n\t\t\tthis._state = {};\n\t\t\tthis._torndown = true;\n\t\t};\n\t"], name, builders._set, name, name, templateProperties.ondestroy ? "\ntemplate.ondestroy.call( this );" : "") );

if ( sharedPath ) {
        if ( format !== 'es' ) {
                throw new Error( "Components with shared helpers must be compiled to ES2015 modules (format: 'es')" );
        }

        var names$1 = Object.keys( generator.uses ).map( function (name) {
                return name !== generator.aliases[ name ] ? (name + " as " + (generator.aliases[ name ])) : name;
        });

        builders.main.addLineAtStart(
                ("import { " + (names$1.join( ', ' )) + " } from " + (JSON.stringify( sharedPath )))
        );
} else {
        Object.keys( generator.uses ).forEach( function (key) {
                var fn = shared[ key ]; // eslint-disable-line import/namespace
                builders.main.addBlock( fn.toString().replace( /^function [^(]*/, 'function ' + generator.aliases[ key ] ) );
        });
}

return generator.generate( builders.main.toString(), options, { name: name, format: format } );

}

var Comment$3 = {

// do nothing

};

var EachBlock$1 = {

enter: function enter ( generator, node ) {
        var ref = generator.contextualise( node.expression );
        var dependencies = ref.dependencies;
        var snippet = ref.snippet;

        var open = "${ " + snippet + ".map( " + (node.index ? ("( " + (node.context) + ", " + (node.index) + " )") : node.context) + " => `";
        generator.append( open );

        // TODO should this be the generator's job? It's duplicated between
        // here and the equivalent DOM compiler visitor
        var contexts = Object.assign( {}, generator.current.contexts );
        contexts[ node.context ] = node.context;

        var indexes = Object.assign( {}, generator.current.indexes );
        if ( node.index ) { indexes[ node.index ] = node.context; }

        var contextDependencies = Object.assign( {}, generator.current.contextDependencies );
        contextDependencies[ node.context ] = dependencies;

        generator.push({
                contexts: contexts,
                indexes: indexes,
                contextDependencies: contextDependencies
        });
},

leave: function leave ( generator ) {
        var close = "` ).join( '' )}";
        generator.append( close );

        generator.pop();
}

};

var Component$1 = {

enter: function enter ( generator, node ) {
        function stringify ( chunk ) {
                if ( chunk.type === 'Text' ) { return chunk.data; }
                if ( chunk.type === 'MustacheTag' ) {
                        var ref = generator.contextualise( chunk.expression );
                        var snippet = ref.snippet;
                        return '${__escape( ' + snippet + ')}';
                }
        }

        var attributes = [];
        var bindings = [];

        node.attributes.forEach( function (attribute) {
                if ( attribute.type === 'Attribute' ) {
                        attributes.push( attribute );
                } else if ( attribute.type === 'Binding' ) {
                        bindings.push( attribute );
                }
        });

        var props = attributes
                .map( function (attribute) {
                        var value;

                        if ( attribute.value === true ) {
                                value = "true";
                        } else if ( attribute.value.length === 0 ) {
                                value = "''";
                        } else if ( attribute.value.length === 1 ) {
                                var chunk = attribute.value[0];
                                if ( chunk.type === 'Text' ) {
                                        value = isNaN( chunk.data ) ? JSON.stringify( chunk.data ) : chunk.data;
                                } else {
                                        var ref = generator.contextualise( chunk.expression );
                                        var snippet = ref.snippet;
                                        value = snippet;
                                }
                        } else {
                                value = '`' + attribute.value.map( stringify ).join( '' ) + '`';
                        }

                        return ((attribute.name) + ": " + value);
                })
                .concat( bindings.map( function (binding) {
                        var ref = flatten( binding.value );
                        var name = ref.name;
                        var keypath = ref.keypath;
                        var value = name in generator.current.contexts ? keypath : ("root." + keypath);
                        return ((binding.name) + ": " + value);
                }))
                .join( ', ' );

        var expression = node.name === ':Self' ? generator.name : ("template.components." + (node.name));

        bindings.forEach( function (binding) {
                generator.addBinding( binding, expression );
        });

        var open = "${" + expression + ".render({" + props + "}";

        if ( node.children.length ) {
                open += ", { yield: () => `";
        }

        generator.append( open );
},

leave: function leave ( generator, node ) {
        var close = node.children.length ? "` })}" : ')}';
        generator.append( close );
}

};

var Element$1 = {

enter: function enter ( generator, node ) {
        if ( node.name in generator.components || node.name === ':Self' ) {
                Component$1.enter( generator, node );
                return;
        }

        var openingTag = "<" + (node.name);

        node.attributes.forEach( function (attribute) {
                if ( attribute.type !== 'Attribute' ) { return; }

                var str = " " + (attribute.name);

                if ( attribute.value !== true ) {
                        str += "=\"" + attribute.value.map( function (chunk) {
                                if ( chunk.type === 'Text' ) {
                                        return chunk.data;
                                }

                                var ref = generator.contextualise( chunk.expression );
                                var snippet = ref.snippet;
                                return '${' + snippet + '}';
                        }).join( '' ) + "\"";
                }

                openingTag += str;
        });

        if ( generator.cssId && !generator.elementDepth ) {
                openingTag += " " + (generator.cssId);
        }

        openingTag += '>';

        generator.append( openingTag );
},

leave: function leave ( generator, node ) {
        if ( node.name in generator.components || node.name === ':Self' ) {
                Component$1.leave( generator, node );
                return;
        }

        if ( !isVoidElementName( node.name ) ) {
                generator.append( ("</" + (node.name) + ">") );
        }
}

};

var IfBlock$1 = {

enter: function enter ( generator, node ) {
        var ref = generator.contextualise( node.expression );
        var snippet = ref.snippet;

        generator.append( '${ ' + snippet + ' ? `' );

        generator.push({
                conditions: generator.current.conditions.concat( snippet )
        });
},

leave: function leave ( generator, node ) {
        generator.append( '` : `' );
        if ( node.else ) { node.else.children.forEach( function (child) { return generator.visit( child ); } ); }
        generator.append( '` }' );

        generator.pop();
}

};

var MustacheTag$1 = {

enter: function enter ( generator, node ) {
        var ref = generator.contextualise( node.expression );
        var snippet = ref.snippet;
        generator.append( '${__escape( ' + snippet + ' )}' );
}

};

var RawMustacheTag$1 = {

enter: function enter ( generator, node ) {
        var ref = generator.contextualise( node.expression );
        var snippet = ref.snippet;
        generator.append( '${' + snippet + '}' );
}

};

var Text$1 = {

enter: function enter ( generator, node ) {
        generator.append( node.data.replace( /\${/g, '\\${' ) );
}

};

var YieldTag$1 = {

enter: function enter ( generator ) {
        generator.append( "${options && options.yield ? options.yield() : ''}" );
}

};

var visitors$1 = {

Comment: Comment$3,
EachBlock: EachBlock$1,
Element: Element$1,
IfBlock: IfBlock$1,
MustacheTag: MustacheTag$1,
RawMustacheTag: RawMustacheTag$1,
Text: Text$1,
YieldTag: YieldTag$1

};

var SsrGenerator = (function (Generator$$1) {

function SsrGenerator ( parsed, source, name, names, visitors, options ) {
        Generator$$1.call( this, parsed, source, name, names, visitors, options );
        this.bindings = [];
        this.renderCode = '';
}

if ( Generator$$1 ) SsrGenerator.__proto__ = Generator$$1;
SsrGenerator.prototype = Object.create( Generator$$1 && Generator$$1.prototype );
SsrGenerator.prototype.constructor = SsrGenerator;

SsrGenerator.prototype.addBinding = function addBinding ( binding, name ) {
        var conditions = [ ("!( '" + (binding.name) + "' in root )")].concat( // TODO handle contextual bindings...
                this.current.conditions.map( function (c) { return ("(" + c + ")"); } )
        );

        var ref = flatten( binding.value );
        var keypath = ref.keypath;

        this.bindings.push( deindent(["\n\t\t\tif ( ", " ) {\n\t\t\t\ttmp = ", ".data();\n\t\t\t\tif ( '", "' in tmp ) {\n\t\t\t\t\troot.", " = tmp.", ";\n\t\t\t\t\tsettled = false;\n\t\t\t\t}\n\t\t\t}\n\t\t"], conditions.join( '&&' ), name, keypath, binding.name, keypath) );
};

SsrGenerator.prototype.append = function append ( code ) {
        this.renderCode += code;
};

return SsrGenerator;

}(Generator));

function ssr ( parsed, source, options, names ) {

var format = options.format || 'cjs';
var name = options.name || 'SvelteComponent';

var generator = new SsrGenerator( parsed, source, name, names, visitors$1, options );

var ref = generator.parseJs();
var computations = ref.computations;
var templateProperties = ref.templateProperties;

var builders = {
        main: new CodeBuilder(),
        bindings: new CodeBuilder(),
        render: new CodeBuilder(),
        renderCss: new CodeBuilder()
};

// create main render() function
generator.push({
        contexts: {},
        indexes: {},
        conditions: []
});

parsed.html.children.forEach( function (node) { return generator.visit( node ); } );

builders.render.addLine(
        templateProperties.data ? "root = Object.assign( template.data(), root || {} );" : "root = root || {};"
);

computations.forEach( function (ref) {
        var key = ref.key;
        var deps = ref.deps;

        builders.render.addLine(
                ("root." + key + " = template.computed." + key + "( " + (deps.map( function (dep) { return ("root." + dep); } ).join( ', ' )) + " );")
        );
});

if ( generator.bindings.length ) {
        var bindings = generator.bindings.join( '\n\n' );

        builders.render.addBlock( deindent(["\n\t\t\tvar settled = false;\n\t\t\tvar tmp;\n\n\t\t\twhile ( !settled ) {\n\t\t\t\tsettled = true;\n\n\t\t\t\t", "\n\t\t\t}\n\t\t"], bindings) );
}

builders.render.addBlock(
        ("return `" + (generator.renderCode) + "`;")
);

// create renderCss() function
builders.renderCss.addBlock(
        "var components = [];"
);

if ( parsed.css ) {
        builders.renderCss.addBlock( deindent(["\n\t\t\tcomponents.push({\n\t\t\t\tfilename: ", ".filename,\n\t\t\t\tcss: ", ",\n\t\t\t\tmap: null // TODO\n\t\t\t});\n\t\t"], name, JSON.stringify( processCss( parsed, generator.code ) )) );
}

if ( templateProperties.components ) {
        builders.renderCss.addBlock( deindent(["\n\t\t\tvar seen = {};\n\n\t\t\tfunction addComponent ( component ) {\n\t\t\t\tvar result = component.renderCss();\n\t\t\t\tresult.components.forEach( x => {\n\t\t\t\t\tif ( seen[ x.filename ] ) return;\n\t\t\t\t\tseen[ x.filename ] = true;\n\t\t\t\t\tcomponents.push( x );\n\t\t\t\t});\n\t\t\t}\n\t\t"]) );

        templateProperties.components.value.properties.forEach( function (prop) {
                builders.renderCss.addLine( ("addComponent( template.components." + (prop.key.name) + " );") );
        });
}

builders.renderCss.addBlock( deindent(["\n\t\treturn {\n\t\t\tcss: components.map( x => x.css ).join( '\\n' ),\n\t\t\tmap: null,\n\t\t\tcomponents\n\t\t};\n\t"]) );

if ( parsed.js ) {
        builders.main.addBlock( ("[✂" + (parsed.js.content.start) + "-" + (parsed.js.content.end) + "✂]") );
}

builders.main.addBlock( deindent(["\n\t\tvar ", " = {};\n\n\t\t", ".filename = ", ";\n\n\t\t", ".data = function () {\n\t\t\treturn ", ";\n\t\t};\n\n\t\t", ".render = function ( root, options ) {\n\t\t\t", "\n\t\t};\n\n\t\t", ".renderCss = function () {\n\t\t\t", "\n\t\t};\n\n\t\tvar escaped = {\n\t\t\t'\"': '&quot;',\n\t\t\t\"'\": '&#39;',\n\t\t\t'&': '&amp;',\n\t\t\t'<': '&lt;',\n\t\t\t'>': '&gt;'\n\t\t};\n\n\t\tfunction __escape ( html ) {\n\t\t\treturn String( html ).replace( /[\"'&<>]/g, match => escaped[ match ] );\n\t\t}\n\t"], name, name, JSON.stringify( options.filename ), name, templateProperties.data ? "template.data()" : "{}", name, builders.render, name, builders.renderCss) );

var result = builders.main.toString();

return generator.generate( result, options, { name: name, format: format } );

}

var version$1 = “1.12.1”;

function normalizeOptions ( options ) {

return Object.assign( {
        generate: 'dom',

        // a filename is necessary for sourcemap generation
        filename: 'SvelteComponent.html',

        onwarn: function (warning) {
                if ( warning.loc ) {
                        console.warn( ("(" + (warning.loc.line) + ":" + (warning.loc.column) + ") – " + (warning.message)) ); // eslint-disable-line no-console
                } else {
                        console.warn( warning.message ); // eslint-disable-line no-console
                }
        },

        onerror: function (error) {
                throw error;
        }
}, options );

}

function compile ( source, _options ) {

var options = normalizeOptions( _options );

var parsed;

try {
        parsed = parse( source, options );
} catch ( err ) {
        options.onerror( err );
        return;
}

var ref = validate( parsed, source, options );
var names = ref.names;

var compiler = options.generate === 'ssr'
        ? ssr
        : dom;

return compiler( parsed, source, options, names );

}

function create ( source, _options ) {

if ( _options === void 0 ) _options = {};

_options.format = 'eval';

var compiled = compile( source, _options );

if ( !compiled || !compiled.code ) {
        return;
}

var result;
try {
        result = (new Function( 'return ' + compiled.code ))();
} catch ( err ) {
        if ( _options.onerror ) {
                _options.onerror( err );
        } else {
                throw err;
        }
        return;
}

return result;

}

exports.compile = compile; exports.create = create; exports.parse = parse; exports.validate = validate; exports.VERSION = version$1;

}((this.svelte = this.svelte || {}))); //# sourceMappingURL=svelte.js.map