all repos — NoPaste @ 3e3c433f026c49e04d0efa0f0f39fc688ed32bb1

Resurrected - The PussTheCat.org fork of NoPaste

scripts/CodeMirror/mode/modelica/modelica.js (view raw)

  1// CodeMirror, copyright (c) by Marijn Haverbeke and others
  2// Distributed under an MIT license: https://codemirror.net/LICENSE
  3
  4// Modelica support for CodeMirror, copyright (c) by Lennart Ochel
  5
  6(function(mod) {
  7  if (typeof exports == "object" && typeof module == "object") // CommonJS
  8    mod(require("../../lib/codemirror"));
  9  else if (typeof define == "function" && define.amd) // AMD
 10    define(["../../lib/codemirror"], mod);
 11  else // Plain browser env
 12    mod(CodeMirror);
 13})
 14
 15(function(CodeMirror) {
 16  "use strict";
 17
 18  CodeMirror.defineMode("modelica", function(config, parserConfig) {
 19
 20    var indentUnit = config.indentUnit;
 21    var keywords = parserConfig.keywords || {};
 22    var builtin = parserConfig.builtin || {};
 23    var atoms = parserConfig.atoms || {};
 24
 25    var isSingleOperatorChar = /[;=\(:\),{}.*<>+\-\/^\[\]]/;
 26    var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\.\+|\.\-|\.\*|\.\/|\.\^)/;
 27    var isDigit = /[0-9]/;
 28    var isNonDigit = /[_a-zA-Z]/;
 29
 30    function tokenLineComment(stream, state) {
 31      stream.skipToEnd();
 32      state.tokenize = null;
 33      return "comment";
 34    }
 35
 36    function tokenBlockComment(stream, state) {
 37      var maybeEnd = false, ch;
 38      while (ch = stream.next()) {
 39        if (maybeEnd && ch == "/") {
 40          state.tokenize = null;
 41          break;
 42        }
 43        maybeEnd = (ch == "*");
 44      }
 45      return "comment";
 46    }
 47
 48    function tokenString(stream, state) {
 49      var escaped = false, ch;
 50      while ((ch = stream.next()) != null) {
 51        if (ch == '"' && !escaped) {
 52          state.tokenize = null;
 53          state.sol = false;
 54          break;
 55        }
 56        escaped = !escaped && ch == "\\";
 57      }
 58
 59      return "string";
 60    }
 61
 62    function tokenIdent(stream, state) {
 63      stream.eatWhile(isDigit);
 64      while (stream.eat(isDigit) || stream.eat(isNonDigit)) { }
 65
 66
 67      var cur = stream.current();
 68
 69      if(state.sol && (cur == "package" || cur == "model" || cur == "when" || cur == "connector")) state.level++;
 70      else if(state.sol && cur == "end" && state.level > 0) state.level--;
 71
 72      state.tokenize = null;
 73      state.sol = false;
 74
 75      if (keywords.propertyIsEnumerable(cur)) return "keyword";
 76      else if (builtin.propertyIsEnumerable(cur)) return "builtin";
 77      else if (atoms.propertyIsEnumerable(cur)) return "atom";
 78      else return "variable";
 79    }
 80
 81    function tokenQIdent(stream, state) {
 82      while (stream.eat(/[^']/)) { }
 83
 84      state.tokenize = null;
 85      state.sol = false;
 86
 87      if(stream.eat("'"))
 88        return "variable";
 89      else
 90        return "error";
 91    }
 92
 93    function tokenUnsignedNuber(stream, state) {
 94      stream.eatWhile(isDigit);
 95      if (stream.eat('.')) {
 96        stream.eatWhile(isDigit);
 97      }
 98      if (stream.eat('e') || stream.eat('E')) {
 99        if (!stream.eat('-'))
100          stream.eat('+');
101        stream.eatWhile(isDigit);
102      }
103
104      state.tokenize = null;
105      state.sol = false;
106      return "number";
107    }
108
109    // Interface
110    return {
111      startState: function() {
112        return {
113          tokenize: null,
114          level: 0,
115          sol: true
116        };
117      },
118
119      token: function(stream, state) {
120        if(state.tokenize != null) {
121          return state.tokenize(stream, state);
122        }
123
124        if(stream.sol()) {
125          state.sol = true;
126        }
127
128        // WHITESPACE
129        if(stream.eatSpace()) {
130          state.tokenize = null;
131          return null;
132        }
133
134        var ch = stream.next();
135
136        // LINECOMMENT
137        if(ch == '/' && stream.eat('/')) {
138          state.tokenize = tokenLineComment;
139        }
140        // BLOCKCOMMENT
141        else if(ch == '/' && stream.eat('*')) {
142          state.tokenize = tokenBlockComment;
143        }
144        // TWO SYMBOL TOKENS
145        else if(isDoubleOperatorChar.test(ch+stream.peek())) {
146          stream.next();
147          state.tokenize = null;
148          return "operator";
149        }
150        // SINGLE SYMBOL TOKENS
151        else if(isSingleOperatorChar.test(ch)) {
152          state.tokenize = null;
153          return "operator";
154        }
155        // IDENT
156        else if(isNonDigit.test(ch)) {
157          state.tokenize = tokenIdent;
158        }
159        // Q-IDENT
160        else if(ch == "'" && stream.peek() && stream.peek() != "'") {
161          state.tokenize = tokenQIdent;
162        }
163        // STRING
164        else if(ch == '"') {
165          state.tokenize = tokenString;
166        }
167        // UNSIGNED_NUBER
168        else if(isDigit.test(ch)) {
169          state.tokenize = tokenUnsignedNuber;
170        }
171        // ERROR
172        else {
173          state.tokenize = null;
174          return "error";
175        }
176
177        return state.tokenize(stream, state);
178      },
179
180      indent: function(state, textAfter) {
181        if (state.tokenize != null) return CodeMirror.Pass;
182
183        var level = state.level;
184        if(/(algorithm)/.test(textAfter)) level--;
185        if(/(equation)/.test(textAfter)) level--;
186        if(/(initial algorithm)/.test(textAfter)) level--;
187        if(/(initial equation)/.test(textAfter)) level--;
188        if(/(end)/.test(textAfter)) level--;
189
190        if(level > 0)
191          return indentUnit*level;
192        else
193          return 0;
194      },
195
196      blockCommentStart: "/*",
197      blockCommentEnd: "*/",
198      lineComment: "//"
199    };
200  });
201
202  function words(str) {
203    var obj = {}, words = str.split(" ");
204    for (var i=0; i<words.length; ++i)
205      obj[words[i]] = true;
206    return obj;
207  }
208
209  var modelicaKeywords = "algorithm and annotation assert block break class connect connector constant constrainedby der discrete each else elseif elsewhen encapsulated end enumeration equation expandable extends external false final flow for function if import impure in initial inner input loop model not operator or outer output package parameter partial protected public pure record redeclare replaceable return stream then true type when while within";
210  var modelicaBuiltin = "abs acos actualStream asin atan atan2 cardinality ceil cos cosh delay div edge exp floor getInstanceName homotopy inStream integer log log10 mod pre reinit rem semiLinear sign sin sinh spatialDistribution sqrt tan tanh";
211  var modelicaAtoms = "Real Boolean Integer String";
212
213  function def(mimes, mode) {
214    if (typeof mimes == "string")
215      mimes = [mimes];
216
217    var words = [];
218
219    function add(obj) {
220      if (obj)
221        for (var prop in obj)
222          if (obj.hasOwnProperty(prop))
223            words.push(prop);
224    }
225
226    add(mode.keywords);
227    add(mode.builtin);
228    add(mode.atoms);
229
230    if (words.length) {
231      mode.helperType = mimes[0];
232      CodeMirror.registerHelper("hintWords", mimes[0], words);
233    }
234
235    for (var i=0; i<mimes.length; ++i)
236      CodeMirror.defineMIME(mimes[i], mode);
237  }
238
239  def(["text/x-modelica"], {
240    name: "modelica",
241    keywords: words(modelicaKeywords),
242    builtin: words(modelicaBuiltin),
243    atoms: words(modelicaAtoms)
244  });
245});