diff .cms/lib/codemirror/mode/yacas/yacas.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/yacas/yacas.js	Fri Oct 11 22:40:23 2024 +0000
@@ -0,0 +1,204 @@
+// CodeMirror, copyright (c) by Marijn Haverbeke and others
+// Distributed under an MIT license: https://codemirror.net/5/LICENSE
+
+// Yacas mode copyright (c) 2015 by Grzegorz Mazur
+// Loosely based on mathematica mode by Calin Barbat
+
+(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('yacas', function(_config, _parserConfig) {
+
+  function words(str) {
+    var obj = {}, words = str.split(" ");
+    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
+    return obj;
+  }
+
+  var bodiedOps = words("Assert BackQuote D Defun Deriv For ForEach FromFile " +
+                        "FromString Function Integrate InverseTaylor Limit " +
+                        "LocalSymbols Macro MacroRule MacroRulePattern " +
+                        "NIntegrate Rule RulePattern Subst TD TExplicitSum " +
+                        "TSum Taylor Taylor1 Taylor2 Taylor3 ToFile " +
+                        "ToStdout ToString TraceRule Until While");
+
+  // patterns
+  var pFloatForm  = "(?:(?:\\.\\d+|\\d+\\.\\d*|\\d+)(?:[eE][+-]?\\d+)?)";
+  var pIdentifier = "(?:[a-zA-Z\\$'][a-zA-Z0-9\\$']*)";
+
+  // regular expressions
+  var reFloatForm    = new RegExp(pFloatForm);
+  var reIdentifier   = new RegExp(pIdentifier);
+  var rePattern      = new RegExp(pIdentifier + "?_" + pIdentifier);
+  var reFunctionLike = new RegExp(pIdentifier + "\\s*\\(");
+
+  function tokenBase(stream, state) {
+    var ch;
+
+    // get next character
+    ch = stream.next();
+
+    // string
+    if (ch === '"') {
+      state.tokenize = tokenString;
+      return state.tokenize(stream, state);
+    }
+
+    // comment
+    if (ch === '/') {
+      if (stream.eat('*')) {
+        state.tokenize = tokenComment;
+        return state.tokenize(stream, state);
+      }
+      if (stream.eat("/")) {
+        stream.skipToEnd();
+        return "comment";
+      }
+    }
+
+    // go back one character
+    stream.backUp(1);
+
+    // update scope info
+    var m = stream.match(/^(\w+)\s*\(/, false);
+    if (m !== null && bodiedOps.hasOwnProperty(m[1]))
+      state.scopes.push('bodied');
+
+    var scope = currentScope(state);
+
+    if (scope === 'bodied' && ch === '[')
+      state.scopes.pop();
+
+    if (ch === '[' || ch === '{' || ch === '(')
+      state.scopes.push(ch);
+
+    scope = currentScope(state);
+
+    if (scope === '[' && ch === ']' ||
+        scope === '{' && ch === '}' ||
+        scope === '(' && ch === ')')
+      state.scopes.pop();
+
+    if (ch === ';') {
+      while (scope === 'bodied') {
+        state.scopes.pop();
+        scope = currentScope(state);
+      }
+    }
+
+    // look for ordered rules
+    if (stream.match(/\d+ *#/, true, false)) {
+      return 'qualifier';
+    }
+
+    // look for numbers
+    if (stream.match(reFloatForm, true, false)) {
+      return 'number';
+    }
+
+    // look for placeholders
+    if (stream.match(rePattern, true, false)) {
+      return 'variable-3';
+    }
+
+    // match all braces separately
+    if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) {
+      return 'bracket';
+    }
+
+    // literals looking like function calls
+    if (stream.match(reFunctionLike, true, false)) {
+      stream.backUp(1);
+      return 'variable';
+    }
+
+    // all other identifiers
+    if (stream.match(reIdentifier, true, false)) {
+      return 'variable-2';
+    }
+
+    // operators; note that operators like @@ or /; are matched separately for each symbol.
+    if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%|#)/, true, false)) {
+      return 'operator';
+    }
+
+    // everything else is an error
+    return 'error';
+  }
+
+  function tokenString(stream, state) {
+    var next, end = false, escaped = false;
+    while ((next = stream.next()) != null) {
+      if (next === '"' && !escaped) {
+        end = true;
+        break;
+      }
+      escaped = !escaped && next === '\\';
+    }
+    if (end && !escaped) {
+      state.tokenize = tokenBase;
+    }
+    return 'string';
+  };
+
+  function tokenComment(stream, state) {
+    var prev, next;
+    while((next = stream.next()) != null) {
+      if (prev === '*' && next === '/') {
+        state.tokenize = tokenBase;
+        break;
+      }
+      prev = next;
+    }
+    return 'comment';
+  }
+
+  function currentScope(state) {
+    var scope = null;
+    if (state.scopes.length > 0)
+      scope = state.scopes[state.scopes.length - 1];
+    return scope;
+  }
+
+  return {
+    startState: function() {
+      return {
+        tokenize: tokenBase,
+        scopes: []
+      };
+    },
+    token: function(stream, state) {
+      if (stream.eatSpace()) return null;
+      return state.tokenize(stream, state);
+    },
+    indent: function(state, textAfter) {
+      if (state.tokenize !== tokenBase && state.tokenize !== null)
+        return CodeMirror.Pass;
+
+      var delta = 0;
+      if (textAfter === ']' || textAfter === '];' ||
+          textAfter === '}' || textAfter === '};' ||
+          textAfter === ');')
+        delta = -1;
+
+      return (state.scopes.length + delta) * _config.indentUnit;
+    },
+    electricChars: "{}[]();",
+    blockCommentStart: "/*",
+    blockCommentEnd: "*/",
+    lineComment: "//"
+  };
+});
+
+CodeMirror.defineMIME('text/x-yacas', {
+  name: 'yacas'
+});
+
+});