GPQAPP

Форк
0
204 строки · 5.3 Кб
1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: https://codemirror.net/LICENSE
3

4
// Yacas mode copyright (c) 2015 by Grzegorz Mazur
5
// Loosely based on mathematica mode by Calin Barbat
6

7
(function(mod) {
8
  if (typeof exports == "object" && typeof module == "object") // CommonJS
9
    mod(require("../../lib/codemirror"));
10
  else if (typeof define == "function" && define.amd) // AMD
11
    define(["../../lib/codemirror"], mod);
12
  else // Plain browser env
13
    mod(CodeMirror);
14
})(function(CodeMirror) {
15
"use strict";
16

17
CodeMirror.defineMode('yacas', function(_config, _parserConfig) {
18

19
  function words(str) {
20
    var obj = {}, words = str.split(" ");
21
    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
22
    return obj;
23
  }
24

25
  var bodiedOps = words("Assert BackQuote D Defun Deriv For ForEach FromFile " +
26
                        "FromString Function Integrate InverseTaylor Limit " +
27
                        "LocalSymbols Macro MacroRule MacroRulePattern " +
28
                        "NIntegrate Rule RulePattern Subst TD TExplicitSum " +
29
                        "TSum Taylor Taylor1 Taylor2 Taylor3 ToFile " +
30
                        "ToStdout ToString TraceRule Until While");
31

32
  // patterns
33
  var pFloatForm  = "(?:(?:\\.\\d+|\\d+\\.\\d*|\\d+)(?:[eE][+-]?\\d+)?)";
34
  var pIdentifier = "(?:[a-zA-Z\\$'][a-zA-Z0-9\\$']*)";
35

36
  // regular expressions
37
  var reFloatForm    = new RegExp(pFloatForm);
38
  var reIdentifier   = new RegExp(pIdentifier);
39
  var rePattern      = new RegExp(pIdentifier + "?_" + pIdentifier);
40
  var reFunctionLike = new RegExp(pIdentifier + "\\s*\\(");
41

42
  function tokenBase(stream, state) {
43
    var ch;
44

45
    // get next character
46
    ch = stream.next();
47

48
    // string
49
    if (ch === '"') {
50
      state.tokenize = tokenString;
51
      return state.tokenize(stream, state);
52
    }
53

54
    // comment
55
    if (ch === '/') {
56
      if (stream.eat('*')) {
57
        state.tokenize = tokenComment;
58
        return state.tokenize(stream, state);
59
      }
60
      if (stream.eat("/")) {
61
        stream.skipToEnd();
62
        return "comment";
63
      }
64
    }
65

66
    // go back one character
67
    stream.backUp(1);
68

69
    // update scope info
70
    var m = stream.match(/^(\w+)\s*\(/, false);
71
    if (m !== null && bodiedOps.hasOwnProperty(m[1]))
72
      state.scopes.push('bodied');
73

74
    var scope = currentScope(state);
75

76
    if (scope === 'bodied' && ch === '[')
77
      state.scopes.pop();
78

79
    if (ch === '[' || ch === '{' || ch === '(')
80
      state.scopes.push(ch);
81

82
    scope = currentScope(state);
83

84
    if (scope === '[' && ch === ']' ||
85
        scope === '{' && ch === '}' ||
86
        scope === '(' && ch === ')')
87
      state.scopes.pop();
88

89
    if (ch === ';') {
90
      while (scope === 'bodied') {
91
        state.scopes.pop();
92
        scope = currentScope(state);
93
      }
94
    }
95

96
    // look for ordered rules
97
    if (stream.match(/\d+ *#/, true, false)) {
98
      return 'qualifier';
99
    }
100

101
    // look for numbers
102
    if (stream.match(reFloatForm, true, false)) {
103
      return 'number';
104
    }
105

106
    // look for placeholders
107
    if (stream.match(rePattern, true, false)) {
108
      return 'variable-3';
109
    }
110

111
    // match all braces separately
112
    if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) {
113
      return 'bracket';
114
    }
115

116
    // literals looking like function calls
117
    if (stream.match(reFunctionLike, true, false)) {
118
      stream.backUp(1);
119
      return 'variable';
120
    }
121

122
    // all other identifiers
123
    if (stream.match(reIdentifier, true, false)) {
124
      return 'variable-2';
125
    }
126

127
    // operators; note that operators like @@ or /; are matched separately for each symbol.
128
    if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%|#)/, true, false)) {
129
      return 'operator';
130
    }
131

132
    // everything else is an error
133
    return 'error';
134
  }
135

136
  function tokenString(stream, state) {
137
    var next, end = false, escaped = false;
138
    while ((next = stream.next()) != null) {
139
      if (next === '"' && !escaped) {
140
        end = true;
141
        break;
142
      }
143
      escaped = !escaped && next === '\\';
144
    }
145
    if (end && !escaped) {
146
      state.tokenize = tokenBase;
147
    }
148
    return 'string';
149
  };
150

151
  function tokenComment(stream, state) {
152
    var prev, next;
153
    while((next = stream.next()) != null) {
154
      if (prev === '*' && next === '/') {
155
        state.tokenize = tokenBase;
156
        break;
157
      }
158
      prev = next;
159
    }
160
    return 'comment';
161
  }
162

163
  function currentScope(state) {
164
    var scope = null;
165
    if (state.scopes.length > 0)
166
      scope = state.scopes[state.scopes.length - 1];
167
    return scope;
168
  }
169

170
  return {
171
    startState: function() {
172
      return {
173
        tokenize: tokenBase,
174
        scopes: []
175
      };
176
    },
177
    token: function(stream, state) {
178
      if (stream.eatSpace()) return null;
179
      return state.tokenize(stream, state);
180
    },
181
    indent: function(state, textAfter) {
182
      if (state.tokenize !== tokenBase && state.tokenize !== null)
183
        return CodeMirror.Pass;
184

185
      var delta = 0;
186
      if (textAfter === ']' || textAfter === '];' ||
187
          textAfter === '}' || textAfter === '};' ||
188
          textAfter === ');')
189
        delta = -1;
190

191
      return (state.scopes.length + delta) * _config.indentUnit;
192
    },
193
    electricChars: "{}[]();",
194
    blockCommentStart: "/*",
195
    blockCommentEnd: "*/",
196
    lineComment: "//"
197
  };
198
});
199

200
CodeMirror.defineMIME('text/x-yacas', {
201
  name: 'yacas'
202
});
203

204
});
205

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.