var typeWords = [
  "-type",
  "-spec",
  "-export_type",
  "-opaque"
], keywordWords = [
  "after",
  "begin",
  "catch",
  "case",
  "cond",
  "end",
  "fun",
  "if",
  "let",
  "of",
  "query",
  "receive",
  "try",
  "when"
], separatorRE = /[\->,;]/, separatorWords = [
  "->",
  ";",
  ","
], operatorAtomWords = [
  "and",
  "andalso",
  "band",
  "bnot",
  "bor",
  "bsl",
  "bsr",
  "bxor",
  "div",
  "not",
  "or",
  "orelse",
  "rem",
  "xor"
], operatorSymbolRE = /[\+\-\*\/<>=\|:!]/, operatorSymbolWords = [
  "=",
  "+",
  "-",
  "*",
  "/",
  ">",
  ">=",
  "<",
  "=<",
  "=:=",
  "==",
  "=/=",
  "/=",
  "||",
  "<-",
  "!"
], openParenRE = /[<\(\[\{]/, openParenWords = [
  "<<",
  "(",
  "[",
  "{"
], closeParenRE = /[>\)\]\}]/, closeParenWords = [
  "}",
  "]",
  ")",
  ">>"
], guardWords = /* @__PURE__ */ "is_atom.is_binary.is_bitstring.is_boolean.is_float.is_function.is_integer.is_list.is_number.is_pid.is_port.is_record.is_reference.is_tuple.atom.binary.bitstring.boolean.function.integer.list.number.pid.port.record.reference.tuple".split("."), bifWords = /* @__PURE__ */ "abs.adler32.adler32_combine.alive.apply.atom_to_binary.atom_to_list.binary_to_atom.binary_to_existing_atom.binary_to_list.binary_to_term.bit_size.bitstring_to_list.byte_size.check_process_code.contact_binary.crc32.crc32_combine.date.decode_packet.delete_module.disconnect_node.element.erase.exit.float.float_to_list.garbage_collect.get.get_keys.group_leader.halt.hd.integer_to_list.internal_bif.iolist_size.iolist_to_binary.is_alive.is_atom.is_binary.is_bitstring.is_boolean.is_float.is_function.is_integer.is_list.is_number.is_pid.is_port.is_process_alive.is_record.is_reference.is_tuple.length.link.list_to_atom.list_to_binary.list_to_bitstring.list_to_existing_atom.list_to_float.list_to_integer.list_to_pid.list_to_tuple.load_module.make_ref.module_loaded.monitor_node.node.node_link.node_unlink.nodes.notalive.now.open_port.pid_to_list.port_close.port_command.port_connect.port_control.pre_loaded.process_flag.process_info.processes.purge_module.put.register.registered.round.self.setelement.size.spawn.spawn_link.spawn_monitor.spawn_opt.split_binary.statistics.term_to_binary.time.throw.tl.trunc.tuple_size.tuple_to_list.unlink.unregister.whereis".split("."), anumRE = /[\w@Ø-ÞÀ-Öß-öø-ÿ]/, escapesRE = /[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/;
function tokenizer(I, L) {
  if (L.in_string) return L.in_string = !doubleQuote(I), rval(L, I, "string");
  if (L.in_atom) return L.in_atom = !singleQuote(I), rval(L, I, "atom");
  if (I.eatSpace()) return rval(L, I, "whitespace");
  if (!peekToken(L) && I.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/)) return is_member(I.current(), typeWords) ? rval(L, I, "type") : rval(L, I, "attribute");
  var R = I.next();
  if (R == "%") return I.skipToEnd(), rval(L, I, "comment");
  if (R == ":") return rval(L, I, "colon");
  if (R == "?") return I.eatSpace(), I.eatWhile(anumRE), rval(L, I, "macro");
  if (R == "#") return I.eatSpace(), I.eatWhile(anumRE), rval(L, I, "record");
  if (R == "$") return I.next() == "\\" && !I.match(escapesRE) ? rval(L, I, "error") : rval(L, I, "number");
  if (R == ".") return rval(L, I, "dot");
  if (R == "'") {
    if (!(L.in_atom = !singleQuote(I))) {
      if (I.match(/\s*\/\s*[0-9]/, false)) return I.match(/\s*\/\s*[0-9]/, true), rval(L, I, "fun");
      if (I.match(/\s*\(/, false) || I.match(/\s*:/, false)) return rval(L, I, "function");
    }
    return rval(L, I, "atom");
  }
  if (R == '"') return L.in_string = !doubleQuote(I), rval(L, I, "string");
  if (/[A-Z_Ø-ÞÀ-Ö]/.test(R)) return I.eatWhile(anumRE), rval(L, I, "variable");
  if (/[a-z_ß-öø-ÿ]/.test(R)) {
    if (I.eatWhile(anumRE), I.match(/\s*\/\s*[0-9]/, false)) return I.match(/\s*\/\s*[0-9]/, true), rval(L, I, "fun");
    var z = I.current();
    return is_member(z, keywordWords) ? rval(L, I, "keyword") : is_member(z, operatorAtomWords) ? rval(L, I, "operator") : I.match(/\s*\(/, false) ? is_member(z, bifWords) && (peekToken(L).token != ":" || peekToken(L, 2).token == "erlang") ? rval(L, I, "builtin") : is_member(z, guardWords) ? rval(L, I, "guard") : rval(L, I, "function") : lookahead(I) == ":" ? z == "erlang" ? rval(L, I, "builtin") : rval(L, I, "function") : is_member(z, ["true", "false"]) ? rval(L, I, "boolean") : rval(L, I, "atom");
  }
  var B = /[0-9]/;
  return B.test(R) ? (I.eatWhile(B), I.eat("#") ? I.eatWhile(/[0-9a-zA-Z]/) || I.backUp(1) : I.eat(".") && (I.eatWhile(B) ? I.eat(/[eE]/) && (I.eat(/[-+]/) ? I.eatWhile(B) || I.backUp(2) : I.eatWhile(B) || I.backUp(1)) : I.backUp(1)), rval(L, I, "number")) : nongreedy(I, openParenRE, openParenWords) ? rval(L, I, "open_paren") : nongreedy(I, closeParenRE, closeParenWords) ? rval(L, I, "close_paren") : greedy(I, separatorRE, separatorWords) ? rval(L, I, "separator") : greedy(I, operatorSymbolRE, operatorSymbolWords) ? rval(L, I, "operator") : rval(L, I, null);
}
function nongreedy(l, A, j) {
  if (l.current().length == 1 && A.test(l.current())) {
    for (l.backUp(1); A.test(l.peek()); ) if (l.next(), is_member(l.current(), j)) return true;
    l.backUp(l.current().length - 1);
  }
  return false;
}
function greedy(l, A, j) {
  if (l.current().length == 1 && A.test(l.current())) {
    for (; A.test(l.peek()); ) l.next();
    for (; 0 < l.current().length; ) if (is_member(l.current(), j)) return true;
    else l.backUp(1);
    l.next();
  }
  return false;
}
function doubleQuote(l) {
  return quote(l, '"', "\\");
}
function singleQuote(l) {
  return quote(l, "'", "\\");
}
function quote(l, A, j) {
  for (; !l.eol(); ) {
    var M = l.next();
    if (M == A) return true;
    M == j && l.next();
  }
  return false;
}
function lookahead(l) {
  var A = l.match(/^\s*([^\s%])/, false);
  return A ? A[1] : "";
}
function is_member(l, A) {
  return -1 < A.indexOf(l);
}
function rval(l, A, j) {
  switch (pushToken(l, realToken(j, A)), j) {
    case "atom":
      return "atom";
    case "attribute":
      return "attribute";
    case "boolean":
      return "atom";
    case "builtin":
      return "builtin";
    case "close_paren":
      return null;
    case "colon":
      return null;
    case "comment":
      return "comment";
    case "dot":
      return null;
    case "error":
      return "error";
    case "fun":
      return "meta";
    case "function":
      return "tag";
    case "guard":
      return "property";
    case "keyword":
      return "keyword";
    case "macro":
      return "macroName";
    case "number":
      return "number";
    case "open_paren":
      return null;
    case "operator":
      return "operator";
    case "record":
      return "bracket";
    case "separator":
      return null;
    case "string":
      return "string";
    case "type":
      return "def";
    case "variable":
      return "variable";
    default:
      return null;
  }
}
function aToken(l, A, j, M) {
  return {
    token: l,
    column: A,
    indent: j,
    type: M
  };
}
function realToken(l, A) {
  return aToken(A.current(), A.column(), A.indentation(), l);
}
function fakeToken(l) {
  return aToken(l, 0, 0, l);
}
function peekToken(l, A) {
  var j = l.tokenStack.length, M = A || 1;
  return j < M ? false : l.tokenStack[j - M];
}
function pushToken(l, A) {
  A.type == "comment" || A.type == "whitespace" || (l.tokenStack = maybe_drop_pre(l.tokenStack, A), l.tokenStack = maybe_drop_post(l.tokenStack));
}
function maybe_drop_pre(l, A) {
  var j = l.length - 1;
  return 0 < j && l[j].type === "record" && A.type === "dot" ? l.pop() : (0 < j && l[j].type === "group" && l.pop(), l.push(A)), l;
}
function maybe_drop_post(l) {
  if (!l.length) return l;
  var A = l.length - 1;
  if (l[A].type === "dot") return [];
  if (A > 1 && l[A].type === "fun" && l[A - 1].token === "fun") return l.slice(0, A - 1);
  switch (l[A].token) {
    case "}":
      return d(l, { g: ["{"] });
    case "]":
      return d(l, { i: ["["] });
    case ")":
      return d(l, { i: ["("] });
    case ">>":
      return d(l, { i: ["<<"] });
    case "end":
      return d(l, { i: [
        "begin",
        "case",
        "fun",
        "if",
        "receive",
        "try"
      ] });
    case ",":
      return d(l, { e: [
        "begin",
        "try",
        "when",
        "->",
        ",",
        "(",
        "[",
        "{",
        "<<"
      ] });
    case "->":
      return d(l, {
        r: ["when"],
        m: [
          "try",
          "if",
          "case",
          "receive"
        ]
      });
    case ";":
      return d(l, { E: [
        "case",
        "fun",
        "if",
        "receive",
        "try",
        "when"
      ] });
    case "catch":
      return d(l, { e: ["try"] });
    case "of":
      return d(l, { e: ["case"] });
    case "after":
      return d(l, { e: ["receive", "try"] });
    default:
      return l;
  }
}
function d(l, A) {
  for (var j in A) for (var M = l.length - 1, N = A[j], P = M - 1; -1 < P; P--) if (is_member(l[P].token, N)) {
    var F = l.slice(0, P);
    switch (j) {
      case "m":
        return F.concat(l[P]).concat(l[M]);
      case "r":
        return F.concat(l[M]);
      case "i":
        return F;
      case "g":
        return F.concat(fakeToken("group"));
      case "E":
        return F.concat(l[P]);
      case "e":
        return F.concat(l[P]);
    }
  }
  return j == "E" ? [] : l;
}
function indenter(l, A, j) {
  var M, N = wordafter(A), P = peekToken(l, 1), F = peekToken(l, 2);
  return l.in_string || l.in_atom ? null : F ? P.token == "when" ? P.column + j.unit : N === "when" && F.type === "function" ? F.indent + j.unit : N === "(" && P.token === "fun" ? P.column + 3 : N === "catch" && (M = getToken(l, ["try"])) ? M.column : is_member(N, [
    "end",
    "after",
    "of"
  ]) ? (M = getToken(l, [
    "begin",
    "case",
    "fun",
    "if",
    "receive",
    "try"
  ]), M ? M.column : null) : is_member(N, closeParenWords) ? (M = getToken(l, openParenWords), M ? M.column : null) : is_member(P.token, [
    ",",
    "|",
    "||"
  ]) || is_member(N, [
    ",",
    "|",
    "||"
  ]) ? (M = postcommaToken(l), M ? M.column + M.token.length : j.unit) : P.token == "->" ? is_member(F.token, [
    "receive",
    "case",
    "if",
    "try"
  ]) ? F.column + j.unit + j.unit : F.column + j.unit : is_member(P.token, openParenWords) ? P.column + P.token.length : (M = defaultToken(l), truthy(M) ? M.column + j.unit : 0) : 0;
}
function wordafter(l) {
  var A = l.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/);
  return truthy(A) && A.index === 0 ? A[0] : "";
}
function postcommaToken(l) {
  var A = l.tokenStack.slice(0, -1), j = getTokenIndex(A, "type", ["open_paren"]);
  return truthy(A[j]) ? A[j] : false;
}
function defaultToken(l) {
  var A = l.tokenStack, j = getTokenIndex(A, "type", [
    "open_paren",
    "separator",
    "keyword"
  ]), M = getTokenIndex(A, "type", ["operator"]);
  return truthy(j) && truthy(M) && j < M ? A[j + 1] : truthy(j) ? A[j] : false;
}
function getToken(l, A) {
  var j = l.tokenStack, M = getTokenIndex(j, "token", A);
  return truthy(j[M]) ? j[M] : false;
}
function getTokenIndex(l, A, j) {
  for (var M = l.length - 1; -1 < M; M--) if (is_member(l[M][A], j)) return M;
  return false;
}
function truthy(l) {
  return l !== false && l != null;
}
const erlang = {
  name: "erlang",
  startState() {
    return {
      tokenStack: [],
      in_string: false,
      in_atom: false
    };
  },
  token: tokenizer,
  indent: indenter,
  languageData: { commentTokens: { line: "%" } }
};
export {
  erlang as t
};
