diff --git a/README.md b/README.md index 82240b9..66a5b8d 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ VHDL formatter web online written in javascript - bugfix "remove non-comment code by mistake" - add `tests` folder, improve the project management +- support extended identifier (backslash names) +- fix exponential notation ### 2.2 [2018-10-16] diff --git a/VHDLFormatter.js b/VHDLFormatter.js index 434e02d..60b3cec 100644 --- a/VHDLFormatter.js +++ b/VHDLFormatter.js @@ -1,9 +1,11 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); let isTesting = false; -const ILCommentPrefix = "@@comments"; -const ILQuotesPrefix = "@@quotes"; -const ILSingleQuotesPrefix = "@@singlequotes"; +const ILEscape = "@@"; +const ILCommentPrefix = ILEscape + "comments"; +const ILQuotesPrefix = ILEscape + "quotes"; +const ILSingleQuotesPrefix = ILEscape + "singlequotes"; +const ILBackslashesPrefix = ILEscape + "backslash"; var FormatMode; (function (FormatMode) { FormatMode[FormatMode["Default"] = 0] = "Default"; @@ -150,17 +152,19 @@ function MixLetters(input) { } return arr.join(""); } -function EscapeComments(arr, comments, commentIndex) { +function EscapeComments(arr) { + var comments = []; + var count = 0; for (var i = 0; i < arr.length; i++) { - let line = arr[i]; + var line = arr[i]; var commentStartIndex = line.indexOf("--"); if (commentStartIndex >= 0) { comments.push(line.substr(commentStartIndex)); - arr[i] = line.substr(0, commentStartIndex) + ILCommentPrefix + commentIndex; - commentIndex++; + arr[i] = line.substr(0, commentStartIndex) + ILCommentPrefix + count; + count++; } } - return commentIndex; + return comments; } function ToLowerCases(arr) { for (var i = 0; i < arr.length; i++) { @@ -243,14 +247,14 @@ function beautify(input, settings) { input = input.replace(/\r\n/g, "\n"); input = input.replace(/\n/g, "\r\n"); var arr = input.split("\r\n"); - var comments = [], commentsIndex = 0; - commentsIndex = EscapeComments(arr, comments, commentsIndex); + var comments = EscapeComments(arr); + var backslashes = escapeBackslashes(arr); RemoveLeadingWhitespaces(arr); input = arr.join("\r\n"); if (settings.RemoveComments) { input = input.replace(/\r\n[ \t]*@@comments[0-9]+[ \t]*\r\n/g, '\r\n'); input = input.replace(/@@comments[0-9]+/g, ''); - commentsIndex = 0; + comments = []; } input = RemoveExtraNewLines(input); input = input.replace(/[\t ]+/g, ' '); @@ -274,9 +278,10 @@ function beautify(input, settings) { arr = input.split("\r\n"); ApplyNoNewLineAfter(arr, settings.NewLineSettings.noNewLineAfter); input = arr.join("\r\n"); - //new input = input.replace(/([a-zA-Z0-9\); ])\);(@@comments[0-9]+)?@@end/g, '$1\r\n);$2@@end'); input = input.replace(/[ ]?([&=:\-<>\+|\*])[ ]?/g, ' $1 '); + // Fix reals in expoential format broken by previous step + input = input.replace(/(\d+e) +([+\-]) +(\d+)/g, '$1$2$3'); input = input.replace(/[ ]?([,])[ ]?/g, '$1 '); input = input.replace(/[ ]?(['"])(THEN)/g, '$1 $2'); input = input.replace(/[ ]?(\?)?[ ]?(<|:|>|\/)?[ ]+(=)?[ ]?/g, ' $1$2$3 '); @@ -300,20 +305,35 @@ function beautify(input, settings) { arr = FormattedLineToString(result, settings.Indentation); input = arr.join("\r\n"); input = SetKeywordCase(input, settings.KeywordCase, KeyWords, TypeNames); - for (var k = 0; k < quotes.length; k++) { - input = input.replace(ILQuotesPrefix + k, quotes[k]); - } - for (var k = 0; k < singleQuotes.length; k++) { - input = input.replace(ILSingleQuotesPrefix + k, singleQuotes[k]); - } - for (var k = 0; k < commentsIndex; k++) { - input = input.replace(ILCommentPrefix + k, comments[k]); - } + input = replaceEscapedWords(input, quotes, ILQuotesPrefix); + input = replaceEscapedWords(input, singleQuotes, ILSingleQuotesPrefix); + input = replaceEscapedWords(input, comments, ILCommentPrefix); + input = replaceEscapedWords(input, backslashes, ILBackslashesPrefix); input = input.replace(/@@semicolon/g, ";"); input = input.replace(/@@[a-z]+/g, ""); return input; } exports.beautify = beautify; +function replaceEscapedWords(input, arr, prefix) { + for (var i = 0; i < arr.length; i++) { + input = input.replace(prefix + i, arr[i]); + } + return input; +} +function escapeBackslashes(arr) { + var escaped = []; + var count = 0; + for (var i = 0; i < arr.length; i++) { + var sequence = arr[i].match(/\\[^\\]+\\/g); + if (sequence != null) { + for (var j = 0; j < sequence.length; j++) { + arr[i] = arr[i].replace(sequence[j], ILBackslashesPrefix + count); + escaped[count++] = sequence[j]; + } + } + } + return escaped; +} function RemoveLeadingWhitespaces(arr) { for (var i = 0; i < arr.length; i++) { arr[i] = arr[i].replace(/^\s+/, ""); diff --git a/VHDLFormatter.ts b/VHDLFormatter.ts index a7ab9b5..7ce3ae3 100644 --- a/VHDLFormatter.ts +++ b/VHDLFormatter.ts @@ -1,7 +1,9 @@ let isTesting = false; -const ILCommentPrefix = "@@comments"; -const ILQuotesPrefix = "@@quotes"; -const ILSingleQuotesPrefix = "@@singlequotes"; +const ILEscape = "@@"; +const ILCommentPrefix = ILEscape + "comments"; +const ILQuotesPrefix = ILEscape + "quotes"; +const ILSingleQuotesPrefix = ILEscape + "singlequotes"; +const ILBackslashesPrefix = ILEscape + "backslash"; enum FormatMode { Default, @@ -183,17 +185,19 @@ function MixLetters(input: string) { return arr.join(""); } -function EscapeComments(arr: Array, comments: Array, commentIndex: number): number { +function EscapeComments(arr: Array): Array { + var comments = []; + var count = 0; for (var i = 0; i < arr.length; i++) { - let line: string = arr[i]; + var line: string = arr[i]; var commentStartIndex = line.indexOf("--"); if (commentStartIndex >= 0) { comments.push(line.substr(commentStartIndex)); - arr[i] = line.substr(0, commentStartIndex) + ILCommentPrefix + commentIndex; - commentIndex++ + arr[i] = line.substr(0, commentStartIndex) + ILCommentPrefix + count; + count++; } } - return commentIndex + return comments } function ToLowerCases(arr: Array) { @@ -295,16 +299,15 @@ export function beautify(input: string, settings: BeautifierSettings) { input = input.replace(/\r\n/g, "\n"); input = input.replace(/\n/g, "\r\n"); var arr = input.split("\r\n"); - var comments = [], - commentsIndex = 0; - commentsIndex = EscapeComments(arr, comments, commentsIndex); + var comments = EscapeComments(arr); + var backslashes = escapeBackslashes(arr); RemoveLeadingWhitespaces(arr); input = arr.join("\r\n"); if (settings.RemoveComments) { input = input.replace(/\r\n[ \t]*@@comments[0-9]+[ \t]*\r\n/g, '\r\n'); input = input.replace(/@@comments[0-9]+/g, ''); - commentsIndex = 0; + comments = []; } input = RemoveExtraNewLines(input); @@ -333,9 +336,9 @@ export function beautify(input: string, settings: BeautifierSettings) { ApplyNoNewLineAfter(arr, settings.NewLineSettings.noNewLineAfter); input = arr.join("\r\n"); - //new input = input.replace(/([a-zA-Z0-9\); ])\);(@@comments[0-9]+)?@@end/g, '$1\r\n);$2@@end'); input = input.replace(/[ ]?([&=:\-<>\+|\*])[ ]?/g, ' $1 '); + input = input.replace(/(\d+e) +([+\-]) +(\d+)/g, '$1$2$3');// Fix exponential notation format broken by previous step input = input.replace(/[ ]?([,])[ ]?/g, '$1 '); input = input.replace(/[ ]?(['"])(THEN)/g, '$1 $2'); input = input.replace(/[ ]?(\?)?[ ]?(<|:|>|\/)?[ ]+(=)?[ ]?/g, ' $1$2$3 '); @@ -361,23 +364,38 @@ export function beautify(input: string, settings: BeautifierSettings) { input = arr.join("\r\n"); input = SetKeywordCase(input, settings.KeywordCase, KeyWords, TypeNames); - for (var k = 0; k < quotes.length; k++) { - input = input.replace(ILQuotesPrefix + k, quotes[k]); - } - - for (var k = 0; k < singleQuotes.length; k++) { - input = input.replace(ILSingleQuotesPrefix + k, singleQuotes[k]); - } - - for (var k = 0; k < commentsIndex; k++) { - input = input.replace(ILCommentPrefix + k, comments[k]); - } + input = replaceEscapedWords(input, quotes, ILQuotesPrefix); + input = replaceEscapedWords(input, singleQuotes, ILSingleQuotesPrefix); + input = replaceEscapedWords(input, comments, ILCommentPrefix); + input = replaceEscapedWords(input, backslashes, ILBackslashesPrefix); input = input.replace(/@@semicolon/g, ";"); input = input.replace(/@@[a-z]+/g, ""); return input; } +function replaceEscapedWords(input: string, arr: Array, prefix: string): string { + for (var i = 0; i < arr.length; i++) { + input = input.replace(prefix + i, arr[i]); + } + return input; +} + +function escapeBackslashes(arr: Array) { + var escaped = []; + var count = 0; + for (var i = 0; i < arr.length; i++) { + var sequence = arr[i].match(/\\[^\\]+\\/g); + if (sequence != null) { + for (var j = 0; j < sequence.length; j++) { + arr[i] = arr[i].replace(sequence[j], ILBackslashesPrefix + count); + escaped[count++] = sequence[j]; + } + } + } + return escaped; +} + function RemoveLeadingWhitespaces(arr: Array) { for (var i = 0; i < arr.length; i++) { arr[i] = arr[i].replace(/^\s+/, ""); diff --git a/tests/VHDLFormatterUnitTests.ts b/tests/VHDLFormatterUnitTests.ts index f3615fc..ea39a55 100644 --- a/tests/VHDLFormatterUnitTests.ts +++ b/tests/VHDLFormatterUnitTests.ts @@ -909,6 +909,8 @@ function IntegrationTest() { IntegrationTest68(); IntegrationTest69(); IntegrationTest70(); + IntegrationTest71(); + IntegrationTest72(); } function IntegrationTest23() { @@ -1313,7 +1315,7 @@ function IntegrationTest66() { let input = 'component a is\r\n generic (b\r\n );\r\n port (\r\n c\r\n );\r\n end component;\r\n-- anything1\r\n-- anything2'; let expected = 'COMPONENT a IS\r\n GENERIC (\r\n b\r\n );\r\n PORT (\r\n c\r\n );\r\nEND COMPONENT;\r\n-- anything1\r\n-- anything2'; let actual = beautify(input, settings); - assertAndCountTest("port map no new line 2", expected, actual); + assertAndCountTest("component generic", expected, actual); } function IntegrationTest67() { @@ -1348,6 +1350,22 @@ function IntegrationTest70() { assertAndCountTest("multiline assignment", expected, actual); } +function IntegrationTest71() { + let settings = GetDefaultSettings(); + let input = 'VARIABLE \\#$)!?\\ : INTEGER;\r\nVARIABLE \\try this in verilog\\ : BIT;\r\nVARIABLE \\Buffer\\ : BIT;'; + let expected = 'VARIABLE \\#$)!?\\ : INTEGER;\r\nVARIABLE \\try this in verilog\\ : BIT;\r\nVARIABLE \\Buffer\\ : BIT;'; + let actual = beautify(input, settings); + assertAndCountTest("backslash, extended indentifier", expected, actual); +} + +function IntegrationTest72() { + let settings = GetDefaultSettings(); + let input = 'test := 12e+6'; + let expected = 'test := 12e+6'; + let actual = beautify(input, settings); + assertAndCountTest("scientific notation", expected, actual); +} + function GetDefaultSettings() { let new_line_after_symbols = new NewLineSettings(); new_line_after_symbols.newLineAfter = ["then", ";"];