Passed
Push — master ( 3324e2...2ba76b )
by Ralf
13:44
created

verilog.js ➔ tokenBase   F

Complexity

Conditions 23

Size

Total Lines 93
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 62
c 0
b 0
f 0
dl 0
loc 93
rs 0
cc 23

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like verilog.js ➔ tokenBase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
// CodeMirror, copyright (c) by Marijn Haverbeke and others
2
// Distributed under an MIT license: http://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
0 ignored issues
show
Bug introduced by
The variable define seems to be never declared. If this is a global, consider adding a /** global: define */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
8
    define(["../../lib/codemirror"], mod);
9
  else // Plain browser env
10
    mod(CodeMirror);
0 ignored issues
show
Bug introduced by
The variable CodeMirror seems to be never declared. If this is a global, consider adding a /** global: CodeMirror */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
11
})(function(CodeMirror) {
12
"use strict";
13
14
CodeMirror.defineMode("verilog", function(config, parserConfig) {
15
16
  var indentUnit = config.indentUnit,
17
      statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
18
      dontAlignCalls = parserConfig.dontAlignCalls,
19
      noIndentKeywords = parserConfig.noIndentKeywords || [],
20
      multiLineStrings = parserConfig.multiLineStrings,
21
      hooks = parserConfig.hooks || {};
22
23
  function words(str) {
24
    var obj = {}, words = str.split(" ");
25
    for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
26
    return obj;
27
  }
28
29
  /**
30
   * Keywords from IEEE 1800-2012
31
   */
32
  var keywords = words(
33
    "accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind " +
34
    "bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config " +
35
    "const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable " +
36
    "dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup " +
37
    "endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask " +
38
    "enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin " +
39
    "function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import " +
40
    "incdir include initial inout input inside instance int integer interconnect interface intersect join join_any " +
41
    "join_none large let liblist library local localparam logic longint macromodule matches medium modport module " +
42
    "nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed " +
43
    "parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup " +
44
    "pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg " +
45
    "reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime " +
46
    "s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify " +
47
    "specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on " +
48
    "table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior " +
49
    "trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void " +
50
    "wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor");
51
52
  /** Operators from IEEE 1800-2012
53
     unary_operator ::=
54
       + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
55
     binary_operator ::=
56
       + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | **
57
       | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
58
       | -> | <->
59
     inc_or_dec_operator ::= ++ | --
60
     unary_module_path_operator ::=
61
       ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
62
     binary_module_path_operator ::=
63
       == | != | && | || | & | | | ^ | ^~ | ~^
64
  */
65
  var isOperatorChar = /[\+\-\*\/!~&|^%=?:]/;
66
  var isBracketChar = /[\[\]{}()]/;
67
68
  var unsignedNumber = /\d[0-9_]*/;
69
  var decimalLiteral = /\d*\s*'s?d\s*\d[0-9_]*/i;
70
  var binaryLiteral = /\d*\s*'s?b\s*[xz01][xz01_]*/i;
71
  var octLiteral = /\d*\s*'s?o\s*[xz0-7][xz0-7_]*/i;
72
  var hexLiteral = /\d*\s*'s?h\s*[0-9a-fxz?][0-9a-fxz?_]*/i;
73
  var realLiteral = /(\d[\d_]*(\.\d[\d_]*)?E-?[\d_]+)|(\d[\d_]*\.\d[\d_]*)/i;
74
75
  var closingBracketOrWord = /^((\w+)|[)}\]])/;
76
  var closingBracket = /[)}\]]/;
77
78
  var curPunc;
79
  var curKeyword;
80
81
  // Block openings which are closed by a matching keyword in the form of ("end" + keyword)
82
  // E.g. "task" => "endtask"
83
  var blockKeywords = words(
84
    "case checker class clocking config function generate interface module package" +
85
    "primitive program property specify sequence table task"
86
  );
87
88
  // Opening/closing pairs
89
  var openClose = {};
90
  for (var keyword in blockKeywords) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
91
    openClose[keyword] = "end" + keyword;
92
  }
93
  openClose["begin"] = "end";
94
  openClose["casex"] = "endcase";
95
  openClose["casez"] = "endcase";
96
  openClose["do"   ] = "while";
97
  openClose["fork" ] = "join;join_any;join_none";
98
  openClose["covergroup"] = "endgroup";
99
100
  for (var i in noIndentKeywords) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
101
    var keyword = noIndentKeywords[i];
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable keyword already seems to be declared on line 90. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
102
    if (openClose[keyword]) {
103
      openClose[keyword] = undefined;
104
    }
