-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
-
275
-
276
-
277
-
278
-
279
-
280
-
281
-
282
-
283
-
284
-
285
-
286
-
287
-
288
-
289
-
290
-
291
-
292
-
293
-
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
303
-
304
-
305
-
306
-
307
-
308
-
309
-
310
-
311
-
312
-
313
-
314
-
315
-
316
-
317
-
318
-
319
-
320
-
321
-
322
-
323
-
324
-
325
-
326
-
327
-
328
-
329
-
330
-
331
-
332
-
333
-
334
-
335
-
336
-
337
-
338
-
339
-
340
-
341
-
342
-
343
-
344
-
345
-
346
-
347
-
348
-
349
-
350
-
351
-
352
-
353
-
354
-
355
-
356
-
357
-
358
-
359
-
360
-
361
-
362
-
363
-
364
-
365
-
366
-
367
-
368
-
369
-
370
-
371
-
372
-
373
-
374
-
375
-
376
-
377
-
378
-
379
-
380
-
381
-
382
-
383
-
384
-
385
-
386
-
387
-
388
-
389
-
390
-
391
-
392
-
393
-
394
-
395
-
396
-
397
-
398
-
399
-
400
-
401
-
402
-
403
-
404
-
405
-
406
-
407
-
408
-
409
-
410
-
411
-
412
-
413
-
414
-
415
-
416
-
417
-
418
-
419
-
420
-
421
-
422
-
423
-
424
-
425
-
426
-
427
-
428
-
429
-
430
-
431
-
432
-
433
-
434
-
435
-
436
-
437
-
438
-
439
-
440
-
441
-
442
-
443
-
444
-
445
-
446
-
447
-
448
-
449
-
450
-
451
-
452
-
453
-
454
-
455
-
456
-
457
-
458
-
459
-
460
-
461
-
462
-
463
-
464
-
465
-
466
-
467
-
468
-
469
-
470
-
471
-
472
-
473
-
474
-
475
-
476
-
477
-
478
-
479
-
480
-
481
-
482
-
483
-
484
-
485
-
486
-
487
-
488
-
489
-
490
-
491
-
492
-
493
-
494
-
495
-
496
-
497
-
498
-
499
-
500
-
501
-
502
-
503
-
504
-
505
-
506
-
507
-
508
-
509
-
510
-
511
-
512
-
513
-
514
-
515
-
516
-
517
-
518
-
519
-
520
-
521
-
522
-
523
-
524
-
525
-
526
-
527
-
528
-
529
-
530
-
531
-
532
-
533
-
534
-
535
-
536
-
537
-
538
-
539
-
540
-
541
-
542
-
543
-
544
-
545
-
546
-
547
-
548
-
549
-
550
-
551
-
552
-
553
-
554
-
555
-
556
-
557
-
558
-
559
-
560
-
561
-
562
-
563
-
564
-
565
-
566
-
567
-
568
-
569
-
570
-
571
-
572
-
573
-
574
-
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
-
595
-
596
-
597
-
598
-
599
-
600
-
601
-
602
-
603
-
604
-
605
-
606
-
607
-
608
-
609
-
610
-
611
-
612
-
613
-
614
-
615
-
616
-
617
-
618
-
619
-
620
-
621
-
622
-
623
-
624
-
625
-
626
-
627
-
628
-
629
-
630
-
631
-
632
-
633
-
634
-
635
-
636
-
637
-
638
-
639
-
640
-
641
-
642
-
643
-
644
-
645
-
646
-
647
-
648
-
649
-
650
-
651
-
652
-
653
-
654
-
655
-
656
-
657
-
658
-
659
-
660
-
661
-
662
-
663
-
664
-
665
-
666
-
667
-
668
-
669
-
670
-
671
-
672
-
673
-
674
-
675
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/LICENSE
(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("verilog", function(config, parserConfig) {
var indentUnit = config.indentUnit,
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
dontAlignCalls = parserConfig.dontAlignCalls,
noIndentKeywords = parserConfig.noIndentKeywords || [],
multiLineStrings = parserConfig.multiLineStrings,
hooks = parserConfig.hooks || {};
function words(str) {
var obj = {}, words = str.split(" ");
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
return obj;
}
/**
* Keywords from IEEE 1800-2012
*/
var keywords = words(
"accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind " +
"bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config " +
"const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable " +
"dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup " +
"endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask " +
"enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin " +
"function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import " +
"incdir include initial inout input inside instance int integer interconnect interface intersect join join_any " +
"join_none large let liblist library local localparam logic longint macromodule matches medium modport module " +
"nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed " +
"parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup " +
"pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg " +
"reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime " +
"s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify " +
"specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on " +
"table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior " +
"trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void " +
"wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor");
/** Operators from IEEE 1800-2012
unary_operator ::=
+ | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_operator ::=
+ | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | **
| < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<<
| -> | <->
inc_or_dec_operator ::= ++ | --
unary_module_path_operator ::=
! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~
binary_module_path_operator ::=
== | != | && | || | & | | | ^ | ^~ | ~^
*/
var isOperatorChar = /[\+\-\*\/!~&|^%=?:]/;
var isBracketChar = /[\[\]{}()]/;
var unsignedNumber = /\d[0-9_]*/;
var decimalLiteral = /\d*\s*'s?d\s*\d[0-9_]*/i;
var binaryLiteral = /\d*\s*'s?b\s*[xz01][xz01_]*/i;
var octLiteral = /\d*\s*'s?o\s*[xz0-7][xz0-7_]*/i;
var hexLiteral = /\d*\s*'s?h\s*[0-9a-fxz?][0-9a-fxz?_]*/i;
var realLiteral = /(\d[\d_]*(\.\d[\d_]*)?E-?[\d_]+)|(\d[\d_]*\.\d[\d_]*)/i;
var closingBracketOrWord = /^((\w+)|[)}\]])/;
var closingBracket = /[)}\]]/;
var curPunc;
var curKeyword;
// Block openings which are closed by a matching keyword in the form of ("end" + keyword)
// E.g. "task" => "endtask"
var blockKeywords = words(
"case checker class clocking config function generate interface module package " +
"primitive program property specify sequence table task"
);
// Opening/closing pairs
var openClose = {};
for (var keyword in blockKeywords) {
openClose[keyword] = "end" + keyword;
}
openClose["begin"] = "end";
openClose["casex"] = "endcase";
openClose["casez"] = "endcase";
openClose["do" ] = "while";
openClose["fork" ] = "join;join_any;join_none";
openClose["covergroup"] = "endgroup";
for (var i in noIndentKeywords) {
var keyword = noIndentKeywords[i];
if (openClose[keyword]) {
openClose[keyword] = undefined;
}
}
// Keywords which open statements that are ended with a semi-colon
var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while");
function tokenBase(stream, state) {
var ch = stream.peek(), style;
if (hooks[ch] && (style = hooks[ch](stream, state)) != false) return style;
if (hooks.tokenBase && (style = hooks.tokenBase(stream, state)) != false)
return style;
if (/[,;:\.]/.test(ch)) {
curPunc = stream.next();
return null;
}
if (isBracketChar.test(ch)) {
curPunc = stream.next();
return "bracket";
}
// Macros (tick-defines)
if (ch == '`') {
stream.next();
if (stream.eatWhile(/[\w\$_]/)) {
return "def";
} else {
return null;
}
}
// System calls
if (ch == '$') {
stream.next();
if (stream.eatWhile(/[\w\$_]/)) {
return "meta";
} else {
return null;
}
}
// Time literals
if (ch == '#') {
stream.next();
stream.eatWhile(/[\d_.]/);
return "def";
}
// Strings
if (ch == '"') {
stream.next();
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
// Comments
if (ch == "/") {
stream.next();
if (stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
}
if (stream.eat("/")) {
stream.skipToEnd();
return "comment";
}
stream.backUp(1);
}
// Numeric literals
if (stream.match(realLiteral) ||
stream.match(decimalLiteral) ||
stream.match(binaryLiteral) ||
stream.match(octLiteral) ||
stream.match(hexLiteral) ||
stream.match(unsignedNumber) ||
stream.match(realLiteral)) {
return "number";
}
// Operators
if (stream.eatWhile(isOperatorChar)) {
return "meta";
}
// Keywords / plain variables
if (stream.eatWhile(/[\w\$_]/)) {
var cur = stream.current();
if (keywords[cur]) {
if (openClose[cur]) {
curPunc = "newblock";
}
if (statementKeywords[cur]) {
curPunc = "newstatement";
}
curKeyword = cur;
return "keyword";
}
return "variable";
}
stream.next();
return null;
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next, end = false;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) {end = true; break;}
escaped = !escaped && next == "\\";
}
if (end || !(escaped || multiLineStrings))
state.tokenize = tokenBase;
return "string";
};
}
function tokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return "comment";
}
function Context(indented, column, type, align, prev) {
this.indented = indented;
this.column = column;
this.type = type;
this.align = align;
this.prev = prev;
}
function pushContext(state, col, type) {
var indent = state.indented;
var c = new Context(indent, col, type, null, state.context);
return state.context = c;
}
function popContext(state) {
var t = state.context.type;
if (t == ")" || t == "]" || t == "}") {
state.indented = state.context.indented;
}
return state.context = state.context.prev;
}
function isClosing(text, contextClosing) {
if (text == contextClosing) {
return true;
} else {
// contextClosing may be multiple keywords separated by ;
var closingKeywords = contextClosing.split(";");
for (var i in closingKeywords) {
if (text == closingKeywords[i]) {
return true;
}
}
return false;
}
}
function buildElectricInputRegEx() {
// Reindentation should occur on any bracket char: {}()[]
// or on a match of any of the block closing keywords, at
// the end of a line
var allClosings = [];
for (var i in openClose) {
if (openClose[i]) {
var closings = openClose[i].split(";");
for (var j in closings) {
allClosings.push(closings[j]);
}
}
}
var re = new RegExp("[{}()\\[\\]]|(" + allClosings.join("|") + ")$");
return re;
}
// Interface
return {
// Regex to force current line to reindent
electricInput: buildElectricInputRegEx(),
startState: function(basecolumn) {
var state = {
tokenize: null,
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
indented: 0,
startOfLine: true
};
if (hooks.startState) hooks.startState(state);
return state;
},
token: function(stream, state) {
var ctx = state.context;
if (stream.sol()) {
if (ctx.align == null) ctx.align = false;
state.indented = stream.indentation();
state.startOfLine = true;
}
if (hooks.token) {
// Call hook, with an optional return value of a style to override verilog styling.
var style = hooks.token(stream, state);
if (style !== undefined) {
return style;
}
}
if (stream.eatSpace()) return null;
curPunc = null;
curKeyword = null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style == "comment" || style == "meta" || style == "variable") return style;
if (ctx.align == null) ctx.align = true;
if (curPunc == ctx.type) {
popContext(state);
} else if ((curPunc == ";" && ctx.type == "statement") ||
(ctx.type && isClosing(curKeyword, ctx.type))) {
ctx = popContext(state);
while (ctx && ctx.type == "statement") ctx = popContext(state);
} else if (curPunc == "{") {
pushContext(state, stream.column(), "}");
} else if (curPunc == "[") {
pushContext(state, stream.column(), "]");
} else if (curPunc == "(") {
pushContext(state, stream.column(), ")");
} else if (ctx && ctx.type == "endcase" && curPunc == ":") {
pushContext(state, stream.column(), "statement");
} else if (curPunc == "newstatement") {
pushContext(state, stream.column(), "statement");
} else if (curPunc == "newblock") {
if (curKeyword == "function" && ctx && (ctx.type == "statement" || ctx.type == "endgroup")) {
// The 'function' keyword can appear in some other contexts where it actually does not
// indicate a function (import/export DPI and covergroup definitions).
// Do nothing in this case
} else if (curKeyword == "task" && ctx && ctx.type == "statement") {
// Same thing for task
} else {
var close = openClose[curKeyword];
pushContext(state, stream.column(), close);
}
}
state.startOfLine = false;
return style;
},
indent: function(state, textAfter) {
if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass;
if (hooks.indent) {
var fromHook = hooks.indent(state);
if (fromHook >= 0) return fromHook;
}
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
var closing = false;
var possibleClosing = textAfter.match(closingBracketOrWord);
if (possibleClosing)
closing = isClosing(possibleClosing[0], ctx.type);
if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1);
else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit;
else return ctx.indented + (closing ? 0 : indentUnit);
},
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: "//"
};
});
CodeMirror.defineMIME("text/x-verilog", {
name: "verilog"
});
CodeMirror.defineMIME("text/x-systemverilog", {
name: "verilog"
});
// TL-Verilog mode.
// See tl-x.org for language spec.
// See the mode in action at makerchip.com.
// Contact: steve.hoover@redwoodeda.com
// TLV Identifier prefixes.
// Note that sign is not treated separately, so "+/-" versions of numeric identifiers
// are included.
var tlvIdentifierStyle = {
"|": "link",
">": "property", // Should condition this off for > TLV 1c.
"$": "variable",
"$$": "variable",
"?$": "qualifier",
"?*": "qualifier",
"-": "hr",
"/": "property",
"/-": "property",
"@": "variable-3",
"@-": "variable-3",
"@++": "variable-3",
"@+=": "variable-3",
"@+=-": "variable-3",
"@--": "variable-3",
"@-=": "variable-3",
"%+": "tag",
"%-": "tag",
"%": "tag",
">>": "tag",
"<<": "tag",
"<>": "tag",
"#": "tag", // Need to choose a style for this.
"^": "attribute",
"^^": "attribute",
"^!": "attribute",
"*": "variable-2",
"**": "variable-2",
"\\": "keyword",
"\"": "comment"
};
// Lines starting with these characters define scope (result in indentation).
var tlvScopePrefixChars = {
"/": "beh-hier",
">": "beh-hier",
"-": "phys-hier",
"|": "pipe",
"?": "when",
"@": "stage",
"\\": "keyword"
};
var tlvIndentUnit = 3;
var tlvTrackStatements = false;
var tlvIdentMatch = /^([~!@#\$%\^&\*-\+=\?\/\\\|'"<>]+)([\d\w_]*)/; // Matches an identifiere.
// Note that ':' is excluded, because of it's use in [:].
var tlvFirstLevelIndentMatch = /^[! ] /;
var tlvLineIndentationMatch = /^[! ] */;
var tlvCommentMatch = /^\/[\/\*]/;
// Returns a style specific to the scope at the given indentation column.
// Type is one of: "indent", "scope-ident", "before-scope-ident".
function tlvScopeStyle(state, indentation, type) {
// Begin scope.
var depth = indentation / tlvIndentUnit; // TODO: Pass this in instead.
return "tlv-" + state.tlvIndentationStyle[depth] + "-" + type;
}
// Return true if the next thing in the stream is an identifier with a mnemonic.
function tlvIdentNext(stream) {
var match;
return (match = stream.match(tlvIdentMatch, false)) && match[2].length > 0;
}
CodeMirror.defineMIME("text/x-tlv", {
name: "verilog",
hooks: {
electricInput: false,
// Return undefined for verilog tokenizing, or style for TLV token (null not used).
// Standard CM styles are used for most formatting, but some TL-Verilog-specific highlighting
// can be enabled with the definition of cm-tlv-* styles, including highlighting for:
// - M4 tokens
// - TLV scope indentation
// - Statement delimitation (enabled by tlvTrackStatements)
token: function(stream, state) {
var style = undefined;
var match; // Return value of pattern matches.
// Set highlighting mode based on code region (TLV or SV).
if (stream.sol() && ! state.tlvInBlockComment) {
// Process region.
if (stream.peek() == '\\') {
style = "def";
stream.skipToEnd();
if (stream.string.match(/\\SV/)) {
state.tlvCodeActive = false;
} else if (stream.string.match(/\\TLV/)){
state.tlvCodeActive = true;
}
}
// Correct indentation in the face of a line prefix char.
if (state.tlvCodeActive && stream.pos == 0 &&
(state.indented == 0) && (match = stream.match(tlvLineIndentationMatch, false))) {
state.indented = match[0].length;
}
// Compute indentation state:
// o Auto indentation on next line
// o Indentation scope styles
var indented = state.indented;
var depth = indented / tlvIndentUnit;
if (depth <= state.tlvIndentationStyle.length) {
// not deeper than current scope
var blankline = stream.string.length == indented;
var chPos = depth * tlvIndentUnit;
if (chPos < stream.string.length) {
var bodyString = stream.string.slice(chPos);
var ch = bodyString[0];
if (tlvScopePrefixChars[ch] && ((match = bodyString.match(tlvIdentMatch)) &&
tlvIdentifierStyle[match[1]])) {
// This line begins scope.
// Next line gets indented one level.
indented += tlvIndentUnit;
// Style the next level of indentation (except non-region keyword identifiers,
// which are statements themselves)
if (!(ch == "\\" && chPos > 0)) {
state.tlvIndentationStyle[depth] = tlvScopePrefixChars[ch];
if (tlvTrackStatements) {state.statementComment = false;}
depth++;
}
}
}
// Clear out deeper indentation levels unless line is blank.
if (!blankline) {
while (state.tlvIndentationStyle.length > depth) {
state.tlvIndentationStyle.pop();
}
}
}
// Set next level of indentation.
state.tlvNextIndent = indented;
}
if (state.tlvCodeActive) {
// Highlight as TLV.
var beginStatement = false;
if (tlvTrackStatements) {
// This starts a statement if the position is at the scope level
// and we're not within a statement leading comment.
beginStatement =
(stream.peek() != " ") && // not a space
(style === undefined) && // not a region identifier
!state.tlvInBlockComment && // not in block comment
//!stream.match(tlvCommentMatch, false) && // not comment start
(stream.column() == state.tlvIndentationStyle.length * tlvIndentUnit); // at scope level
if (beginStatement) {
if (state.statementComment) {
// statement already started by comment
beginStatement = false;
}
state.statementComment =
stream.match(tlvCommentMatch, false); // comment start
}
}
var match;
if (style !== undefined) {
// Region line.
style += " " + tlvScopeStyle(state, 0, "scope-ident")
} else if (((stream.pos / tlvIndentUnit) < state.tlvIndentationStyle.length) &&
(match = stream.match(stream.sol() ? tlvFirstLevelIndentMatch : /^ /))) {
// Indentation
style = // make this style distinct from the previous one to prevent
// codemirror from combining spans
"tlv-indent-" + (((stream.pos % 2) == 0) ? "even" : "odd") +
// and style it
" " + tlvScopeStyle(state, stream.pos - tlvIndentUnit, "indent");
// Style the line prefix character.
if (match[0].charAt(0) == "!") {
style += " tlv-alert-line-prefix";
}
// Place a class before a scope identifier.
if (tlvIdentNext(stream)) {
style += " " + tlvScopeStyle(state, stream.pos, "before-scope-ident");
}
} else if (state.tlvInBlockComment) {
// In a block comment.
if (stream.match(/^.*?\*\//)) {
// Exit block comment.
state.tlvInBlockComment = false;
if (tlvTrackStatements && !stream.eol()) {
// Anything after comment is assumed to be real statement content.
state.statementComment = false;
}
} else {
stream.skipToEnd();
}
style = "comment";
} else if ((match = stream.match(tlvCommentMatch)) && !state.tlvInBlockComment) {
// Start comment.
if (match[0] == "//") {
// Line comment.
stream.skipToEnd();
} else {
// Block comment.
state.tlvInBlockComment = true;
}
style = "comment";
} else if (match = stream.match(tlvIdentMatch)) {
// looks like an identifier (or identifier prefix)
var prefix = match[1];
var mnemonic = match[2];
if (// is identifier prefix
tlvIdentifierStyle.hasOwnProperty(prefix) &&
// has mnemonic or we're at the end of the line (maybe it hasn't been typed yet)
(mnemonic.length > 0 || stream.eol())) {
style = tlvIdentifierStyle[prefix];
if (stream.column() == state.indented) {
// Begin scope.
style += " " + tlvScopeStyle(state, stream.column(), "scope-ident")
}
} else {
// Just swallow one character and try again.
// This enables subsequent identifier match with preceding symbol character, which
// is legal within a statement. (Eg, !$reset). It also enables detection of
// comment start with preceding symbols.
stream.backUp(stream.current().length - 1);
style = "tlv-default";
}
} else if (stream.match(/^\t+/)) {
// Highlight tabs, which are illegal.
style = "tlv-tab";
} else if (stream.match(/^[\[\]{}\(\);\:]+/)) {
// [:], (), {}, ;.
style = "meta";
} else if (match = stream.match(/^[mM]4([\+_])?[\w\d_]*/)) {
// m4 pre proc
style = (match[1] == "+") ? "tlv-m4-plus" : "tlv-m4";
} else if (stream.match(/^ +/)){
// Skip over spaces.
if (stream.eol()) {
// Trailing spaces.
style = "error";
} else {
// Non-trailing spaces.
style = "tlv-default";
}
} else if (stream.match(/^[\w\d_]+/)) {
// alpha-numeric token.
style = "number";
} else {
// Eat the next char w/ no formatting.
stream.next();
style = "tlv-default";
}
if (beginStatement) {
style += " tlv-statement";
}
} else {
if (stream.match(/^[mM]4([\w\d_]*)/)) {
// m4 pre proc
style = "tlv-m4";
}
}
return style;
},
indent: function(state) {
return (state.tlvCodeActive == true) ? state.tlvNextIndent : -1;
},
startState: function(state) {
state.tlvIndentationStyle = []; // Styles to use for each level of indentation.
state.tlvCodeActive = true; // True when we're in a TLV region (and at beginning of file).
state.tlvNextIndent = -1; // The number of spaces to autoindent the next line if tlvCodeActive.
state.tlvInBlockComment = false; // True inside /**/ comment.
if (tlvTrackStatements) {
state.statementComment = false; // True inside a statement's header comment.
}
}
}
});
});