function parseWords(e) {
  for (var r = {}, i = e.split(" "), a = 0; a < i.length; ++a) r[i[a]] = true;
  return r;
}
var keywords = parseWords("Tcl safe after append array auto_execok auto_import auto_load auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror binary break catch cd close concat continue dde eof encoding error eval exec exit expr fblocked fconfigure fcopy file fileevent filename filename flush for foreach format gets glob global history http if incr info interp join lappend lindex linsert list llength load lrange lreplace lsearch lset lsort memory msgcat namespace open package parray pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp registry regsub rename resource return scan seek set socket source split string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest tclvars tell time trace unknown unset update uplevel upvar variable vwait"), functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch"), isOperatorChar = /[+\-*&%=<>!?^\/\|]/;
function chain(e, r, i) {
  return r.tokenize = i, i(e, r);
}
function tokenBase(e, s) {
  var l = s.beforeParams;
  s.beforeParams = false;
  var u = e.next();
  if ((u == '"' || u == "'") && s.inParams) return chain(e, s, tokenString(u));
  if (/[\[\]{}\(\),;\.]/.test(u)) return u == "(" && l ? s.inParams = true : u == ")" && (s.inParams = false), null;
  if (/\d/.test(u)) return e.eatWhile(/[\w\.]/), "number";
  if (u == "#") return e.eat("*") ? chain(e, s, tokenComment) : u == "#" && e.match(/ *\[ *\[/) ? chain(e, s, tokenUnparsed) : (e.skipToEnd(), "comment");
  if (u == '"') return e.skipTo(/"/), "comment";
  if (u == "$") return e.eatWhile(/[$_a-z0-9A-Z\.{:]/), e.eatWhile(/}/), s.beforeParams = true, "builtin";
  if (isOperatorChar.test(u)) return e.eatWhile(isOperatorChar), "comment";
  e.eatWhile(/[\w\$_{}\xa1-\uffff]/);
  var d = e.current().toLowerCase();
  return keywords && keywords.propertyIsEnumerable(d) ? "keyword" : functions && functions.propertyIsEnumerable(d) ? (s.beforeParams = true, "keyword") : null;
}
function tokenString(e) {
  return function(r, i) {
    for (var a = false, o, c = false; (o = r.next()) != null; ) {
      if (o == e && !a) {
        c = true;
        break;
      }
      a = !a && o == "\\";
    }
    return c && (i.tokenize = tokenBase), "string";
  };
}
function tokenComment(e, r) {
  for (var i = false, a; a = e.next(); ) {
    if (a == "#" && i) {
      r.tokenize = tokenBase;
      break;
    }
    i = a == "*";
  }
  return "comment";
}
function tokenUnparsed(e, r) {
  for (var i = 0, a; a = e.next(); ) {
    if (a == "#" && i == 2) {
      r.tokenize = tokenBase;
      break;
    }
    a == "]" ? i++ : a != " " && (i = 0);
  }
  return "meta";
}
const tcl = {
  name: "tcl",
  startState: function() {
    return {
      tokenize: tokenBase,
      beforeParams: false,
      inParams: false
    };
  },
  token: function(e, r) {
    return e.eatSpace() ? null : r.tokenize(e, r);
  },
  languageData: { commentTokens: { line: "#" } }
};
export {
  tcl as t
};