105
  }
106
107
  // Keywords which open statements that are ended with a semi-colon
108
  var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while");
109
110
  function tokenBase(stream, state) {
111
    var ch = stream.peek(), style;
112
    if (hooks[ch] && (style = hooks[ch](stream, state)) != false) return style;
0 ignored issues
show
Best Practice introduced by
Comparing style = hooks.ch(stream, state) to false using the != operator is not safe. Consider using !== instead.
Loading history...
113
    if (hooks.tokenBase && (style = hooks.tokenBase(stream, state)) != false)
0 ignored issues
show
Best Practice introduced by
Comparing style = hooks.tokenBase(stream, state) to false using the != operator is not safe. Consider using !== instead.
Loading history...
114
      return style;
115
116
    if (/[,;:\.]/.test(ch)) {
117
      curPunc = stream.next();
118
      return null;
119
    }
120
    if (isBracketChar.test(ch)) {
121
      curPunc = stream.next();
122
      return "bracket";
123
    }
124
    // Macros (tick-defines)
125
    if (ch == '`') {
126
      stream.next();
127
      if (stream.eatWhile(/[\w\$_]/)) {
128
        return "def";
129
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
130
        return null;
131
      }
132
    }
133
    // System calls
134
    if (ch == '$') {
135
      stream.next();
136
      if (stream.eatWhile(/[\w\$_]/)) {
137
        return "meta";
138
      } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
139
        return null;
140
      }
141
    }
142
    // Time literals
143
    if (ch == '#') {
144
      stream.next();
145
      stream.eatWhile(/[\d_.]/);
146
      return "def";
147
    }
148
    // Strings
149
    if (ch == '"') {
150
      stream.next();
151
      state.tokenize = tokenString(ch);
152
      return state.tokenize(stream, state);
153
    }
154
    // Comments
155
    if (ch == "/") {
156
      stream.next();
157
      if (stream.eat("*")) {
158
        state.tokenize = tokenComment;
159
        return tokenComment(stream, state);
160
      }
161
      if (stream.eat("/")) {
162
        stream.skipToEnd();
163
        return "comment";
164
      }
165
      stream.backUp(1);
166
    }
167
168
    // Numeric literals
169
    if (stream.match(realLiteral) ||
170
        stream.match(decimalLiteral) ||
171
        stream.match(binaryLiteral) ||
172
        stream.match(octLiteral) ||
173
        stream.match(hexLiteral) ||
174
        stream.match(unsignedNumber) ||
175
        stream.match(realLiteral)) {
176
      return "number";
177
    }
178
179
    // Operators
180
    if (stream.eatWhile(isOperatorChar)) {
181
      return "meta";
182
    }
183
184
    // Keywords / plain variables
185
    if (stream.eatWhile(/[\w\$_]/)) {
186
      var cur = stream.current();
187
      if (keywords[cur]) {
188
        if (openClose[cur]) {
189
          curPunc = "newblock";
190
        }
191
        if (statementKeywords[cur]) {
192
          curPunc = "newstatement";
193
        }
194
        curKeyword = cur;
195
        return "keyword";
196
      }
197
      return "variable";
198
    }
199
200
    stream.next();
201
    return null;
202
  }
203
204
  function tokenString(quote) {
205
    return function(stream, state) {
206
      var escaped = false, next, end = false;
207
      while ((next = stream.next()) != null) {
0 ignored issues
show
Best Practice introduced by
Comparing next = stream.next() to null using the != operator is not safe. Consider using !== instead.
Loading history...
208
        if (next == quote && !escaped) {end = true; break;}
209
        escaped = !escaped && next == "\\";
210
      }
211
      if (end || !(escaped || multiLineStrings))
212
        state.tokenize = tokenBase;
213
      return "string";
214
    };
215
  }
216
217
  function tokenComment(stream, state) {
218
    var maybeEnd = false, ch;
219
    while (ch = stream.next()) {
220
      if (ch == "/" && maybeEnd) {
221
        state.tokenize = tokenBase;
222
        break;
223
      }
224
      maybeEnd = (ch == "*");
225
    }
226
    return "comment";
227
  }
228
229
  function Context(indented, column, type, align, prev) {
230
    this.indented = indented;
231
    this.column = column;
232
    this.type = type;
233
    this.align = align;
234
    this.prev = prev;
235
  }
236
  function pushContext(state, col, type) {
237
    var indent = state.indented;
238
    var c = new Context(indent, col, type, null, state.context);
239
    return state.context = c;
240
  }
