function kw(y) {
  return {
    type: y,
    style: "keyword"
  };
}
var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"), operator = kw("operator"), atom = {
  type: "atom",
  style: "atom"
}, attribute = {
  type: "attribute",
  style: "attribute"
}, type = kw("typedef"), keywords = {
  if: A,
  while: A,
  else: B,
  do: B,
  try: B,
  return: C,
  break: C,
  continue: C,
  new: C,
  throw: C,
  var: kw("var"),
  inline: attribute,
  static: attribute,
  using: kw("import"),
  public: attribute,
  private: attribute,
  cast: kw("cast"),
  import: kw("import"),
  macro: kw("macro"),
  function: kw("function"),
  catch: kw("catch"),
  untyped: kw("untyped"),
  callback: kw("cb"),
  for: kw("for"),
  switch: kw("switch"),
  case: kw("case"),
  default: kw("default"),
  in: operator,
  never: kw("property_access"),
  trace: kw("trace"),
  class: type,
  abstract: type,
  enum: type,
  interface: type,
  typedef: type,
  extends: type,
  implements: type,
  dynamic: type,
  true: atom,
  false: atom,
  null: atom
}, isOperatorChar = /[+\-*&%=<>!?|]/;
function chain(y, J, Y) {
  return J.tokenize = Y, Y(y, J);
}
function toUnescaped(y, J) {
  for (var Y = false, X; (X = y.next()) != null; ) {
    if (X == J && !Y) return true;
    Y = !Y && X == "\\";
  }
}
var type, content;
function ret(y, J, Y) {
  return type = y, content = Y, J;
}
function haxeTokenBase(y, J) {
  var Y = y.next();
  if (Y == '"' || Y == "'") return chain(y, J, haxeTokenString(Y));
  if (/[\[\]{}\(\),;\:\.]/.test(Y)) return ret(Y);
  if (Y == "0" && y.eat(/x/i)) return y.eatWhile(/[\da-f]/i), ret("number", "number");
  if (/\d/.test(Y) || Y == "-" && y.eat(/\d/)) return y.match(/^\d*(?:\.\d*(?!\.))?(?:[eE][+\-]?\d+)?/), ret("number", "number");
  if (J.reAllowed && Y == "~" && y.eat(/\//)) return toUnescaped(y, "/"), y.eatWhile(/[gimsu]/), ret("regexp", "string.special");
  if (Y == "/") return y.eat("*") ? chain(y, J, haxeTokenComment) : y.eat("/") ? (y.skipToEnd(), ret("comment", "comment")) : (y.eatWhile(isOperatorChar), ret("operator", null, y.current()));
  if (Y == "#") return y.skipToEnd(), ret("conditional", "meta");
  if (Y == "@") return y.eat(/:/), y.eatWhile(/[\w_]/), ret("metadata", "meta");
  if (isOperatorChar.test(Y)) return y.eatWhile(isOperatorChar), ret("operator", null, y.current());
  var X;
  if (/[A-Z]/.test(Y)) return y.eatWhile(/[\w_<>]/), X = y.current(), ret("type", "type", X);
  y.eatWhile(/[\w_]/);
  var X = y.current(), Z = keywords.propertyIsEnumerable(X) && keywords[X];
  return Z && J.kwAllowed ? ret(Z.type, Z.style, X) : ret("variable", "variable", X);
}
function haxeTokenString(y) {
  return function(J, Y) {
    return toUnescaped(J, y) && (Y.tokenize = haxeTokenBase), ret("string", "string");
  };
}
function haxeTokenComment(y, J) {
  for (var Y = false, X; X = y.next(); ) {
    if (X == "/" && Y) {
      J.tokenize = haxeTokenBase;
      break;
    }
    Y = X == "*";
  }
  return ret("comment", "comment");
}
var atomicTypes = {
  atom: true,
  number: true,
  variable: true,
  string: true,
  regexp: true
};
function HaxeLexical(y, J, Y, X, Z, Q) {
  this.indented = y, this.column = J, this.type = Y, this.prev = Z, this.info = Q, X != null && (this.align = X);
}
function inScope(y, J) {
  for (var Y = y.localVars; Y; Y = Y.next) if (Y.name == J) return true;
}
function parseHaxe(y, J, Y, X, Z) {
  var Q = y.cc;
  for (cx.state = y, cx.stream = Z, cx.marked = null, cx.cc = Q, y.lexical.hasOwnProperty("align") || (y.lexical.align = true); ; ) if ((Q.length ? Q.pop() : statement)(Y, X)) {
    for (; Q.length && Q[Q.length - 1].lex; ) Q.pop()();
    return cx.marked ? cx.marked : Y == "variable" && inScope(y, X) ? "variableName.local" : Y == "variable" && imported(y, X) ? "variableName.special" : J;
  }
}
function imported(y, J) {
  if (/[a-z]/.test(J.charAt(0))) return false;
  for (var Y = y.importedtypes.length, X = 0; X < Y; X++) if (y.importedtypes[X] == J) return true;
}
function registerimport(y) {
  for (var J = cx.state, Y = J.importedtypes; Y; Y = Y.next) if (Y.name == y) return;
  J.importedtypes = {
    name: y,
    next: J.importedtypes
  };
}
var cx = {
  state: null,
  column: null,
  marked: null,
  cc: null
};
function pass() {
  for (var y = arguments.length - 1; y >= 0; y--) cx.cc.push(arguments[y]);
}
function cont() {
  return pass.apply(null, arguments), true;
}
function inList(y, J) {
  for (var Y = J; Y; Y = Y.next) if (Y.name == y) return true;
  return false;
}
function register(y) {
  var J = cx.state;
  if (J.context) {
    if (cx.marked = "def", inList(y, J.localVars)) return;
    J.localVars = {
      name: y,
      next: J.localVars
    };
  } else if (J.globalVars) {
    if (inList(y, J.globalVars)) return;
    J.globalVars = {
      name: y,
      next: J.globalVars
    };
  }
}
var defaultVars = {
  name: "this",
  next: null
};
function pushcontext() {
  cx.state.context || (cx.state.localVars = defaultVars), cx.state.context = {
    prev: cx.state.context,
    vars: cx.state.localVars
  };
}
function popcontext() {
  cx.state.localVars = cx.state.context.vars, cx.state.context = cx.state.context.prev;
}
popcontext.lex = true;
function pushlex(y, J) {
  var Y = function() {
    var Y2 = cx.state;
    Y2.lexical = new HaxeLexical(Y2.indented, cx.stream.column(), y, null, Y2.lexical, J);
  };
  return Y.lex = true, Y;
}
function poplex() {
  var y = cx.state;
  y.lexical.prev && (y.lexical.type == ")" && (y.indented = y.lexical.indented), y.lexical = y.lexical.prev);
}
poplex.lex = true;
function expect(y) {
  function J(Y) {
    return Y == y ? cont() : y == ";" ? pass() : cont(J);
  }
  return J;
}
function statement(y) {
  return y == "@" ? cont(metadef) : y == "var" ? cont(pushlex("vardef"), vardef1, expect(";"), poplex) : y == "keyword a" ? cont(pushlex("form"), expression, statement, poplex) : y == "keyword b" ? cont(pushlex("form"), statement, poplex) : y == "{" ? cont(pushlex("}"), pushcontext, block, poplex, popcontext) : y == ";" ? cont() : y == "attribute" ? cont(maybeattribute) : y == "function" ? cont(functiondef) : y == "for" ? cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), poplex, statement, poplex) : y == "variable" ? cont(pushlex("stat"), maybelabel) : y == "switch" ? cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), block, poplex, poplex) : y == "case" ? cont(expression, expect(":")) : y == "default" ? cont(expect(":")) : y == "catch" ? cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), statement, poplex, popcontext) : y == "import" ? cont(importdef, expect(";")) : y == "typedef" ? cont(typedef) : pass(pushlex("stat"), expression, expect(";"), poplex);
}
function expression(y) {
  return atomicTypes.hasOwnProperty(y) || y == "type" ? cont(maybeoperator) : y == "function" ? cont(functiondef) : y == "keyword c" ? cont(maybeexpression) : y == "(" ? cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator) : y == "operator" ? cont(expression) : y == "[" ? cont(pushlex("]"), commasep(maybeexpression, "]"), poplex, maybeoperator) : y == "{" ? cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator) : cont();
}
function maybeexpression(y) {
  return y.match(/[;\}\)\],]/) ? pass() : pass(expression);
}
function maybeoperator(y, J) {
  if (y == "operator" && /\+\+|--/.test(J)) return cont(maybeoperator);
  if (y == "operator" || y == ":") return cont(expression);
  if (y != ";") {
    if (y == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator);
    if (y == ".") return cont(property, maybeoperator);
    if (y == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator);
  }
}
function maybeattribute(y) {
  if (y == "attribute") return cont(maybeattribute);
  if (y == "function") return cont(functiondef);
  if (y == "var") return cont(vardef1);
}
function metadef(y) {
  if (y == ":" || y == "variable") return cont(metadef);
  if (y == "(") return cont(pushlex(")"), commasep(metaargs, ")"), poplex, statement);
}
function metaargs(y) {
  if (y == "variable") return cont();
}
function importdef(y, J) {
  if (y == "variable" && /[A-Z]/.test(J.charAt(0))) return registerimport(J), cont();
  if (y == "variable" || y == "property" || y == "." || J == "*") return cont(importdef);
}
function typedef(y, J) {
  if (y == "variable" && /[A-Z]/.test(J.charAt(0))) return registerimport(J), cont();
  if (y == "type" && /[A-Z]/.test(J.charAt(0))) return cont();
}
function maybelabel(y) {
  return y == ":" ? cont(poplex, statement) : pass(maybeoperator, expect(";"), poplex);
}
function property(y) {
  if (y == "variable") return cx.marked = "property", cont();
}
function objprop(y) {
  if (y == "variable" && (cx.marked = "property"), atomicTypes.hasOwnProperty(y)) return cont(expect(":"), expression);
}
function commasep(y, J) {
  function Y(X) {
    return X == "," ? cont(y, Y) : X == J ? cont() : cont(expect(J));
  }
  return function(X) {
    return X == J ? cont() : pass(y, Y);
  };
}
function block(y) {
  return y == "}" ? cont() : pass(statement, block);
}
function vardef1(y, J) {
  return y == "variable" ? (register(J), cont(typeuse, vardef2)) : cont();
}
function vardef2(y, J) {
  if (J == "=") return cont(expression, vardef2);
  if (y == ",") return cont(vardef1);
}
function forspec1(y, J) {
  return y == "variable" ? (register(J), cont(forin, expression)) : pass();
}
function forin(y, J) {
  if (J == "in") return cont();
}
function functiondef(y, J) {
  if (y == "variable" || y == "type") return register(J), cont(functiondef);
  if (J == "new") return cont(functiondef);
  if (y == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext);
}
function typeuse(y) {
  if (y == ":") return cont(typestring);
}
function typestring(y) {
  if (y == "type" || y == "variable") return cont();
  if (y == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex);
}
function typeprop(y) {
  if (y == "variable") return cont(typeuse);
}
function funarg(y, J) {
  if (y == "variable") return register(J), cont(typeuse);
}
const haxe = {
  name: "haxe",
  startState: function(y) {
    return {
      tokenize: haxeTokenBase,
      reAllowed: true,
      kwAllowed: true,
      cc: [],
      lexical: new HaxeLexical(-y, 0, "block", false),
      importedtypes: [
        "Int",
        "Float",
        "String",
        "Void",
        "Std",
        "Bool",
        "Dynamic",
        "Array"
      ],
      context: null,
      indented: 0
    };
  },
  token: function(y, J) {
    if (y.sol() && (J.lexical.hasOwnProperty("align") || (J.lexical.align = false), J.indented = y.indentation()), y.eatSpace()) return null;
    var Y = J.tokenize(y, J);
    return type == "comment" ? Y : (J.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/)), J.kwAllowed = type != ".", parseHaxe(J, Y, type, content, y));
  },
  indent: function(y, J, Y) {
    if (y.tokenize != haxeTokenBase) return 0;
    var X = J && J.charAt(0), Z = y.lexical;
    Z.type == "stat" && X == "}" && (Z = Z.prev);
    var Q = Z.type, $ = X == Q;
    return Q == "vardef" ? Z.indented + 4 : Q == "form" && X == "{" ? Z.indented : Q == "stat" || Q == "form" ? Z.indented + Y.unit : Z.info == "switch" && !$ ? Z.indented + (/^(?:case|default)\b/.test(J) ? Y.unit : 2 * Y.unit) : Z.align ? Z.column + ($ ? 0 : 1) : Z.indented + ($ ? 0 : Y.unit);
  },
  languageData: {
    indentOnInput: /^\s*[{}]$/,
    commentTokens: {
      line: "//",
      block: {
        open: "/*",
        close: "*/"
      }
    }
  }
}, hxml = {
  name: "hxml",
  startState: function() {
    return {
      define: false,
      inString: false
    };
  },
  token: function(y, J) {
    var Y = y.peek(), X = y.sol();
    if (Y == "#") return y.skipToEnd(), "comment";
    if (X && Y == "-") {
      var Z = "variable-2";
      return y.eat(/-/), y.peek() == "-" && (y.eat(/-/), Z = "keyword a"), y.peek() == "D" && (y.eat(/[D]/), Z = "keyword c", J.define = true), y.eatWhile(/[A-Z]/i), Z;
    }
    var Y = y.peek();
    return J.inString == 0 && Y == "'" && (J.inString = true, y.next()), J.inString == 1 ? (y.skipTo("'") || y.skipToEnd(), y.peek() == "'" && (y.next(), J.inString = false), "string") : (y.next(), null);
  },
  languageData: { commentTokens: { line: "#" } }
};
export {
  hxml as n,
  haxe as t
};
