(
function
(mod) {
if
(
typeof
exports ==
"object"
&&
typeof
module ==
"object"
)
mod(require(
"../../lib/codemirror"
));
else
if
(
typeof
define ==
"function"
&& define.amd)
define([
"../../lib/codemirror"
], mod);
else
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;
function
words(str) {
var
obj = {}, words = str.split(
" "
);
for
(
var
i = 0; i < words.length; ++i) obj[words[i]] =
true
;
return
obj;
}
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"
);
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;
var
blockKeywords = words(
"case checker class clocking config function generate group interface module package"
+
"primitive program property specify sequence table task"
);
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"
;
for
(
var
i
in
noIndentKeywords) {
var
keyword = noIndentKeywords[i];
if
(openClose[keyword]) {
openClose[keyword] = undefined;
}
}
var
statementKeywords = words(
"always always_comb always_ff always_latch assert assign assume else for foreach forever if initial repeat while"
);
function
tokenBase(stream, state) {
var
ch = stream.peek();
if
(/[,;:\.]/.test(ch)) {
curPunc = stream.next();
return
null
;
}
if
(isBracketChar.test(ch)) {
curPunc = stream.next();
return
"bracket"
;
}
if
(ch ==
'`'
) {
stream.next();
if
(stream.eatWhile(/[\w\$_]/)) {
return
"def"
;
}
else
{
return
null
;
}
}
if
(ch ==
'$'
) {
stream.next();
if
(stream.eatWhile(/[\w\$_]/)) {
return
"meta"
;
}
else
{
return
null
;
}
}
if
(ch ==
'#'
) {
stream.next();
stream.eatWhile(/[\d_.]/);
return
"def"
;
}
if
(ch ==
'"'
) {
stream.next();
state.tokenize = tokenString(ch);
return
state.tokenize(stream, state);
}
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 mulitple 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) {
return {
tokenize: null,
context: new Context((basecolumn || 0) - indentUnit, 0, "
top
", false),
indented: 0,
startOfLine: true
};
},
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 (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
") {
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;
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: "
",
lineComment: "
};
});
CodeMirror.defineMIME("text/x-verilog
", {
name: "
verilog
"
});
CodeMirror.defineMIME("
text/x-systemverilog
", {
name: "
systemverilog"
});
});