241
  function popContext(state) {
242
    var t = state.context.type;
243
    if (t == ")" || t == "]" || t == "}") {
244
      state.indented = state.context.indented;
245
    }
246
    return state.context = state.context.prev;
247
  }
248
249
  function isClosing(text, contextClosing) {
250
    if (text == contextClosing) {
251
      return true;
252
    } else {
0 ignored issues
show
Comprehensibility introduced by
else is not necessary here since all if branches return, consider removing it to reduce nesting and make code more readable.
Loading history...
253
      // contextClosing may be mulitple keywords separated by ;
254
      var closingKeywords = contextClosing.split(";");
255
      for (var i in closingKeywords) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
256
        if (text == closingKeywords[i]) {
257
          return true;
258
        }
259
      }
260
      return false;
261
    }
262
  }
263
264
  function buildElectricInputRegEx() {
265
    // Reindentation should occur on any bracket char: {}()[]
266
    // or on a match of any of the block closing keywords, at
267
    // the end of a line
268
    var allClosings = [];
269
    for (var i in openClose) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
270
      if (openClose[i]) {
271
        var closings = openClose[i].split(";");
272
        for (var j in closings) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
273
          allClosings.push(closings[j]);
274
        }
275
      }
276
    }
277
    var re = new RegExp("[{}()\\[\\]]|(" + allClosings.join("|") + ")$");
278
    return re;
279
  }
280
281
  // Interface
282
  return {
283
284
    // Regex to force current line to reindent
285
    electricInput: buildElectricInputRegEx(),
286
287
    startState: function(basecolumn) {
288
      var state = {
289
        tokenize: null,
290
        context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
291
        indented: 0,
292
        startOfLine: true
293
      };
294
      if (hooks.startState) hooks.startState(state);
295
      return state;
296
    },
297
298
    token: function(stream, state) {
299
      var ctx = state.context;
300
      if (stream.sol()) {
301
        if (ctx.align == null) ctx.align = false;
0 ignored issues
show
Best Practice introduced by
Comparing ctx.align to null using the == operator is not safe. Consider using === instead.
Loading history...
302
        state.indented = stream.indentation();
303
        state.startOfLine = true;
304
      }
305
      if (hooks.token) hooks.token(stream, state);
306
      if (stream.eatSpace()) return null;
307
      curPunc = null;
308
      curKeyword = null;
309
      var style = (state.tokenize || tokenBase)(stream, state);
310
      if (style == "comment" || style == "meta" || style == "variable") return style;
311
      if (ctx.align == null) ctx.align = true;
312
313
      if (curPunc == ctx.type) {
314
        popContext(state);
315
      } else if ((curPunc == ";" && ctx.type == "statement") ||
316
               (ctx.type && isClosing(curKeyword, ctx.type))) {
317
        ctx = popContext(state);
318
        while (ctx && ctx.type == "statement") ctx = popContext(state);
319
      } else if (curPunc == "{") {
320
        pushContext(state, stream.column(), "}");
321
      } else if (curPunc == "[") {
322
        pushContext(state, stream.column(), "]");
323
      } else if (curPunc == "(") {
324
        pushContext(state, stream.column(), ")");
325
      } else if (ctx && ctx.type == "endcase" && curPunc == ":") {
326
        pushContext(state, stream.column(), "statement");
327
      } else if (curPunc == "newstatement") {
328
        pushContext(state, stream.column(), "statement");
329
      } else if (curPunc == "newblock") {
330
        if (curKeyword == "function" && ctx && (ctx.type == "statement" || ctx.type == "endgroup")) {
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
331
          // The 'function' keyword can appear in some other contexts where it actually does not
332
          // indicate a function (import/export DPI and covergroup definitions).
333
          // Do nothing in this case
334
        } else if (curKeyword == "task" && ctx && ctx.type == "statement") {
0 ignored issues
show
Comprehensibility Documentation Best Practice introduced by
This code block is empty. Consider removing it or adding a comment to explain.
Loading history...
335
          // Same thing for task
336
        } else {
337
          var close = openClose[curKeyword];
338
          pushContext(state, stream.column(), close);
339
        }
340
      }
341
342
      state.startOfLine = false;
343
      return style;
344
    },
345
346
    indent: function(state, textAfter) {
347
      if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
0 ignored issues
show
Best Practice introduced by
Comparing state.tokenize to null using the != operator is not safe. Consider using !== instead.
Loading history...
348
      if (hooks.indent) {
349
        var fromHook = hooks.indent(state);
350
        if (fromHook >= 0) return fromHook;
351
      }
352
      var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
353
      if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
354
      var closing = false;
355
      var possibleClosing = textAfter.match(closingBracketOrWord);
356
      if (possibleClosing)
357
        closing = isClosing(possibleClosing[0], ctx.type);
358
      if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
359
      else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1);
360
      else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
361
      else return ctx.indented + (closing ? 0 : indentUnit);
362
    },
