function wordRegexp(e) {
  return /* @__PURE__ */ RegExp("^((" + e.join(")|(") + "))\\b");
}
var singleOperators = /[\^@!\|<>#~\.\*\-\+\\/,=]/, doubleOperators = /(<-)|(:=)|(=<)|(>=)|(<=)|(<:)|(>:)|(=:)|(\\=)|(\\=:)|(!!)|(==)|(::)/, tripleOperators = /(:::)|(\.\.\.)|(=<:)|(>=:)/, middle = [
  "in",
  "then",
  "else",
  "of",
  "elseof",
  "elsecase",
  "elseif",
  "catch",
  "finally",
  "with",
  "require",
  "prepare",
  "import",
  "export",
  "define",
  "do"
], end = ["end"], atoms = wordRegexp([
  "true",
  "false",
  "nil",
  "unit"
]), commonKeywords = wordRegexp([
  "andthen",
  "at",
  "attr",
  "declare",
  "feat",
  "from",
  "lex",
  "mod",
  "div",
  "mode",
  "orelse",
  "parser",
  "prod",
  "prop",
  "scanner",
  "self",
  "syn",
  "token"
]), openingKeywords = wordRegexp([
  "local",
  "proc",
  "fun",
  "case",
  "class",
  "if",
  "cond",
  "or",
  "dis",
  "choice",
  "not",
  "thread",
  "try",
  "raise",
  "lock",
  "for",
  "suchthat",
  "meth",
  "functor"
]), middleKeywords = wordRegexp(middle), endKeywords = wordRegexp(end);
function tokenBase(e, g) {
  if (e.eatSpace()) return null;
  if (e.match(/[{}]/)) return "bracket";
  if (e.match("[]")) return "keyword";
  if (e.match(tripleOperators) || e.match(doubleOperators)) return "operator";
  if (e.match(atoms)) return "atom";
  var _ = e.match(openingKeywords);
  if (_) return g.doInCurrentLine ? g.doInCurrentLine = false : g.currentIndent++, _[0] == "proc" || _[0] == "fun" ? g.tokenize = tokenFunProc : _[0] == "class" ? g.tokenize = tokenClass : _[0] == "meth" && (g.tokenize = tokenMeth), "keyword";
  if (e.match(middleKeywords) || e.match(commonKeywords)) return "keyword";
  if (e.match(endKeywords)) return g.currentIndent--, "keyword";
  var v = e.next();
  if (v == '"' || v == "'") return g.tokenize = tokenString(v), g.tokenize(e, g);
  if (/[~\d]/.test(v)) {
    if (v == "~") if (/^[0-9]/.test(e.peek())) {
      if (e.next() == "0" && e.match(/^[xX][0-9a-fA-F]+/) || e.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/)) return "number";
    } else return null;
    return v == "0" && e.match(/^[xX][0-9a-fA-F]+/) || e.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/) ? "number" : null;
  }
  return v == "%" ? (e.skipToEnd(), "comment") : v == "/" && e.eat("*") ? (g.tokenize = tokenComment, tokenComment(e, g)) : singleOperators.test(v) ? "operator" : (e.eatWhile(/\w/), "variable");
}
function tokenClass(e, p) {
  return e.eatSpace() ? null : (e.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)/), p.tokenize = tokenBase, "type");
}
function tokenMeth(e, p) {
  return e.eatSpace() ? null : (e.match(/([a-zA-Z][A-Za-z0-9_]*)|(`.+`)/), p.tokenize = tokenBase, "def");
}
function tokenFunProc(e, p) {
  return e.eatSpace() ? null : !p.hasPassedFirstStage && e.eat("{") ? (p.hasPassedFirstStage = true, "bracket") : p.hasPassedFirstStage ? (e.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)|\$/), p.hasPassedFirstStage = false, p.tokenize = tokenBase, "def") : (p.tokenize = tokenBase, null);
}
function tokenComment(e, p) {
  for (var m = false, h; h = e.next(); ) {
    if (h == "/" && m) {
      p.tokenize = tokenBase;
      break;
    }
    m = h == "*";
  }
  return "comment";
}
function tokenString(e) {
  return function(p, m) {
    for (var h = false, g, _ = false; (g = p.next()) != null; ) {
      if (g == e && !h) {
        _ = true;
        break;
      }
      h = !h && g == "\\";
    }
    return (_ || !h) && (m.tokenize = tokenBase), "string";
  };
}
function buildElectricInputRegEx() {
  var e = middle.concat(end);
  return /* @__PURE__ */ RegExp("[\\[\\]]|(" + e.join("|") + ")$");
}
const oz = {
  name: "oz",
  startState: function() {
    return {
      tokenize: tokenBase,
      currentIndent: 0,
      doInCurrentLine: false,
      hasPassedFirstStage: false
    };
  },
  token: function(e, p) {
    return e.sol() && (p.doInCurrentLine = 0), p.tokenize(e, p);
  },
  indent: function(e, p, m) {
    var h = p.replace(/^\s+|\s+$/g, "");
    return h.match(endKeywords) || h.match(middleKeywords) || h.match(/(\[])/) ? m.unit * (e.currentIndent - 1) : e.currentIndent < 0 ? 0 : e.currentIndent * m.unit;
  },
  languageData: {
    indentOnInut: buildElectricInputRegEx(),
    commentTokens: {
      line: "%",
      block: {
        open: "/*",
        close: "*/"
      }
    }
  }
};
export {
  oz as t
};
