GPQAPP

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

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

14
CodeMirror.defineMode("oz", function (conf) {
15

16
  function wordRegexp(words) {
17
    return new RegExp("^((" + words.join(")|(") + "))\\b");
18
  }
19

20
  var singleOperators = /[\^@!\|<>#~\.\*\-\+\\/,=]/;
21
  var doubleOperators = /(<-)|(:=)|(=<)|(>=)|(<=)|(<:)|(>:)|(=:)|(\\=)|(\\=:)|(!!)|(==)|(::)/;
22
  var tripleOperators = /(:::)|(\.\.\.)|(=<:)|(>=:)/;
23

24
  var middle = ["in", "then", "else", "of", "elseof", "elsecase", "elseif", "catch",
25
    "finally", "with", "require", "prepare", "import", "export", "define", "do"];
26
  var end = ["end"];
27

28
  var atoms = wordRegexp(["true", "false", "nil", "unit"]);
29
  var commonKeywords = wordRegexp(["andthen", "at", "attr", "declare", "feat", "from", "lex",
30
    "mod", "div", "mode", "orelse", "parser", "prod", "prop", "scanner", "self", "syn", "token"]);
31
  var openingKeywords = wordRegexp(["local", "proc", "fun", "case", "class", "if", "cond", "or", "dis",
32
    "choice", "not", "thread", "try", "raise", "lock", "for", "suchthat", "meth", "functor"]);
33
  var middleKeywords = wordRegexp(middle);
34
  var endKeywords = wordRegexp(end);
35

36
  // Tokenizers
37
  function tokenBase(stream, state) {
38
    if (stream.eatSpace()) {
39
      return null;
40
    }
41

42
    // Brackets
43
    if(stream.match(/[{}]/)) {
44
      return "bracket";
45
    }
46

47
    // Special [] keyword
48
    if (stream.match('[]')) {
49
        return "keyword"
50
    }
51

52
    // Operators
53
    if (stream.match(tripleOperators) || stream.match(doubleOperators)) {
54
      return "operator";
55
    }
56

57
    // Atoms
58
    if(stream.match(atoms)) {
59
      return 'atom';
60
    }
61

62
    // Opening keywords
63
    var matched = stream.match(openingKeywords);
64
    if (matched) {
65
      if (!state.doInCurrentLine)
66
        state.currentIndent++;
67
      else
68
        state.doInCurrentLine = false;
69

70
      // Special matching for signatures
71
      if(matched[0] == "proc" || matched[0] == "fun")
72
        state.tokenize = tokenFunProc;
73
      else if(matched[0] == "class")
74
        state.tokenize = tokenClass;
75
      else if(matched[0] == "meth")
76
        state.tokenize = tokenMeth;
77

78
      return 'keyword';
79
    }
80

81
    // Middle and other keywords
82
    if (stream.match(middleKeywords) || stream.match(commonKeywords)) {
83
      return "keyword"
84
    }
85

86
    // End keywords
87
    if (stream.match(endKeywords)) {
88
      state.currentIndent--;
89
      return 'keyword';
90
    }
91

92
    // Eat the next char for next comparisons
93
    var ch = stream.next();
94

95
    // Strings
96
    if (ch == '"' || ch == "'") {
97
      state.tokenize = tokenString(ch);
98
      return state.tokenize(stream, state);
99
    }
100

101
    // Numbers
102
    if (/[~\d]/.test(ch)) {
103
      if (ch == "~") {
104
        if(! /^[0-9]/.test(stream.peek()))
105
          return null;
106
        else if (( stream.next() == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/))
107
          return "number";
108
      }
109

110
      if ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/))
111
        return "number";
112

113
      return null;
114
    }
115

116
    // Comments
117
    if (ch == "%") {
118
      stream.skipToEnd();
119
      return 'comment';
120
    }
121
    else if (ch == "/") {
122
      if (stream.eat("*")) {
123
        state.tokenize = tokenComment;
124
        return tokenComment(stream, state);
125
      }
126
    }
127

128
    // Single operators
129
    if(singleOperators.test(ch)) {
130
      return "operator";
131
    }
132

133
    // If nothing match, we skip the entire alphanumeric block
134
    stream.eatWhile(/\w/);
135

136
    return "variable";
137
  }
138

139
  function tokenClass(stream, state) {
140
    if (stream.eatSpace()) {
141
      return null;
142
    }
143
    stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)/);
144
    state.tokenize = tokenBase;
145
    return "variable-3"
146
  }
147

148
  function tokenMeth(stream, state) {
149
    if (stream.eatSpace()) {
150
      return null;
151
    }
152
    stream.match(/([a-zA-Z][A-Za-z0-9_]*)|(`.+`)/);
153
    state.tokenize = tokenBase;
154
    return "def"
155
  }
156

157
  function tokenFunProc(stream, state) {
158
    if (stream.eatSpace()) {
159
      return null;
160
    }
161

162
    if(!state.hasPassedFirstStage && stream.eat("{")) {
163
      state.hasPassedFirstStage = true;
164
      return "bracket";
165
    }
166
    else if(state.hasPassedFirstStage) {
167
      stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)|\$/);
168
      state.hasPassedFirstStage = false;
169
      state.tokenize = tokenBase;
170
      return "def"
171
    }
172
    else {
173
      state.tokenize = tokenBase;
174
      return null;
175
    }
176
  }
177

178
  function tokenComment(stream, state) {
179
    var maybeEnd = false, ch;
180
    while (ch = stream.next()) {
181
      if (ch == "/" && maybeEnd) {
182
        state.tokenize = tokenBase;
183
        break;
184
      }
185
      maybeEnd = (ch == "*");
186
    }
187
    return "comment";
188
  }
189

190
  function tokenString(quote) {
191
    return function (stream, state) {
192
      var escaped = false, next, end = false;
193
      while ((next = stream.next()) != null) {
194
        if (next == quote && !escaped) {
195
          end = true;
196
          break;
197
        }
198
        escaped = !escaped && next == "\\";
199
      }
200
      if (end || !escaped)
201
        state.tokenize = tokenBase;
202
      return "string";
203
    };
204
  }
205

206
  function buildElectricInputRegEx() {
207
    // Reindentation should occur on [] or on a match of any of
208
    // the block closing keywords, at the end of a line.
209
    var allClosings = middle.concat(end);
210
    return new RegExp("[\\[\\]]|(" + allClosings.join("|") + ")$");
211
  }
212

213
  return {
214

215
    startState: function () {
216
      return {
217
        tokenize: tokenBase,
218
        currentIndent: 0,
219
        doInCurrentLine: false,
220
        hasPassedFirstStage: false
221
      };
222
    },
223

224
    token: function (stream, state) {
225
      if (stream.sol())
226
        state.doInCurrentLine = 0;
227

228
      return state.tokenize(stream, state);
229
    },
230

231
    indent: function (state, textAfter) {
232
      var trueText = textAfter.replace(/^\s+|\s+$/g, '');
233

234
      if (trueText.match(endKeywords) || trueText.match(middleKeywords) || trueText.match(/(\[])/))
235
        return conf.indentUnit * (state.currentIndent - 1);
236

237
      if (state.currentIndent < 0)
238
        return 0;
239

240
      return state.currentIndent * conf.indentUnit;
241
    },
242
    fold: "indent",
243
    electricInput: buildElectricInputRegEx(),
244
    lineComment: "%",
245
    blockCommentStart: "/*",
246
    blockCommentEnd: "*/"
247
  };
248
});
249

250
CodeMirror.defineMIME("text/x-oz", "oz");
251

252
});
253

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

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

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

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