363
364
    blockCommentStart: "/*",
365
    blockCommentEnd: "*/",
366
    lineComment: "//"
367
  };
368
});
369
370
  CodeMirror.defineMIME("text/x-verilog", {
371
    name: "verilog"
372
  });
373
374
  CodeMirror.defineMIME("text/x-systemverilog", {
375
    name: "verilog"
376
  });
377
378
  // SVXVerilog mode
379
380
  var svxchScopePrefixes = {
381
    ">": "property", "->": "property", "-": "hr", "|": "link", "?$": "qualifier", "?*": "qualifier",
382
    "@-": "variable-3", "@": "variable-3", "?": "qualifier"
383
  };
384
385
  function svxGenIndent(stream, state) {
386
    var svxindentUnit = 2;
387
    var rtnIndent = -1, indentUnitRq = 0, curIndent = stream.indentation();
0 ignored issues
show
Unused Code introduced by
The assignment to variable rtnIndent seems to be never used. Consider removing it.
Loading history...
388
    switch (state.svxCurCtlFlowChar) {
389
    case "\\":
390
      curIndent = 0;
391
      break;
392
    case "|":
393
      if (state.svxPrevPrevCtlFlowChar == "@") {
394
        indentUnitRq = -2; //-2 new pipe rq after cur pipe
395
        break;
396
      }
397
      if (svxchScopePrefixes[state.svxPrevCtlFlowChar])
398
        indentUnitRq = 1; // +1 new scope
399
      break;
400
    case "M":  // m4
401
      if (state.svxPrevPrevCtlFlowChar == "@") {
402
        indentUnitRq = -2; //-2 new inst rq after  pipe
403
        break;
404
      }
405
      if (svxchScopePrefixes[state.svxPrevCtlFlowChar])
406
        indentUnitRq = 1; // +1 new scope
407
      break;
408
    case "@":
409
      if (state.svxPrevCtlFlowChar == "S")
410
        indentUnitRq = -1; // new pipe stage after stmts
411
      if (state.svxPrevCtlFlowChar == "|")
412
        indentUnitRq = 1; // 1st pipe stage
413
      break;
414
    case "S":
415
      if (state.svxPrevCtlFlowChar == "@")
416
        indentUnitRq = 1; // flow in pipe stage
417
      if (svxchScopePrefixes[state.svxPrevCtlFlowChar])
418
        indentUnitRq = 1; // +1 new scope
419
      break;
420
    }
421
    var statementIndentUnit = svxindentUnit;
422
    rtnIndent = curIndent + (indentUnitRq*statementIndentUnit);
423
    return rtnIndent >= 0 ? rtnIndent : curIndent;
424
  }
