From b0df2d1a3afabe2b21a7de937953af6ba95a2ffe Mon Sep 17 00:00:00 2001 From: Stephen M Moraco Date: Tue, 2 Jan 2024 15:48:46 -0700 Subject: [PATCH] fixes due to findings by Grover (P1 testing) - Clean up Syntax recognition of block names - Statements like 'DAT{{' caused problems (exposed other potential issues, which are now fixed) - Clean up Semantic highlighting of code in presence of statements like 'DAT{{' - P2 BUGFIX repair VAR name detection when storage type not provided --- spin2/CHANGELOG.md | 8 + .../spin/_method_signature_demo.spin | 2 +- .../TEST_LANG_SERVER/spin2/221206-fixes.spin2 | 3 +- ...30-fixes.spin2 => chk_dupe_declares.spin2} | 0 .../spin2/debug_coloring_examples.spin2 | 13 +- .../spin2/docs-spin2-language.spin2 | 6 +- spin2/client/src/spin.code.utils.ts | 2 +- spin2/package.json | 2 +- spin2/scripts/LIVE-package.json | 2 +- spin2/scripts/TEST-package.json | 2 +- .../server/src/parser/spin.extension.utils.ts | 2 +- .../src/parser/spin.semantic.findings.ts | 2 +- .../parser/spin1.documentSemanticParser.ts | 150 +-- .../src/parser/spin1.documentSymbolParser.ts | 12 +- .../parser/spin2.documentSemanticParser.ts | 213 ++-- .../src/parser/spin2.documentSymbolParser.ts | 10 +- spin2/server/src/parser/spin2.utils.ts | 16 + .../syntaxes/spin1.tmLanguage.YAML-tmLanguage | 680 ++++++------- spin2/syntaxes/spin1.tmLanguage.json | 14 +- .../syntaxes/spin2.tmLanguage.YAML-tmLanguage | 955 ++++++++---------- spin2/syntaxes/spin2.tmLanguage.json | 30 +- 21 files changed, 1061 insertions(+), 1063 deletions(-) rename spin2/TEST_LANG_SERVER/spin2/{231230-fixes.spin2 => chk_dupe_declares.spin2} (100%) diff --git a/spin2/CHANGELOG.md b/spin2/CHANGELOG.md index e8cd899..288da33 100644 --- a/spin2/CHANGELOG.md +++ b/spin2/CHANGELOG.md @@ -18,6 +18,14 @@ Possible next additions: - Add new-file templates as Snippets - Add additional Snippets as the community identifies them +## [2.2.12] 2024-01-02 + +Update P1 and P2 + +- Clean up Syntax recognition of block names - Statements like 'DAT{{' caused problems (exposed other potential issues, which are now fixed) +- Clean up Semantic highlighting of code in presence of statements like 'DAT{{' +- P2 BUGFIX repair VAR name detection when storage type not provided + ## [2.2.11] 2023-12-30 Update P2 Only diff --git a/spin2/TEST_LANG_SERVER/spin/_method_signature_demo.spin b/spin2/TEST_LANG_SERVER/spin/_method_signature_demo.spin index c0f44f3..0d18ed0 100644 --- a/spin2/TEST_LANG_SERVER/spin/_method_signature_demo.spin +++ b/spin2/TEST_LANG_SERVER/spin/_method_signature_demo.spin @@ -1,6 +1,6 @@ CON -PUB main() : ok +PUB main : ok '' our main entry point '' '' @returns ok - return T/F where T means start succeeded diff --git a/spin2/TEST_LANG_SERVER/spin2/221206-fixes.spin2 b/spin2/TEST_LANG_SERVER/spin2/221206-fixes.spin2 index 97b5dbc..1a31467 100644 --- a/spin2/TEST_LANG_SERVER/spin2/221206-fixes.spin2 +++ b/spin2/TEST_LANG_SERVER/spin2/221206-fixes.spin2 @@ -55,7 +55,6 @@ pn_ res 1 'pin(s) ' ----------------------------------------------------------------- CON - _clkfreq = 100_000_000 debug_main 'single-step through main code <---- BAD debug_main is NOT a constant debug_coginit 'single-step through main code <---- BAD debug_main is NOT a constant @@ -105,7 +104,7 @@ DAT launch_spin loc ptrb,#\$80000 'point to zeroes in empty hub space ' ----------------------------------------------------------------- -CON _clkfreq = 200_000_000 +CON 'debug_main 'uncomment to single-step through everything, even COGINITs 'debug_coginit 'uncomment to break on COGINITs diff --git a/spin2/TEST_LANG_SERVER/spin2/231230-fixes.spin2 b/spin2/TEST_LANG_SERVER/spin2/chk_dupe_declares.spin2 similarity index 100% rename from spin2/TEST_LANG_SERVER/spin2/231230-fixes.spin2 rename to spin2/TEST_LANG_SERVER/spin2/chk_dupe_declares.spin2 diff --git a/spin2/TEST_LANG_SERVER/spin2/debug_coloring_examples.spin2 b/spin2/TEST_LANG_SERVER/spin2/debug_coloring_examples.spin2 index fda09eb..6ddaf4f 100644 --- a/spin2/TEST_LANG_SERVER/spin2/debug_coloring_examples.spin2 +++ b/spin2/TEST_LANG_SERVER/spin2/debug_coloring_examples.spin2 @@ -48,7 +48,6 @@ PUB go() | i ' ----------------- ' SCOPE (2) -CON _clkfreq = 100_000_000 PUB go2() | a, af, b, bf debug(`SCOPE MyScope) @@ -63,7 +62,6 @@ PUB go2() | a, af, b, bf ' ----------------- ' TERM (1) -CON _clkfreq = 10_000_000 PUB go3() | i debug(`TERM MyTerm SIZE 9 1 TEXTSIZE 40) @@ -75,7 +73,6 @@ PUB go3() | i ' ----------------- ' LOGIC (1) -CON _clkfreq = 10_000_000 PUB go4() | i debug(`LOGIC MyLogic SAMPLES 32 'Low' 3 'Mid' 2 'High') debug(`MyLogic TRIGGER $07 $04 HOLDOFF 2) @@ -87,14 +84,13 @@ PUB go4() | i ' ----------------- ' LOGIC (2) -CON _clkfreq = 333_333_333 'go really fast, 3ns clock period - rxpin = 24 +CON rxpin = 24 txpin = rxpin + 1 samps = 32 bufflongs = samps / 16 xmode = $D0800000 + rxpin << 17 + samps 'streamer mode -VAR buff[bufflongs] +VAR buff[bufflongs + samps] PUB go5() | i, buffaddr @@ -125,7 +121,6 @@ repeat ' ----------------- ' FFT -CON _clkfreq = 100_000_000 PUB go6() | i, j, k ' Set up FFT debug(`FFT MyFFT SIZE 250 200 SAMPLES 2048 0 127 RATE 256 LOGSCALE COLOR YELLOW 4 YELLOW 5) @@ -143,7 +138,6 @@ PUB go6() | i, j, k ' ----------------- ' Spectro -CON _clkfreq = 100_000_000 PUB go7() | i, j, k ' Set up SPECTRO debug(`SPECTRO MySpectro SAMPLES 2048 0 236 RANGE 1000 LUMA8X GREEN) @@ -160,7 +154,6 @@ PUB go7() | i, j, k ' ----------------- ' Plot -CON _clkfreq = 10_000_000 PUB go8(): i, j, k debug(`plot myplot size 400 480 backcolor white update) debug(`myplot origin 200 200 polar -64 -16) @@ -189,7 +182,6 @@ PUB go8(): i, j, k ' ----------------- ' Bitmap -CON _clkfreq = 10_000_000 PUB go9() | i debug(`bitmap MyBitmap SIZE 32 16 DOTSIZE 8 LUT2 LONGS_2BIT) debug(`MyBitmap TRACE 14 LUTCOLORS WHITE RED BLUE YELLOW 6) @@ -233,7 +225,6 @@ flag long %%3333333333333330 ' ----------------- ' Bitmap (2) -CON _clkfreq = 100_000_000 PUB go10() | i debug(`bitmap a title 'LUT1' pos 100 100 trace 2 lut1 longs_1bit alt) debug(`bitmap b title 'LUT2' pos 370 100 trace 2 lut2 longs_2bit alt) diff --git a/spin2/TEST_LANG_SERVER/spin2/docs-spin2-language.spin2 b/spin2/TEST_LANG_SERVER/spin2/docs-spin2-language.spin2 index 2583c06..b1eb882 100644 --- a/spin2/TEST_LANG_SERVER/spin2/docs-spin2-language.spin2 +++ b/spin2/TEST_LANG_SERVER/spin2/docs-spin2-language.spin2 @@ -35,12 +35,12 @@ CON ' ----------------------------------------------------------------------------- CON_NAME = CLKMODE - CON_NAME = CLKFREQ + CON_NAME2 = CLKFREQ CON - CON_NAME = CLKMODE - CON_NAME = CLKFREQ + CON_NAME3 = CLKMODE + CON_NAME4 = CLKFREQ PUB something() diff --git a/spin2/client/src/spin.code.utils.ts b/spin2/client/src/spin.code.utils.ts index d578b84..5c8e405 100644 --- a/spin2/client/src/spin.code.utils.ts +++ b/spin2/client/src/spin.code.utils.ts @@ -112,7 +112,7 @@ export class SpinCodeUtils { } } if (startStatus) { - this._logMessage("** isSectStart line=[" + line + "]"); + this._logMessage(`** isSectStart codeUt line=[${line}]`); } return { isSectionStart: startStatus, diff --git a/spin2/package.json b/spin2/package.json index e7a2403..57df9bd 100644 --- a/spin2/package.json +++ b/spin2/package.json @@ -5,7 +5,7 @@ "icon": "images/Propeller.ico", "author": "IronSheep", "license": "MIT", - "version": "2.2.11", + "version": "2.2.12", "repository": { "type": "git", "url": "https://github.com/ironsheep/P2-vscode-langserv-extension" diff --git a/spin2/scripts/LIVE-package.json b/spin2/scripts/LIVE-package.json index e7a2403..57df9bd 100644 --- a/spin2/scripts/LIVE-package.json +++ b/spin2/scripts/LIVE-package.json @@ -5,7 +5,7 @@ "icon": "images/Propeller.ico", "author": "IronSheep", "license": "MIT", - "version": "2.2.11", + "version": "2.2.12", "repository": { "type": "git", "url": "https://github.com/ironsheep/P2-vscode-langserv-extension" diff --git a/spin2/scripts/TEST-package.json b/spin2/scripts/TEST-package.json index cb38897..0e985c4 100644 --- a/spin2/scripts/TEST-package.json +++ b/spin2/scripts/TEST-package.json @@ -4,7 +4,7 @@ "description": "P1 and P2 Spin/Pasm Syntax/Semantic Highlighting w/Code Outline, Object Outline and Custom tabbing support", "author": "IronSheep", "license": "MIT", - "version": "2.2.11", + "version": "2.2.12", "repository": { "type": "git", "url": "https://github.com/ironsheep/P2-vscode-langserv-extension" diff --git a/spin2/server/src/parser/spin.extension.utils.ts b/spin2/server/src/parser/spin.extension.utils.ts index 149cbd7..7a0ac2e 100644 --- a/spin2/server/src/parser/spin.extension.utils.ts +++ b/spin2/server/src/parser/spin.extension.utils.ts @@ -78,7 +78,7 @@ export class ExtensionUtils { } } if (startStatus) { - this._logMessage("** isSectStart line=[" + line + "]"); + this._logMessage(`** isSectStart extUt line=[${line}]`); } return { isSectionStart: startStatus, diff --git a/spin2/server/src/parser/spin.semantic.findings.ts b/spin2/server/src/parser/spin.semantic.findings.ts index 4c448b8..f351b70 100644 --- a/spin2/server/src/parser/spin.semantic.findings.ts +++ b/spin2/server/src/parser/spin.semantic.findings.ts @@ -1600,7 +1600,7 @@ export class DocumentFindings { } public setOutlineSymbol(newSymbol: OutLineSymbol) { - this._logMessage(` OUTLINE setOutlineSymbol(${newSymbol.label}) = ${newSymbol.kind}`); + this._logMessage(` OUTLINE setOutlineSymbol(${newSymbol.label}) = ${newSymbol.kind()}`); this.outlineSymbols.push(newSymbol); } diff --git a/spin2/server/src/parser/spin1.documentSemanticParser.ts b/spin2/server/src/parser/spin1.documentSemanticParser.ts index 41e3a22..9e7d9b1 100644 --- a/spin2/server/src/parser/spin1.documentSemanticParser.ts +++ b/spin2/server/src/parser/spin1.documentSemanticParser.ts @@ -148,11 +148,14 @@ export class Spin1DocumentSemanticParser { const trimmedLine = line.trim(); const lineWOutInlineComments: string = this.parseUtils.getLineWithoutInlineComments(line); const bHaveLineToProcess: boolean = lineWOutInlineComments.length > 0; - const trimmedNonCommentLine: string = bHaveLineToProcess ? this.parseUtils.getRemainderWOutTrailingTicComment(0, lineWOutInlineComments).trimStart() : ""; + var trimmedNonCommentLine: string = bHaveLineToProcess ? this.parseUtils.getRemainderWOutTrailingTicComment(0, lineWOutInlineComments).trimStart() : ""; const offSet: number = trimmedNonCommentLine.length > 0 ? line.indexOf(trimmedNonCommentLine) + 1 : line.indexOf(trimmedLine) + 1; const tempComment = line.substring(trimmedNonCommentLine.length + offSet).trim(); this.rightEdgeComment = tempComment.length > 0 ? tempComment : undefined; const sectionStatus = this.extensionUtils.isSectionStartLine(line); + if (sectionStatus.isSectionStart) { + trimmedNonCommentLine = trimmedNonCommentLine.substring(3); + } const lineParts: string[] = trimmedNonCommentLine.split(/[ \t]/).filter(Boolean); // special blocks of doc-comment and non-doc comment lines handling @@ -516,14 +519,18 @@ export class Spin1DocumentSemanticParser { const trimmedLine = line.trim(); const lineWOutInlineComments: string = this.parseUtils.getLineWithoutInlineComments(line); const bHaveLineToProcess: boolean = lineWOutInlineComments.length > 0; - const trimmedNonCommentLine: string = bHaveLineToProcess ? this.parseUtils.getRemainderWOutTrailingTicComment(0, lineWOutInlineComments).trimStart() : ""; + let trimmedNonCommentLine: string = bHaveLineToProcess ? this.parseUtils.getRemainderWOutTrailingTicComment(0, lineWOutInlineComments).trimStart() : ""; const sectionStatus = this.extensionUtils.isSectionStartLine(line); + if (sectionStatus.isSectionStart) { + trimmedNonCommentLine = trimmedNonCommentLine.substring(3); + } const lineParts: string[] = trimmedNonCommentLine.split(/[ \t]/).filter(Boolean); if (currState == eParseState.inMultiLineDocComment) { // in multi-line doc-comment, hunt for end '}}' to exit // ALLOW {cmt}, {{cmt}} on same line without closing! - let closingOffset = lineWOutInlineComments.indexOf("}}"); + //this._logMessage(` hunt for '}}' Ln#${lineNbr} trimmedNonCommentLine=[${trimmedNonCommentLine}]`); + let closingOffset = trimmedNonCommentLine.indexOf("}}"); if (closingOffset != -1) { // have close, comment ended currState = priorState; @@ -535,11 +542,11 @@ export class Spin1DocumentSemanticParser { } else if (currState == eParseState.inMultiLineComment) { // in multi-line non-doc-comment, hunt for end '}' to exit // ALLOW {...} on same line without closing! - this._logMessage(" hunt for '}' Ln#" + lineNbr + " trimmedLine=[" + trimmedLine + "]"); + //this._logMessage(` hunt for '}' Ln#${lineNbr} lineWOutInlineComments=[${lineWOutInlineComments}]`); const closingOffset: number = lineWOutInlineComments.indexOf("}"); if (closingOffset != -1) { // have close, comment ended - this._logMessage(" FOUND '}' Ln#" + lineNbr + " trimmedLine=[" + trimmedLine + "]"); + this._logMessage(` FOUND '}' Ln#${lineNbr} trimmedLine=[${trimmedLine}]`); currState = priorState; this._logMessage(`* Ln#${lineNbr} foundMuli end-} exit MultiLineComment`); } else { @@ -552,6 +559,70 @@ export class Spin1DocumentSemanticParser { tokenSet.push(newToken); }); continue; + } else if (trimmedLine.startsWith("''")) { + // process single line doc comment + // DO NOTHING Let Syntax highlighting do this + } else if (trimmedLine.startsWith("'")) { + // process single line non-doc comment + // DO NOTHING Let Syntax highlighting do this + } else if (trimmedNonCommentLine.startsWith("{{")) { + // process multi-line doc comment + let openingOffset = trimmedNonCommentLine.indexOf("{{"); + const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); + if (closingOffset != -1) { + // is single-line {{comment}}, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + currState = eParseState.inMultiLineDocComment; + this._logMessage(`* Ln#${lineNbr} foundMuli srt-{{ starting MultiLineDocComment`); + // DO NOTHING Let Syntax highlighting do this + } + continue; + } else if (trimmedNonCommentLine.startsWith("{")) { + // process possible multi-line non-doc comment + // do we have a close on this same line? + let openingOffset = trimmedNonCommentLine.indexOf("{"); + const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); + if (closingOffset != -1) { + // is single line {comment}, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + currState = eParseState.inMultiLineComment; + this._logMessage(`* Ln#${lineNbr} foundMuli srt-{ starting MultiLineComment`); + // DO NOTHING Let Syntax highlighting do this + } + continue; + } else if (trimmedNonCommentLine.includes("{{")) { + // process multi-line doc comment + let openingOffset = trimmedNonCommentLine.indexOf("{{"); + const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); + if (closingOffset != -1) { + // is single line {{comment}}, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + currState = eParseState.inMultiLineDocComment; + this._logMessage(`* Ln#${lineNbr} foundMuli mid-{{ starting MultiLineDocComment`); + // DO NOTHING Let Syntax highlighting do this + } + // don't continue there might be some text to process before the {{ + } else if (trimmedNonCommentLine.includes("{")) { + // process possible multi-line non-doc comment + // do we have a close on this same line? + let openingOffset = trimmedNonCommentLine.indexOf("{"); + const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); + if (closingOffset != -1) { + // is single line comment, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + currState = eParseState.inMultiLineComment; + this._logMessage(`* Ln#${lineNbr} foundMuli mid-{ starting MultiLineComment`); + // DO NOTHING Let Syntax highlighting do this + } + // don't continue there might be some text to process before the {{ } else if (sectionStatus.isSectionStart) { currState = sectionStatus.inProgressStatus; this._logState(" -- Ln#" + lineNbr + " currState=[" + currState + "]"); @@ -638,70 +709,6 @@ export class Spin1DocumentSemanticParser { }); } } - } else if (trimmedLine.startsWith("''")) { - // process single line doc comment - // DO NOTHING Let Syntax highlighting do this - } else if (trimmedLine.startsWith("'")) { - // process single line non-doc comment - // DO NOTHING Let Syntax highlighting do this - } else if (trimmedNonCommentLine.startsWith("{{")) { - // process multi-line doc comment - let openingOffset = trimmedNonCommentLine.indexOf("{{"); - const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); - if (closingOffset != -1) { - // is single-line {{comment}}, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - currState = eParseState.inMultiLineDocComment; - this._logMessage(`* Ln#${lineNbr} foundMuli srt-{{ starting MultiLineDocComment`); - // DO NOTHING Let Syntax highlighting do this - } - continue; - } else if (trimmedNonCommentLine.startsWith("{")) { - // process possible multi-line non-doc comment - // do we have a close on this same line? - let openingOffset = trimmedNonCommentLine.indexOf("{"); - const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); - if (closingOffset != -1) { - // is single line {comment}, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - currState = eParseState.inMultiLineComment; - this._logMessage(`* Ln#${lineNbr} foundMuli srt-{ starting MultiLineComment`); - // DO NOTHING Let Syntax highlighting do this - } - continue; - } else if (trimmedNonCommentLine.includes("{{")) { - // process multi-line doc comment - let openingOffset = trimmedNonCommentLine.indexOf("{{"); - const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); - if (closingOffset != -1) { - // is single line {{comment}}, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - currState = eParseState.inMultiLineDocComment; - this._logMessage(`* Ln#${lineNbr} foundMuli mid-{{ starting MultiLineDocComment`); - // DO NOTHING Let Syntax highlighting do this - } - // don't continue there might be some text to process before the {{ - } else if (trimmedNonCommentLine.includes("{")) { - // process possible multi-line non-doc comment - // do we have a close on this same line? - let openingOffset = trimmedNonCommentLine.indexOf("{"); - const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); - if (closingOffset != -1) { - // is single line comment, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - currState = eParseState.inMultiLineComment; - this._logMessage(`* Ln#${lineNbr} foundMuli mid-{ starting MultiLineComment`); - // DO NOTHING Let Syntax highlighting do this - } - // don't continue there might be some text to process before the {{ } else if (currState == eParseState.inCon) { // process a line in a constant section if (bHaveLineToProcess) { @@ -2337,7 +2344,7 @@ export class Spin1DocumentSemanticParser { } } } - currentOffset = nameOffset + 1; + currentOffset = nameOffset + variableNamePart.length; } } else { // have simple target name, no [] @@ -2420,9 +2427,8 @@ export class Spin1DocumentSemanticParser { } } } - currentOffset = nameOffset + 1; + currentOffset = nameOffset + cleanedVariableName.length; } - currentOffset = nameOffset + 1; } } // ------------------------------------------- diff --git a/spin2/server/src/parser/spin1.documentSymbolParser.ts b/spin2/server/src/parser/spin1.documentSymbolParser.ts index 32ffde6..a145ce8 100644 --- a/spin2/server/src/parser/spin1.documentSymbolParser.ts +++ b/spin2/server/src/parser/spin1.documentSymbolParser.ts @@ -67,6 +67,11 @@ export class Spin1DocumentSymbolParser { continue; } + const sectionStatus = this.extensionUtils.isSectionStartLine(line); + if (sectionStatus.isSectionStart) { + nonCommentLine = nonCommentLine.substring(3); + } + // skip all {{ --- }} multi-line doc comments if (currState == eParseState.inMultiLineDocComment) { // in multi-line doc-comment, hunt for end '}}' to exit @@ -128,13 +133,12 @@ export class Spin1DocumentSymbolParser { } } - const sectionStatus = this.extensionUtils.isSectionStartLine(line); if (sectionStatus.isSectionStart) { currState = sectionStatus.inProgressStatus; } if (line.length > 2) { - const lineParts: string[] = linePrefix.split(/[ \t]/).filter(Boolean); + const lineParts: string[] = linePrefix.split(/[ \t\{\']/).filter(Boolean); linePrefix = lineParts.length > 0 ? lineParts[0].toUpperCase() : ""; // the only form of comment we care about here is block comment after section name (e.g., "CON { text }") // NEW and let's add the use of ' comment too @@ -285,9 +289,9 @@ export class Spin1DocumentSymbolParser { // get line parts - we only care about first one const dataDeclNonCommentStr = this.parseUtils.getNonCommentLineRemainder(currentOffset, line); let lineParts: string[] = this.parseUtils.getNonWhiteNParenLineParts(dataDeclNonCommentStr); - //this._logMessage("- Oln GetDatDecl lineParts=[" + lineParts + "](" + lineParts.length + ")"); + this._logMessage(`- Oln GetDatDecl lineParts=[${lineParts}](${lineParts.length})`); let haveMoreThanDat: boolean = lineParts.length > 1 && lineParts[0].toUpperCase() == "DAT"; - if (haveMoreThanDat || lineParts[0].toUpperCase() != "DAT") { + if (haveMoreThanDat || (lineParts.length > 0 && lineParts[0].toUpperCase() != "DAT")) { // remember this object name so we can annotate a call to it let nameIndex: number = 0; let typeIndex: number = 1; diff --git a/spin2/server/src/parser/spin2.documentSemanticParser.ts b/spin2/server/src/parser/spin2.documentSemanticParser.ts index e3abbdf..22dabbd 100644 --- a/spin2/server/src/parser/spin2.documentSemanticParser.ts +++ b/spin2/server/src/parser/spin2.documentSemanticParser.ts @@ -184,6 +184,8 @@ export class Spin2DocumentSemanticParser { const lineNbr: number = i + 1; const line: string = lines[i]; const trimmedLine: string = line.trim(); + + // Nnew PNut/Propeller Tool directive support: {Spin2_v##} if (this.bHuntingForVersion && containsSpinLanguageSpec(trimmedLine)) { this._logMessage(` -- POSSIBLE spec: stopping HUNT Ln#${lineNbr}=[${trimmedLine}]`); this.bHuntingForVersion = false; // done we found it @@ -195,16 +197,20 @@ export class Spin2DocumentSemanticParser { this._logMessage(` -- found Spin2 SAME version (${newLangVersion}), stopping HUNT Ln#${lineNbr}=[${trimmedLine}]`); } } + const lineWOutInlineComments: string = this.parseUtils.getLineWithoutInlineComments(line); const bHaveLineToProcess: boolean = lineWOutInlineComments.length > 0; //this._logMessage(` -- Ln#${lineNbr} bHaveLineToProcess=(${bHaveLineToProcess}), lineWOutInlineComments=[${lineWOutInlineComments}](${lineWOutInlineComments.length})`); const nonCommentLine: string = bHaveLineToProcess ? this.parseUtils.getRemainderWOutTrailingTicComment(0, lineWOutInlineComments) : ""; - const trimmedNonCommentLine: string = bHaveLineToProcess ? nonCommentLine.trimStart() : ""; + let trimmedNonCommentLine: string = bHaveLineToProcess ? nonCommentLine.trimStart() : ""; //this._logMessage(` -- Ln#${lineNbr} CHK trimmedNonCommentLine=[${trimmedNonCommentLine}](${trimmedNonCommentLine.length})`); const offSet: number = trimmedNonCommentLine.length > 0 ? line.indexOf(trimmedNonCommentLine) + 1 : line.indexOf(trimmedLine) + 1; const tempComment: string = line.substring(trimmedNonCommentLine.length + offSet).trim(); this.rightEdgeComment = tempComment.length > 0 ? tempComment : undefined; const sectionStatus = this.extensionUtils.isSectionStartLine(line); + if (sectionStatus.isSectionStart) { + trimmedNonCommentLine = trimmedNonCommentLine.substring(3); + } const singleLineParts: string[] = trimmedNonCommentLine.split(/[ \t]/).filter(Boolean); // NOTE: comment mid-line set a pending state so next line uses the new state @@ -696,14 +702,17 @@ export class Spin2DocumentSemanticParser { const bHaveLineToProcess: boolean = lineWOutInlineComments.length > 0; //this._logMessage(` -- Ln#${lineNbr} bHaveLineToProcess=(${bHaveLineToProcess}), lineWOutInlineComments=[${lineWOutInlineComments}](${lineWOutInlineComments.length})`); const nonCommentLine: string = bHaveLineToProcess ? this.parseUtils.getRemainderWOutTrailingTicComment(0, lineWOutInlineComments) : ""; - const trimmedNonCommentLine: string = bHaveLineToProcess ? nonCommentLine.trimStart() : ""; + let trimmedNonCommentLine: string = bHaveLineToProcess ? nonCommentLine.trimStart() : ""; const sectionStatus = this.extensionUtils.isSectionStartLine(line); + if (sectionStatus.isSectionStart) { + trimmedNonCommentLine = trimmedNonCommentLine.substring(3); + } const singleLineParts: string[] = trimmedNonCommentLine.split(/[ \t]/).filter(Boolean); if (currState == eParseState.inMultiLineDocComment) { // in multi-line doc-comment, hunt for end '}}' to exit // ALLOW {cmt}, {{cmt}} on same line without closing! - let closingOffset = lineWOutInlineComments.indexOf("}}"); + let closingOffset = trimmedNonCommentLine.indexOf("}}"); if (closingOffset != -1) { // have close, comment ended currState = priorState; @@ -766,6 +775,72 @@ export class Spin2DocumentSemanticParser { } const parsingContinuedLineSet: boolean = !continuedLineSet.isEmpty; + if (trimmedLine.startsWith("''")) { + // process single line doc comment + // DO NOTHING Let Syntax highlighting do this + } else if (trimmedLine.startsWith("'")) { + // process single line non-doc comment + // DO NOTHING Let Syntax highlighting do this + } else if (trimmedNonCommentLine.startsWith("{{")) { + // process multi-line doc comment + let openingOffset = trimmedNonCommentLine.indexOf("{{"); + const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); + if (closingOffset != -1) { + // is single line comment, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + currState = eParseState.inMultiLineDocComment; + this._logMessage(`* Ln#${lineNbr} foundMuli srt-{{ starting MultiLineDocComment`); + // DO NOTHING Let Syntax highlighting do this + } + continue; + } else if (trimmedNonCommentLine.startsWith("{")) { + // process possible multi-line non-doc comment + // do we have a close on this same line? + let openingOffset = trimmedNonCommentLine.indexOf("{"); + const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); + if (closingOffset != -1) { + // is single line comment, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + currState = eParseState.inMultiLineComment; + this._logMessage(`* Ln#${lineNbr} foundMuli srt-{ starting MultiLineComment`); + // DO NOTHING Let Syntax highlighting do this + } + continue; + } else if (trimmedNonCommentLine.includes("{{")) { + // process multi-line doc comment + let openingOffset = trimmedNonCommentLine.indexOf("{{"); + const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); + if (closingOffset != -1) { + // is single line comment, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + pendingState = eParseState.inMultiLineDocComment; + this._logMessage(`* Ln#${lineNbr} foundMuli mid-{{ starting MultiLineDocComment`); + // DO NOTHING Let Syntax highlighting do this + } + // don't continue there might be some text to process before the {{ + } else if (trimmedNonCommentLine.includes("{") && !trimmedNonCommentLine.includes("{{")) { + // process possible multi-line non-doc comment + // do we have a close on this same line? + let openingOffset = trimmedNonCommentLine.indexOf("{"); + const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); + if (closingOffset != -1) { + // is single line comment, just ignore it Let Syntax highlighting do this + } else { + // is open of multiline comment + priorState = currState; + pendingState = eParseState.inMultiLineComment; + this._logMessage(`* Ln#${lineNbr} foundMuli mid-{ starting MultiLineComment`); + // DO NOTHING Let Syntax highlighting do this + } + // don't continue there might be some text to process before the { + } + if (sectionStatus.isSectionStart) { // ID the remainder of the line - single, non-continued line only if (currState == eParseState.inPub || currState == eParseState.inPri) { @@ -843,72 +918,6 @@ export class Spin2DocumentSemanticParser { } // NOT in section start... - if (trimmedLine.startsWith("''")) { - // process single line doc comment - // DO NOTHING Let Syntax highlighting do this - } else if (trimmedLine.startsWith("'")) { - // process single line non-doc comment - // DO NOTHING Let Syntax highlighting do this - } else if (trimmedNonCommentLine.startsWith("{{")) { - // process multi-line doc comment - let openingOffset = trimmedNonCommentLine.indexOf("{{"); - const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); - if (closingOffset != -1) { - // is single line comment, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - currState = eParseState.inMultiLineDocComment; - this._logMessage(`* Ln#${lineNbr} foundMuli srt-{{ starting MultiLineDocComment`); - // DO NOTHING Let Syntax highlighting do this - } - continue; - } else if (trimmedNonCommentLine.startsWith("{")) { - // process possible multi-line non-doc comment - // do we have a close on this same line? - let openingOffset = trimmedNonCommentLine.indexOf("{"); - const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); - if (closingOffset != -1) { - // is single line comment, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - currState = eParseState.inMultiLineComment; - this._logMessage(`* Ln#${lineNbr} foundMuli srt-{ starting MultiLineComment`); - // DO NOTHING Let Syntax highlighting do this - } - continue; - } else if (trimmedNonCommentLine.includes("{{")) { - // process multi-line doc comment - let openingOffset = trimmedNonCommentLine.indexOf("{{"); - const closingOffset = trimmedNonCommentLine.indexOf("}}", openingOffset + 2); - if (closingOffset != -1) { - // is single line comment, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - pendingState = eParseState.inMultiLineDocComment; - this._logMessage(`* Ln#${lineNbr} foundMuli mid-{{ starting MultiLineDocComment`); - // DO NOTHING Let Syntax highlighting do this - } - // don't continue there might be some text to process before the {{ - } else if (trimmedNonCommentLine.includes("{") && !trimmedNonCommentLine.includes("{{")) { - // process possible multi-line non-doc comment - // do we have a close on this same line? - let openingOffset = trimmedNonCommentLine.indexOf("{"); - const closingOffset = trimmedNonCommentLine.indexOf("}", openingOffset + 1); - if (closingOffset != -1) { - // is single line comment, just ignore it Let Syntax highlighting do this - } else { - // is open of multiline comment - priorState = currState; - pendingState = eParseState.inMultiLineComment; - this._logMessage(`* Ln#${lineNbr} foundMuli mid-{ starting MultiLineComment`); - // DO NOTHING Let Syntax highlighting do this - } - // don't continue there might be some text to process before the { - } - //this._logPASM(`- NON SECTION START Pass2 Ln#${lineNbr} trimmedLine=[${trimmedLine}](${trimmedLine.length})`); if (currState == eParseState.inCon) { @@ -1792,9 +1801,9 @@ export class Spin2DocumentSemanticParser { if (remainingNonCommentLineStr.length > 0) { //this._logVAR(" - Ln#" + lineNbr + " GetVarDecl remainingNonCommentLineStr=[" + remainingNonCommentLineStr + "]"); const isMultiDeclaration: boolean = remainingNonCommentLineStr.includes(","); - let lineParts: string[] = this.parseUtils.getNonWhiteDataInitLineParts(remainingNonCommentLineStr); + let lineParts: string[] = this.parseUtils.getNonWhiteDataDeclarationLineParts(remainingNonCommentLineStr); const hasGoodType: boolean = lineParts.length > 0 && this.parseUtils.isStorageType(lineParts[0]); - this._logVAR(" - Ln#" + lineNbr + " GetVarDecl lineParts=[" + lineParts + "](" + lineParts.length + ")"); + this._logVAR(` - Ln#${lineNbr} GetVarDecl lineParts=[${lineParts}](${lineParts.length})`); let nameSet: string[] = []; if (hasGoodType && lineParts.length > 1) { if (!isMultiDeclaration) { @@ -1809,9 +1818,14 @@ export class Spin2DocumentSemanticParser { // NOTE this is an instance-variable! for (let index = 1; index < nameSet.length; index++) { // remove array suffix and comma delim. from name - const newName = nameSet[index]; // .replace(/[\[,]/, ''); + let newName = nameSet[index]; // .replace(/[\[,]/, ''); + if (newName.includes("[")) { + const tempParts: string[] = newName.split(/[\[\]]/).filter(Boolean); + this._logVAR(` -- GLBL GetVarDecl adjust longVarName:[${newName}] -> [${tempParts[0]}]`); + newName = tempParts[0]; + } if (newName.charAt(0).match(/[a-zA-Z_]/)) { - this._logVAR(" -- GLBL GetVarDecl newName=[" + newName + "]"); + this._logVAR(` -- GLBL GetVarDecl newName=[${newName}]`); const nameOffset = line.indexOf(newName, currentOffset); // FIXME: UNDONE, do we have to dial this in? const referenceDetails: RememberedToken | undefined = this.semanticFindings.getGlobalToken(newName); if (referenceDetails) { @@ -1830,9 +1844,15 @@ export class Spin2DocumentSemanticParser { } } else if (!hasGoodType && lineParts.length > 0) { for (let index = 0; index < lineParts.length; index++) { - const longVarName = lineParts[index]; + let longVarName = lineParts[index]; + // if name is array of values then only report name part + if (longVarName.includes("[")) { + const tempParts: string[] = longVarName.split(/[\[\]]/).filter(Boolean); + this._logVAR(` -- GLBL GetVarDecl adjust longVarName:[${longVarName}] -> [${tempParts[0]}]`); + longVarName = tempParts[0]; + } if (longVarName.charAt(0).match(/[a-zA-Z_]/)) { - this._logVAR(" -- GLBL GetVarDecl newName=[" + longVarName + "]"); + this._logVAR(` -- GLBL GetVarDecl newName=[${longVarName}]`); const nameOffset = line.indexOf(longVarName, currentOffset); // FIXME: UNDONE, do we have to dial this in? const referenceDetails: RememberedToken | undefined = this.semanticFindings.getGlobalToken(longVarName); if (referenceDetails) { @@ -5517,7 +5537,7 @@ export class Spin2DocumentSemanticParser { if (remainingNonCommentLineStr.length > 0) { // get line parts - we only care about first one let lineParts: string[] = this.parseUtils.getCommaDelimitedNonWhiteLineParts(remainingNonCommentLineStr); - this._logVAR(" -- rptVarDecl lineParts=[" + lineParts + "]"); + this._logVAR(` -- rptVarDecl lineParts=[${lineParts}]`); // remember this object name so we can annotate a call to it const isMultiDeclaration: boolean = remainingNonCommentLineStr.includes(","); const hasStorageType: boolean = this.parseUtils.isStorageType(lineParts[0]); @@ -5612,9 +5632,13 @@ export class Spin2DocumentSemanticParser { } } else { // have single declaration per line - let newName = lineParts[0]; + let nameSet: string[] = [lineParts[0]]; + if (lineParts[0].includes("[")) { + nameSet = lineParts[0].split(/[\[\]}]/).filter(Boolean); + } + let newName: string = nameSet[0]; if (newName.charAt(0).match(/[a-zA-Z_]/)) { - this._logVAR(" -- GLBL rvdl2 newName=[" + newName + "]"); + this._logVAR(` -- GLBL rvdl2 newName=[${newName}]`); const nameOffset: number = line.indexOf(newName, currentOffset); this._recordToken(tokenSet, line, { line: lineIdx, @@ -5624,6 +5648,39 @@ export class Spin2DocumentSemanticParser { ptTokenModifiers: ["declaration", "instance"], }); } + if (nameSet.length > 1) { + // process remaining names is it only one size constant? + newName = nameSet[1]; + this._logVAR(` -- GLBL rvdl2 remaining newName=[${newName}]`); + if (this.semanticFindings.isGlobalToken(newName)) { + const referenceDetails: RememberedToken | undefined = this.semanticFindings.getGlobalToken(newName); + const searchString: string = newName; + const nameOffset = line.indexOf(searchString, currentOffset); + if (referenceDetails != undefined) { + this._logVAR(" -- FOUND global name=[" + newName + "]"); + this._recordToken(tokenSet, line, { + line: lineIdx, + startCharacter: nameOffset, + length: newName.length, + ptTokenType: referenceDetails.type, + ptTokenModifiers: referenceDetails.modifiers, + }); + } else { + // we don't have name registered so just mark it + if (!this.parseUtils.isSpinReservedWord(newName) && !this.parseUtils.isBuiltinStreamerReservedWord(newName) && !this.parseUtils.isDebugMethod(newName)) { + this._logVAR(" -- VAR Add MISSING name=[" + newName + "]"); + this._recordToken(tokenSet, line, { + line: lineIdx, + startCharacter: nameOffset, + length: newName.length, + ptTokenType: "variable", + ptTokenModifiers: ["missingDeclaration"], + }); + this.semanticFindings.pushDiagnosticMessage(lineIdx, nameOffset, nameOffset + newName.length, eSeverity.Error, `P2 Spin J missing declaration [${newName}]`); + } + } + } + } } } return tokenSet; diff --git a/spin2/server/src/parser/spin2.documentSymbolParser.ts b/spin2/server/src/parser/spin2.documentSymbolParser.ts index c71e77d..e47e44f 100644 --- a/spin2/server/src/parser/spin2.documentSymbolParser.ts +++ b/spin2/server/src/parser/spin2.documentSymbolParser.ts @@ -64,6 +64,11 @@ export class Spin2DocumentSymbolParser { continue; } + const sectionStatus = this._isOlnSectionStartLine(line); + if (sectionStatus.isSectionStart) { + nonCommentLine = nonCommentLine.substring(3); + } + // skip all {{ --- }} multi-line doc comments if (currState == eParseState.inMultiLineDocComment) { // in multi-line doc-comment, hunt for end '}}' to exit @@ -125,13 +130,12 @@ export class Spin2DocumentSymbolParser { } } - const sectionStatus = this._isOlnSectionStartLine(line); if (sectionStatus.isSectionStart) { currState = sectionStatus.inProgressStatus; } if (line.length > 2) { - const lineParts: string[] = linePrefix.split(/[ \t]/).filter(Boolean); + const lineParts: string[] = linePrefix.split(/[ \t\{]/).filter(Boolean); linePrefix = lineParts.length > 0 ? lineParts[0].toUpperCase() : ""; // the only form of comment we care about here is block comment after section name (e.g., "CON { text }") // NEW and let's add the use of ' comment too @@ -353,7 +357,7 @@ export class Spin2DocumentSymbolParser { let lineParts: string[] = this.parseUtils.getNonWhiteNParenLineParts(dataDeclNonCommentStr); this._logMessage("- OLn GetDatDecl lineParts=[" + lineParts + "](" + lineParts.length + ")"); let haveMoreThanDat: boolean = lineParts.length > 1 && lineParts[0].toUpperCase() == "DAT"; - if (haveMoreThanDat || lineParts[0].toUpperCase() != "DAT") { + if (haveMoreThanDat || (lineParts.length > 0 && lineParts[0].toUpperCase() != "DAT")) { // remember this object name so we can annotate a call to it let nameIndex: number = 0; let typeIndex: number = 1; diff --git a/spin2/server/src/parser/spin2.utils.ts b/spin2/server/src/parser/spin2.utils.ts index 3e293b6..fa9266c 100644 --- a/spin2/server/src/parser/spin2.utils.ts +++ b/spin2/server/src/parser/spin2.utils.ts @@ -321,6 +321,22 @@ export class Spin2ParseUtils { return nonDocCommentRHSStr; } + public getNonWhiteDataDeclarationLineParts(line: string): string[] { + const nonEqualsLine: string = this.removeDoubleQuotedStrings(line); + const lineParts: string[] | null = nonEqualsLine.match(/[^ \t\,\(\)\+\-\/\<\>\|\&\*\^\@]+/g); + let filterParts: string[] = []; + if (lineParts != null) { + for (let index = 0; index < lineParts.length; index++) { + const element = lineParts[index]; + if (element.length > 0) { + filterParts.push(element); + } + } + } + + return filterParts; + } + public getNonWhiteDataInitLineParts(line: string): string[] { const nonEqualsLine: string = this.removeDoubleQuotedStrings(line); const lineParts: string[] | null = nonEqualsLine.match(/[^ \t\,\[\]\(\)\+\-\/\<\>\|\&\*\^\@]+/g); diff --git a/spin2/syntaxes/spin1.tmLanguage.YAML-tmLanguage b/spin2/syntaxes/spin1.tmLanguage.YAML-tmLanguage index b46d566..96822d3 100644 --- a/spin2/syntaxes/spin1.tmLanguage.YAML-tmLanguage +++ b/spin2/syntaxes/spin1.tmLanguage.YAML-tmLanguage @@ -1,355 +1,345 @@ $schema: https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json name: spin patterns: - - include: "#comment" - - include: "#block" + - include: "#comment" + - include: "#block" repository: - allocation_constants: - name: keyword.control.allocation.spin - match: (?i)\b(_FREE|_STACK)\b - array_index: - name: meta.array.index.spin - match: (?i)\b(\[)(.*)?(\])\b + allocation_constants: + name: keyword.control.allocation.spin + match: (?i)\b(_FREE|_STACK)\b + array_index: + name: meta.array.index.spin + match: (?i)\b(\[)(.*)?(\])\b + captures: + "1": + name: keyword.operator.spin + "2": + patterns: + - include: "#number" + "3": + name: keyword.operator.spin + binary_number: + name: constant.numeric.binary.spin + match: (\%[01][01_]*)\b + captures: + "1": + name: constant.numeric.base2.spin + block: + name: meta.block.spin + patterns: + - include: "#constant_top_block" + - include: "#constant_block" + - include: "#variable_block" + - include: "#object_block" + - include: "#public_block" + - include: "#private_block" + - include: "#data_block" + block_comment: + name: comment.block.spin + begin: "{" + end: "}" + patterns: + - include: "#block_comment" + clock_constants_settable: + name: constant.language.control.configuration.spin + match: (?i)\b(_CLKFREQ|_CLKMODE|_XINFREQ)\b + clock_constants: + name: constant.language.control.configuration.spin + match: (?i)\b(XINPUT|XTAL(1|2|3)|RC(FAST|SLOW)|PLL(1|2|4|8|16)X)\b + cog_functions: + name: support.function.cog_control + match: (?i)\b(COG(ID|NEW|INIT|STOP)|REBOOT)\b + cog_register_names: + name: variable.language.cog-register-names.spin + match: (?i)\b((DIR|IN|OUT|CTR|FRQ|PHS)(A|B)|CNT|VCFG|VSCL|PAR|SPR)\b + comment: + patterns: + - include: "#doc_block_comment" + - include: "#block_comment" + - include: "#doc_line_comment" + - include: "#line_comment" + configuration: + name: variable.language.readonly.configuration + match: (?i)\b(CHIPVER|CLKMODE|CLKFREQ|CLKSET)\b + constants: + name: constant.language.spin + match: (?i)\b(TRUE|FALSE|(POS|NEG)X|PI)\b + constant_block: + name: meta.block.constant.spin + begin: '(?i)^(CON)\b' + end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b + beginCaptures: + "0": + name: keyword.block.con.spin + patterns: + - include: "#comment" + - include: "#number" + - include: "#constants" + - include: "#clock_constants" + - include: "#clock_constants_settable" + - include: "#spin_float_conversions" + - include: "#allocation_constants" + - match: \b((\w|_)+)\s*(=)\s*(.*)$ captures: - "1": - name: keyword.operator.spin - "2": - patterns: - - include: "#number" - "3": - name: keyword.operator.spin - binary_number: - name: constant.numeric.binary.spin - match: (\%[01][01_]*)\b + "1": + name: entity.name.constant.spin + "3": + name: keyword.equ.operator.assignment.spin + "4": + patterns: + - include: "#number" + - include: "#string" + - include: "#comment" + - include: "#number" + - include: "#constants" + - include: "#clock_constants" + - include: "#spin_float_conversions" + - include: "#allocation_constants" + constant_top_block: + name: meta.block.constant.spin + end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b + patterns: + - include: "#comment" + - include: "#number" + - include: "#constants" + - include: "#clock_constants" + - include: "#clock_constants_settable" + - include: "#spin_float_conversions" + - include: "#allocation_constants" + - match: \b((\w|_)+)\s*(=)\s*(.*)$ captures: - '1': - name: constant.numeric.base2.spin - block: - name: meta.block.spin - patterns: - - include: "#constant_top_block" - - include: "#constant_block" - - include: "#variable_block" - - include: "#object_block" - - include: "#public_block" - - include: "#private_block" - - include: "#data_block" - block_comment: - name: comment.block.spin - begin: "{" - end: "}" - patterns: - - include: "#block_comment" - clock_constants_settable: - name: constant.language.control.configuration.spin - match: (?i)\b(_CLKFREQ|_CLKMODE|_XINFREQ)\b - clock_constants: - name: constant.language.control.configuration.spin - match: (?i)\b(XINPUT|XTAL(1|2|3)|RC(FAST|SLOW)|PLL(1|2|4|8|16)X)\b - cog_functions: - name: support.function.cog_control - match: (?i)\b(COG(ID|NEW|INIT|STOP)|REBOOT)\b - cog_register_names: - name: variable.language.cog-register-names.spin - match: (?i)\b((DIR|IN|OUT|CTR|FRQ|PHS)(A|B)|CNT|VCFG|VSCL|PAR|SPR)\b - comment: - patterns: - - include: "#doc_block_comment" - - include: "#block_comment" - - include: "#doc_line_comment" - - include: "#line_comment" - configuration: - name: variable.language.readonly.configuration - match: (?i)\b(CHIPVER|CLKMODE|CLKFREQ|CLKSET)\b - constants: - name: constant.language.spin - match: (?i)\b(TRUE|FALSE|(POS|NEG)X|PI)\b - constant_block: - name: meta.block.constant.spin - begin: '(?i)^(CON)(\s+|\s*$)' - end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b - beginCaptures: - "0": - name: keyword.block.con.spin - patterns: - - include: "#comment" - - include: "#number" - - include: "#constants" - - include: "#clock_constants" - - include: "#clock_constants_settable" - - include: "#spin_float_conversions" - - include: "#allocation_constants" - - match: \b((\w|_)+)\s*(=)\s*(.*)$ - captures: - "1": - name: entity.name.constant.spin - "3": - name: keyword.equ.operator.assignment.spin - "4": - patterns: - - include: "#number" - - include: "#string" - - include: "#comment" - - include: "#number" - - include: "#constants" - - include: "#clock_constants" - - include: "#spin_float_conversions" - - include: "#allocation_constants" - constant_top_block: - name: meta.block.constant.spin - end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b - patterns: - - include: "#comment" - - include: "#number" - - include: "#constants" - - include: "#clock_constants" - - include: "#clock_constants_settable" - - include: "#spin_float_conversions" - - include: "#allocation_constants" - - match: \b((\w|_)+)\s*(=)\s*(.*)$ - captures: - "1": - name: entity.name.constant.spin - "3": - name: keyword.equ.operator.assignment.spin - "4": - patterns: - - include: "#number" - - include: "#string" - - include: "#comment" - - include: "#number" - - include: "#constants" - - include: "#clock_constants" - - include: "#spin_float_conversions" - - include: "#allocation_constants" - data_block: - name: meta.block.data.spin - begin: '(?i)^(DAT)(\s+|\s*$)' - end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b - beginCaptures: - "0": - name: keyword.block.dat.spin - patterns: - - include: "#comment" - - include: "#cog_register_names" - - include: "#constants" - - include: "#clock_constants" - - include: "#storage_modifier" - - include: "#directives_file_include" - - include: "#spin_float_conversions" - - include: "#array_index" - - include: "#number" - - include: "#string" - - name: storage.modifier.pasm - match: (?i)\b(ORG|FIT)\b - - name: storage.type.pasm - match: (?i)\b(BYTE|WORD|LONG|RES)\b - - name: keyword.pasm.instruction.configuration - match: (?i)\bCLKSET\b - - name: keyword.pasm.instruction.cog_control - match: (?i)\bCOG(ID|INIT|STOP)\b - - name: keyword.pasm.instruction.process_control - match: (?i)\b(LOCK(NEW|RET|CLR|SET)|WAIT(CNT|PEQ|PNE|VID))\b - - name: keyword.pasm.control.conditions - match: (?i)\bIF_(ALWAYS|NEVER|N?E|(A|B)E?|N?C|N?Z|C_(EQ|NE)_Z|N?C_(AND|OR)_N?Z|Z_(EQ|NE)_C|N?Z_(AND|OR)_N?C)\b - - name: keyword.pasm.instruction.control.flow - match: (?i)\b(CALL|DJNZ|JMP|JMPRET|TJNZ|TJZ|RET)\b - - name: keyword.pasm.instruction.effects - match: (?i)\b(NR|WR|WC|WZ)\b - - name: keyword.pasm.instruction.main_memory_access - match: (?i)\b(RD|WR)(BYTE|WORD|LONG)\b - - name: keyword.pasm.instruction.common - match: (?i)\b(ABS(NEG)?|NEGN?(C|Z)?|MINS?|MAXS?|ADD(ABS|S|X|SX)?|SUB(ABS|S|X|SX)?|SUMN?(C|Z)?|MULS?|ANDN?|X?OR|ONES|ENC|RC(L|R)|REV|RO(L|R)|SH(L|R)|SAR|CMPS?X?|CMPSUB|TESTN?|MOV(S|D|I)?|MUXN?(C|Z)?|HUBOP|NOP)\b - - name: keyword.operator.pasm - match: (?i)\b(\+|\-|\^\^|\|\||\|<|>\||!|@|\*\*?|//?|#>|<#|~>|<<|>>|<-|->|><|&|\||\^|AND|OR|==|<>|<|>|=<|=>)\b - decimal_number: - name: constant.numeric.decimal.spin - patterns: - - - name: constant.numeric.base10.spin - match: '([\+\-][0-9][0-9_]*)\b' - - - name: constant.numeric.base10.spin - match: '\b([0-9][0-9_]*)\b' - - - name: constant.numeric.base10.spin2 - match: '\b([0-9]+)[eE][\+\-]?[0-9]+\b' - spin_float_conversions: - name: keyword.operator.float.spin - match: (?i)\b(FLOAT|ROUND|TRUNC)\b - directives_wraps: - name: keyword.control.directive.spin - match: (?i)\b(STRING|CONSTANT)\b - directives_file_include: - name: keyword.control.directive.spin - match: (?i)\b(FILE)\b - doc_block_comment: - name: comment.block.documentation.spin - begin: "{{" - end: "}}" - patterns: - - include: "#doc_block_comment" - doc_line_comment: - name: comment.line.documentation.spin - match: "''.*$" - float_number: - name: constant.numeric.decimal.spin - patterns: - - - name: constant.numeric.float.spin - match: \b([\+\-]?(?:0|[1-9][0-9_]*)\.(?:[0-9]+)?(?:[eE][\+\-]?[0-9]+)?)\b - - - name: constant.numeric.float.spin - match: \b([\+\-]?(?:0|[1-9][0-9_]*)?\.(?:[0-9]+)(?:[eE][\+\-]?[0-9]+))\b - hexadecimal_number: - name: constant.numeric.hexadecimal.spin - match: (?i)(\$[0-9a-fA-F][0-9a-fA-F_]*)\b + "1": + name: entity.name.constant.spin + "3": + name: keyword.equ.operator.assignment.spin + "4": + patterns: + - include: "#number" + - include: "#string" + - include: "#comment" + - include: "#number" + - include: "#constants" + - include: "#clock_constants" + - include: "#spin_float_conversions" + - include: "#allocation_constants" + data_block: + name: meta.block.data.spin + begin: '(?i)^(DAT)\b' + end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b + beginCaptures: + "0": + name: keyword.block.dat.spin + patterns: + - include: "#comment" + - include: "#cog_register_names" + - include: "#constants" + - include: "#clock_constants" + - include: "#storage_modifier" + - include: "#directives_file_include" + - include: "#spin_float_conversions" + - include: "#array_index" + - include: "#number" + - include: "#string" + - name: storage.modifier.pasm + match: (?i)\b(ORG|FIT)\b + - name: storage.type.pasm + match: (?i)\b(BYTE|WORD|LONG|RES)\b + - name: keyword.pasm.instruction.configuration + match: (?i)\bCLKSET\b + - name: keyword.pasm.instruction.cog_control + match: (?i)\bCOG(ID|INIT|STOP)\b + - name: keyword.pasm.instruction.process_control + match: (?i)\b(LOCK(NEW|RET|CLR|SET)|WAIT(CNT|PEQ|PNE|VID))\b + - name: keyword.pasm.control.conditions + match: (?i)\bIF_(ALWAYS|NEVER|N?E|(A|B)E?|N?C|N?Z|C_(EQ|NE)_Z|N?C_(AND|OR)_N?Z|Z_(EQ|NE)_C|N?Z_(AND|OR)_N?C)\b + - name: keyword.pasm.instruction.control.flow + match: (?i)\b(CALL|DJNZ|JMP|JMPRET|TJNZ|TJZ|RET)\b + - name: keyword.pasm.instruction.effects + match: (?i)\b(NR|WR|WC|WZ)\b + - name: keyword.pasm.instruction.main_memory_access + match: (?i)\b(RD|WR)(BYTE|WORD|LONG)\b + - name: keyword.pasm.instruction.common + match: (?i)\b(ABS(NEG)?|NEGN?(C|Z)?|MINS?|MAXS?|ADD(ABS|S|X|SX)?|SUB(ABS|S|X|SX)?|SUMN?(C|Z)?|MULS?|ANDN?|X?OR|ONES|ENC|RC(L|R)|REV|RO(L|R)|SH(L|R)|SAR|CMPS?X?|CMPSUB|TESTN?|MOV(S|D|I)?|MUXN?(C|Z)?|HUBOP|NOP)\b + - name: keyword.operator.pasm + match: (?i)\b(\+|\-|\^\^|\|\||\|<|>\||!|@|\*\*?|//?|#>|<#|~>|<<|>>|<-|->|><|&|\||\^|AND|OR|==|<>|<|>|=<|=>)\b + decimal_number: + name: constant.numeric.decimal.spin + patterns: + - name: constant.numeric.base10.spin + match: '([\+\-][0-9][0-9_]*)\b' + - name: constant.numeric.base10.spin + match: '\b([0-9][0-9_]*)\b' + - name: constant.numeric.base10.spin2 + match: '\b([0-9]+)[eE][\+\-]?[0-9]+\b' + spin_float_conversions: + name: keyword.operator.float.spin + match: (?i)\b(FLOAT|ROUND|TRUNC)\b + directives_wraps: + name: keyword.control.directive.spin + match: (?i)\b(STRING|CONSTANT)\b + directives_file_include: + name: keyword.control.directive.spin + match: (?i)\b(FILE)\b + doc_block_comment: + name: comment.block.documentation.spin + begin: "{{" + end: "}}" + patterns: + - include: "#doc_block_comment" + doc_line_comment: + name: comment.line.documentation.spin + match: "''.*$" + float_number: + name: constant.numeric.decimal.spin + patterns: + - name: constant.numeric.float.spin + match: \b([\+\-]?(?:0|[1-9][0-9_]*)\.(?:[0-9]+)?(?:[eE][\+\-]?[0-9]+)?)\b + - name: constant.numeric.float.spin + match: \b([\+\-]?(?:0|[1-9][0-9_]*)?\.(?:[0-9]+)(?:[eE][\+\-]?[0-9]+))\b + hexadecimal_number: + name: constant.numeric.hexadecimal.spin + match: (?i)(\$[0-9a-fA-F][0-9a-fA-F_]*)\b + captures: + "1": + name: constant.numeric.base16.spin + return_var: + name: meta.return-type.spin + match: (?i)\b(RESULT)\b + lock_functions: + name: support.function.process_control.spin + match: (?i)\b(LOCK(CLR|NEW|RET|SET))\b + wait_functions: + name: support.function.waiting.spin + match: (?i)\b(WAIT(CNT|PEQ|PNE|VID))\b + memory_functions: + name: support.function.memory.spin + match: (?i)\b((BYTE|WORD|LONG)(FILL|MOVE)|LOOK(UPZ?|DOWNZ?)|STR(SIZE|COMP))\b + storage_types: + name: storage.type.pasm + match: (?i)\b(BYTE|WORD|LONG)\b + number: + patterns: + - include: "#quaternary_number" + - include: "#binary_number" + - include: "#hexadecimal_number" + - include: "#float_number" + - include: "#decimal_number" + object_block: + name: meta.block.object.spin + begin: '(?i)^(OBJ)\b' + end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b + beginCaptures: + "0": + name: keyword.block.obj.spin + patterns: + - include: "#comment" + - include: "#spin_float_conversions" + - name: meta.object-initialization.spin + match: \b(\w+)(\[.*\])?\s*(:)\s*((\")(\.|[^"])*(\")) captures: - '1': - name: constant.numeric.base16.spin - return_var: - name: meta.return-type.spin - match: (?i)\b(RESULT)\b - lock_functions: - name: support.function.process_control.spin - match: (?i)\b(LOCK(CLR|NEW|RET|SET))\b - wait_functions: - name: support.function.waiting.spin - match: (?i)\b(WAIT(CNT|PEQ|PNE|VID))\b - memory_functions: - name: support.function.memory.spin - match: (?i)\b((BYTE|WORD|LONG)(FILL|MOVE)|LOOK(UPZ?|DOWNZ?)|STR(SIZE|COMP))\b - storage_types: - name: storage.type.pasm - match: (?i)\b(BYTE|WORD|LONG)\b - number: - patterns: - - include: "#quaternary_number" - - include: "#binary_number" - - include: "#hexadecimal_number" - - include: "#float_number" - - include: "#decimal_number" - object_block: - name: meta.block.object.spin - begin: '(?i)^(OBJ)(\s+|\s*$)' - end: '(?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT)(\s+|\s*$))' - beginCaptures: - '0': - name: keyword.block.obj.spin - patterns: - - include: '#comment' - - include: "#spin_float_conversions" - - - name: meta.object-initialization.spin - match: \b(\w+)(\[.*\])?\s*(:)\s*((\")(\.|[^"])*(\")) - captures: - '1': {name: entity.name.object.spin} - '2': {patterns: [ - {include: '#number'}, - {include: '#constants'}, - {include: '#array_index'} - ]} - '3': {name: punctuation.spin} - '4': {name: meta.object.filename.spin} - '5': {name: punctuation.spin} - '7': {name: punctuation.spin} - operator: - name: keyword.operator.spin - match: (?i)\b(\+(\+|=)?|-(-|=)?|\^(\^|=)?|\|(\||=)?|~(~|>)?=?|\?|\|<|>\||!|NOT|@@?|:?=|\*(\*|=)?|/(/|=)?|#>=?|<#=?|<>?=?|<-=?|->=?|><=?|&=|AND=?|OR=?|===?|<>=?|=[<>]=?)\b - private_block: - name: meta.block.private.spin - begin: '(?i)^(PRI)(\s+|\s*$)' - end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b - beginCaptures: - "0": - name: keyword.block.pri.spin - patterns: - - include: "#comment" - - include: "#constants" - - include: "#string" - - include: "#configuration" - - include: "#clock_constants" - - include: "#return_var" - - include: "#directives_wraps" - - include: "#spin_float_conversions" - - include: "#array_index" - - include: "#number" - - include: "#storage_types" - - include: "#cog_functions" - - include: "#memory_functions" - - include: "#lock_functions" - - include: "#wait_functions" - - include: "#operator" - - include: "#cog_register_names" - - include: "#control_flow" - public_block: - name: meta.block.public.spin - begin: '(?i)^(PUB)(\s+|\s*$)' - end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b - beginCaptures: - "0": - name: keyword.block.pub.spin - patterns: - - include: "#comment" - - include: "#constants" - - include: "#string" - - include: "#configuration" - - include: "#clock_constants" - - include: "#return_var" - - include: "#directives_wraps" - - include: "#spin_float_conversions" - - include: "#array_index" - - include: "#number" - - include: "#storage_types" - - include: "#cog_functions" - - include: "#memory_functions" - - include: "#lock_functions" - - include: "#wait_functions" - - include: "#operator" - - include: "#cog_register_names" - - include: "#control_flow" - quaternary_number: - name: constant.numeric.quaternary.spin - match: (\%\%[0-3][0-3_]*)\b + "1": { name: entity.name.object.spin } + "2": { patterns: [{ include: "#number" }, { include: "#constants" }, { include: "#array_index" }] } + "3": { name: punctuation.spin } + "4": { name: meta.object.filename.spin } + "5": { name: punctuation.spin } + "7": { name: punctuation.spin } + operator: + name: keyword.operator.spin + match: (?i)\b(\+(\+|=)?|-(-|=)?|\^(\^|=)?|\|(\||=)?|~(~|>)?=?|\?|\|<|>\||!|NOT|@@?|:?=|\*(\*|=)?|/(/|=)?|#>=?|<#=?|<>?=?|<-=?|->=?|><=?|&=|AND=?|OR=?|===?|<>=?|=[<>]=?)\b + private_block: + name: meta.block.private.spin + begin: '(?i)^(PRI)(\s+)' + end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b + beginCaptures: + "0": + name: keyword.block.pri.spin + patterns: + - include: "#comment" + - include: "#constants" + - include: "#string" + - include: "#configuration" + - include: "#clock_constants" + - include: "#return_var" + - include: "#directives_wraps" + - include: "#spin_float_conversions" + - include: "#array_index" + - include: "#number" + - include: "#storage_types" + - include: "#cog_functions" + - include: "#memory_functions" + - include: "#lock_functions" + - include: "#wait_functions" + - include: "#operator" + - include: "#cog_register_names" + - include: "#control_flow" + public_block: + name: meta.block.public.spin + begin: '(?i)^(PUB)(\s+)' + end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b + beginCaptures: + "0": + name: keyword.block.pub.spin + patterns: + - include: "#comment" + - include: "#constants" + - include: "#string" + - include: "#configuration" + - include: "#clock_constants" + - include: "#return_var" + - include: "#directives_wraps" + - include: "#spin_float_conversions" + - include: "#array_index" + - include: "#number" + - include: "#storage_types" + - include: "#cog_functions" + - include: "#memory_functions" + - include: "#lock_functions" + - include: "#wait_functions" + - include: "#operator" + - include: "#cog_register_names" + - include: "#control_flow" + quaternary_number: + name: constant.numeric.quaternary.spin + match: (\%\%[0-3][0-3_]*)\b + captures: + "1": + name: constant.numeric.base4.spin + control_flow: + name: keyword.control.flow.spin + match: (?i)\b(RETURN|REPEAT|FROM|TO|STEP|UNTIL|WHILE|NEXT|QUIT|ABORT|IF(NOT)?|ELSE(IF|IFNOT)?|CASE|OTHER)\b + storage_modifier: + name: storage.modifier.pasm + match: (?i)\b(org|end|fit)\b + string: + name: string.quoted.double.spin + begin: '"' + end: '"' + variable_block: + name: meta.block.variable.spin + begin: '(?i)^(VAR)\b' + end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b + beginCaptures: + "0": + name: keyword.block.var.spin + patterns: + - include: "#comment" + - include: "#constants" + - include: "#string" + - include: "#array_index" + - include: "#number" + - include: "#spin_float_conversions" + - include: "#storage_types" + - match: (?i)\b(byte|word|long)\s*((\w|_)+)(\[.*\])? captures: - '1': - name: constant.numeric.base4.spin - control_flow: - name: keyword.control.flow.spin - match: (?i)\b(RETURN|REPEAT|FROM|TO|STEP|UNTIL|WHILE|NEXT|QUIT|ABORT|IF(NOT)?|ELSE(IF|IFNOT)?|CASE|OTHER)\b - storage_modifier: - name: storage.modifier.pasm - match: (?i)\b(org|end|fit)\b - string: - name: string.quoted.double.spin - begin: '"' - end: '"' - variable_block: - name: meta.block.variable.spin - begin: '(?i)^(VAR)(\s+|\s*$)' - end: (?i)^(?=(CON|VAR|OBJ|PUB|PRI|DAT))\b - beginCaptures: - "0": - name: keyword.block.var.spin - patterns: - - include: "#comment" - - include: "#constants" - - include: "#string" - - include: "#array_index" - - include: "#number" - - include: "#spin_float_conversions" - - include: "#storage_types" - - match: (?i)\b(byte|word|long)\s*((\w|_)+)(\[.*\])? - captures: - "1": - name: storage.type.spin - "2": - name: variable.name.spin - "4": - patterns: - - include: "#array_index" - line_comment: - name: comment.line.spin - match: "(?