diff .cms/lib/codemirror/mode/oz/oz.js @ 0:78edf6b517a0 draft

24.10
author Coffee CMS <info@coffee-cms.ru>
date Fri, 11 Oct 2024 22:40:23 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.cms/lib/codemirror/mode/oz/oz.js	Fri Oct 11 22:40:23 2024 +0000
@@ -0,0 +1,252 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
+CodeMirror.defineMode("oz", function (conf) {
+
+  function wordRegexp(words) {
+    return new RegExp("^((" + words.join(")|(") + "))\\b");
+  }
+
+  var singleOperators = /[\^@!\|<>#~\.\*\-\+\\/,=]/;
+  var doubleOperators = /(<-)|(:=)|(=<)|(>=)|(<=)|(<:)|(>:)|(=:)|(\\=)|(\\=:)|(!!)|(==)|(::)/;
+  var tripleOperators = /(:::)|(\.\.\.)|(=<:)|(>=:)/;
+
+  var middle = ["in", "then", "else", "of", "elseof", "elsecase", "elseif", "catch",
+    "finally", "with", "require", "prepare", "import", "export", "define", "do"];
+  var end = ["end"];
+
+  var atoms = wordRegexp(["true", "false", "nil", "unit"]);
+  var commonKeywords = wordRegexp(["andthen", "at", "attr", "declare", "feat", "from", "lex",
+    "mod", "div", "mode", "orelse", "parser", "prod", "prop", "scanner", "self", "syn", "token"]);
+  var openingKeywords = wordRegexp(["local", "proc", "fun", "case", "class", "if", "cond", "or", "dis",
+    "choice", "not", "thread", "try", "raise", "lock", "for", "suchthat", "meth", "functor"]);
+  var middleKeywords = wordRegexp(middle);
+  var endKeywords = wordRegexp(end);
+
+  // Tokenizers
+  function tokenBase(stream, state) {
+    if (stream.eatSpace()) {
+      return null;
+    }
+
+    // Brackets
+    if(stream.match(/[{}]/)) {
+      return "bracket";
+    }
+
+    // Special [] keyword
+    if (stream.match('[]')) {
+        return "keyword"
+    }
+
+    // Operators
+    if (stream.match(tripleOperators) || stream.match(doubleOperators)) {
+      return "operator";
+    }
+
+    // Atoms
+    if(stream.match(atoms)) {
+      return 'atom';
+    }
+
+    // Opening keywords
+    var matched = stream.match(openingKeywords);
+    if (matched) {
+      if (!state.doInCurrentLine)
+        state.currentIndent++;
+      else
+        state.doInCurrentLine = false;
+
+      // Special matching for signatures
+      if(matched[0] == "proc" || matched[0] == "fun")
+        state.tokenize = tokenFunProc;
+      else if(matched[0] == "class")
+        state.tokenize = tokenClass;
+      else if(matched[0] == "meth")
+        state.tokenize = tokenMeth;
+
+      return 'keyword';
+    }
+
+    // Middle and other keywords
+    if (stream.match(middleKeywords) || stream.match(commonKeywords)) {
+      return "keyword"
+    }
+
+    // End keywords
+    if (stream.match(endKeywords)) {
+      state.currentIndent--;
+      return 'keyword';
+    }
+
+    // Eat the next char for next comparisons
+    var ch = stream.next();
+
+    // Strings
+    if (ch == '"' || ch == "'") {
+      state.tokenize = tokenString(ch);
+      return state.tokenize(stream, state);
+    }
+
+    // Numbers
+    if (/[~\d]/.test(ch)) {
+      if (ch == "~") {
+        if(! /^[0-9]/.test(stream.peek()))
+          return null;
+        else if (( stream.next() == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/))
+          return "number";
+      }
+
+      if ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/))
+        return "number";
+
+      return null;
+    }
+
+    // Comments
+    if (ch == "%") {
+      stream.skipToEnd();
+      return 'comment';
+    }
+    else if (ch == "/") {
+      if (stream.eat("*")) {
+        state.tokenize = tokenComment;
+        return tokenComment(stream, state);
+      }
+    }
+
+    // Single operators
+    if(singleOperators.test(ch)) {
+      return "operator";
+    }
+
+    // If nothing match, we skip the entire alphanumeric block
+    stream.eatWhile(/\w/);
+
+    return "variable";
+  }
+
+  function tokenClass(stream, state) {
+    if (stream.eatSpace()) {
+      return null;
+    }
+    stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)/);
+    state.tokenize = tokenBase;
+    return "variable-3"
+  }
+
+  function tokenMeth(stream, state) {
+    if (stream.eatSpace()) {
+      return null;
+    }
+    stream.match(/([a-zA-Z][A-Za-z0-9_]*)|(`.+`)/);
+    state.tokenize = tokenBase;
+    return "def"
+  }
+
+  function tokenFunProc(stream, state) {
+    if (stream.eatSpace()) {
+      return null;
+    }
+
+    if(!state.hasPassedFirstStage && stream.eat("{")) {
+      state.hasPassedFirstStage = true;
+      return "bracket";
+    }
+    else if(state.hasPassedFirstStage) {
+      stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)|\$/);
+      state.hasPassedFirstStage = false;
+      state.tokenize = tokenBase;
+      return "def"
+    }
+    else {
+      state.tokenize = tokenBase;
+      return null;
+    }
+  }
+
+  function tokenComment(stream, state) {
+    var maybeEnd = false, ch;
+    while (ch = stream.next()) {
+      if (ch == "/" && maybeEnd) {
+        state.tokenize = tokenBase;
+        break;
+      }
+      maybeEnd = (ch == "*");
+    }
+    return "comment";
+  }
+
+  function tokenString(quote) {
+    return function (stream, state) {
+      var escaped = false, next, end = false;
+      while ((next = stream.next()) != null) {
+        if (next == quote && !escaped) {
+          end = true;
+          break;
+        }
+        escaped = !escaped && next == "\\";
+      }
+      if (end || !escaped)
+        state.tokenize = tokenBase;
+      return "string";
+    };
+  }
+
+  function buildElectricInputRegEx() {
+    // Reindentation should occur on [] or on a match of any of
+    // the block closing keywords, at the end of a line.
+    var allClosings = middle.concat(end);
+    return new RegExp("[\\[\\]]|(" + allClosings.join("|") + ")$");
+  }
+
+  return {
+
+    startState: function () {
+      return {
+        tokenize: tokenBase,
+        currentIndent: 0,
+        doInCurrentLine: false,
+        hasPassedFirstStage: false
+      };
+    },
+
+    token: function (stream, state) {
+      if (stream.sol())
+        state.doInCurrentLine = 0;
+
+      return state.tokenize(stream, state);
+    },
+
+    indent: function (state, textAfter) {
+      var trueText = textAfter.replace(/^\s+|\s+$/g, '');
+
+      if (trueText.match(endKeywords) || trueText.match(middleKeywords) || trueText.match(/(\[])/))
+        return conf.indentUnit * (state.currentIndent - 1);
+
+      if (state.currentIndent < 0)
+        return 0;
+
+      return state.currentIndent * conf.indentUnit;
+    },
+    fold: "indent",
+    electricInput: buildElectricInputRegEx(),
+    lineComment: "%",
+    blockCommentStart: "/*",
+    blockCommentEnd: "*/"
+  };
+});
+
+CodeMirror.defineMIME("text/x-oz", "oz");
+
+});