425
426
  CodeMirror.defineMIME("text/x-svx", {
427
    name: "verilog",
428
    hooks: {
429
      "\\": function(stream, state) {
430
        var vxIndent = 0, style = false;
431
        var curPunc  = stream.string;
0 ignored issues
show
Unused Code introduced by
The assignment to variable curPunc seems to be never used. Consider removing it.
Loading history...
432
        if ((stream.sol()) && (/\\SV/.test(stream.string))) {
433
          curPunc = (/\\SVX_version/.test(stream.string))
434
            ? "\\SVX_version" : stream.string;
435
          stream.skipToEnd();
436
          if (curPunc == "\\SV" && state.vxCodeActive) {state.vxCodeActive = false;};
437
          if ((/\\SVX/.test(curPunc) && !state.vxCodeActive)
438
            || (curPunc=="\\SVX_version" && state.vxCodeActive)) {state.vxCodeActive = true;};
439
          style = "keyword";
440
          state.svxCurCtlFlowChar  = state.svxPrevPrevCtlFlowChar
441
            = state.svxPrevCtlFlowChar = "";
442
          if (state.vxCodeActive == true) {
0 ignored issues
show
Best Practice introduced by
Comparing state.vxCodeActive to true using the == operator is not safe. Consider using === instead.
Loading history...
443
            state.svxCurCtlFlowChar  = "\\";
444
            vxIndent = svxGenIndent(stream, state);
445
          }
446
          state.vxIndentRq = vxIndent;
447
        }
448
        return style;
449
      },
450
      tokenBase: function(stream, state) {
451
        var vxIndent = 0, style = false;
452
        var svxisOperatorChar = /[\[\]=:]/;
453
        var svxkpScopePrefixs = {
454
          "**":"variable-2", "*":"variable-2", "$$":"variable", "$":"variable",
455
          "^^":"attribute", "^":"attribute"};
456
        var ch = stream.peek();
457
        var vxCurCtlFlowCharValueAtStart = state.svxCurCtlFlowChar;
458
        if (state.vxCodeActive == true) {
0 ignored issues
show
Best Practice introduced by
Comparing state.vxCodeActive to true using the == operator is not safe. Consider using === instead.
Loading history...
459
          if (/[\[\]{}\(\);\:]/.test(ch)) {
460
            // bypass nesting and 1 char punc
461
            style = "meta";
462
            stream.next();
463
          } else if (ch == "/") {
464
            stream.next();
465
            if (stream.eat("/")) {
466
              stream.skipToEnd();
467
              style = "comment";
468
              state.svxCurCtlFlowChar = "S";
469
            } else {
470
              stream.backUp(1);
471
            }
472
          } else if (ch == "@") {
473
            // pipeline stage
474
            style = svxchScopePrefixes[ch];
475
            state.svxCurCtlFlowChar = "@";
476
            stream.next();
477
            stream.eatWhile(/[\w\$_]/);
478
          } else if (stream.match(/\b[mM]4+/, true)) { // match: function(pattern, consume, caseInsensitive)
479
            // m4 pre proc
480
            stream.skipTo("(");
481
            style = "def";
482
            state.svxCurCtlFlowChar = "M";
483
          } else if (ch == "!" && stream.sol()) {
484
            // v stmt in svx region
485
            // state.svxCurCtlFlowChar  = "S";
486
            style = "comment";
487
            stream.next();
488
          } else if (svxisOperatorChar.test(ch)) {
489
            // operators
490
            stream.eatWhile(svxisOperatorChar);
491
            style = "operator";
492
          } else if (ch == "#") {
493
            // phy hier
494
            state.svxCurCtlFlowChar  = (state.svxCurCtlFlowChar == "")
495
              ? ch : state.svxCurCtlFlowChar;
496
            stream.next();
497
            stream.eatWhile(/[+-]\d/);
498
            style = "tag";
499
          } else if (svxkpScopePrefixs.propertyIsEnumerable(ch)) {
500
            // special SVX operators
501
            style = svxkpScopePrefixs[ch];
502
            state.svxCurCtlFlowChar = state.svxCurCtlFlowChar == "" ? "S" : state.svxCurCtlFlowChar;  // stmt
503
            stream.next();
504
            stream.match(/[a-zA-Z_0-9]+/);
505
          } else if (style = svxchScopePrefixes[ch] || false) {
506
            // special SVX operators
507
            state.svxCurCtlFlowChar = state.svxCurCtlFlowChar == "" ? ch : state.svxCurCtlFlowChar;
508
            stream.next();
509
            stream.match(/[a-zA-Z_0-9]+/);
510
          }
511
          if (state.svxCurCtlFlowChar != vxCurCtlFlowCharValueAtStart) { // flow change
512
            vxIndent = svxGenIndent(stream, state);
513
            state.vxIndentRq = vxIndent;
514
          }
515
        }
516
        return style;
517
      },
518
      token: function(stream, state) {
519
        if (state.vxCodeActive == true && stream.sol() && state.svxCurCtlFlowChar != "") {
0 ignored issues
show
Best Practice introduced by
Comparing state.vxCodeActive to true using the == operator is not safe. Consider using === instead.
Loading history...
520
          state.svxPrevPrevCtlFlowChar = state.svxPrevCtlFlowChar;
521
          state.svxPrevCtlFlowChar = state.svxCurCtlFlowChar;
522
          state.svxCurCtlFlowChar = "";
523
        }
524
      },
525
      indent: function(state) {
526
        return (state.vxCodeActive == true) ? state.vxIndentRq : -1;
0 ignored issues
show
Best Practice introduced by
Comparing state.vxCodeActive to true using the == operator is not safe. Consider using === instead.
Loading history...
527
      },
528
      startState: function(state) {
529
        state.svxCurCtlFlowChar = "";
530
        state.svxPrevCtlFlowChar = "";
531
        state.svxPrevPrevCtlFlowChar = "";
532
        state.vxCodeActive = true;
533
        state.vxIndentRq = 0;
534
      }
535
    }
536
  });
537
});
538