UNPKG

@imc-trading/svlangserver

Version:
1,012 lines 144 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SystemVerilogParser = void 0; const node_1 = require("vscode-languageserver/node"); const genutils_1 = require("./genutils"); const grammar_engine_1 = require("./grammar_engine"); const svcompletion_grammar_1 = require("./svcompletion_grammar"); const svsymbol_1 = require("./svsymbol"); const svpreprocessor_1 = require("./svpreprocessor"); const DEBUG_MODE = 0; class ParseToken { } function _jsonToContainerSymbolsInfo(file, jsonContainerSymbolsInfo) { let containerSymbolsInfo = {}; if (jsonContainerSymbolsInfo.length > SystemVerilogParser.ContainerInfoIndex.Symbols) { if (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Symbols] != undefined) { containerSymbolsInfo.symbolsInfo = []; for (let symbol of (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Symbols])) { containerSymbolsInfo.symbolsInfo.push(svsymbol_1.SystemVerilogSymbol.fromJSON(file, symbol)); } } } if (jsonContainerSymbolsInfo.length > SystemVerilogParser.ContainerInfoIndex.Imports) { if (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Imports] != undefined) { containerSymbolsInfo.importsInfo = []; for (let importInfo of (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Imports])) { containerSymbolsInfo.importsInfo.push({ pkg: importInfo[0], symbolsText: importInfo[1] }); } } } if (jsonContainerSymbolsInfo.length > SystemVerilogParser.ContainerInfoIndex.Containers) { if (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Containers] != undefined) { containerSymbolsInfo.containersInfo = []; for (let jsonContainerInfo of (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Containers])) { containerSymbolsInfo.containersInfo.push({ symbol: svsymbol_1.SystemVerilogSymbol.fromJSON(file, jsonContainerInfo[0][0]), position: SystemVerilogParser.jsonToPosition(jsonContainerInfo[0][1]), info: _jsonToContainerSymbolsInfo(file, jsonContainerInfo[1]) }); } } } if (jsonContainerSymbolsInfo.length > SystemVerilogParser.ContainerInfoIndex.Exports) { if (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Exports] != undefined) { containerSymbolsInfo.exportsInfo = []; for (let exportInfo of (jsonContainerSymbolsInfo[SystemVerilogParser.ContainerInfoIndex.Exports])) { containerSymbolsInfo.exportsInfo.push({ pkg: exportInfo[0], symbolsText: exportInfo[1] }); } } } return containerSymbolsInfo; } class ContainerStack { constructor(fileSymbolsInfo) { this._stack = { fileInfo: fileSymbolsInfo, containersInfo: [] }; this._symbolMap = new Map(); this._importMap = new Map(); this._exportMap = new Map(); } push(symbol) { let containerSymbols; if (this._stack.containersInfo.length <= 0) { if (this._stack.fileInfo.containersInfo == undefined) { this._stack.fileInfo.containersInfo = []; } containerSymbols = this._stack.fileInfo.containersInfo; } else { let containerSymbolsInfo = this._stack.containersInfo[this._stack.containersInfo.length - 1].info; if (containerSymbolsInfo.containersInfo == undefined) { containerSymbolsInfo.containersInfo = []; } containerSymbols = containerSymbolsInfo.containersInfo; } let containerInfo; let symbolStr = [symbol.name, ...symbol.type, ...this.toStringList()].join(' '); let resSymbol; if (this._symbolMap.has(symbolStr)) { containerInfo = containerSymbols[this._symbolMap.get(symbolStr)]; containerInfo.symbol.overwrite(symbol); resSymbol = containerInfo.symbol; } else { this._symbolMap.set(symbolStr, containerSymbols.length); containerInfo = { symbol: symbol, position: undefined, info: {} }; containerSymbols.push(containerInfo); resSymbol = symbol; } this._stack.containersInfo.push(containerInfo); return resSymbol; } pushSymbol(symbol) { let symbols; if (this._stack.containersInfo.length <= 0) { if (this._stack.fileInfo.symbolsInfo == undefined) { this._stack.fileInfo.symbolsInfo = []; } symbols = this._stack.fileInfo.symbolsInfo; } else { let containerSymbolsInfo = this._stack.containersInfo[this._stack.containersInfo.length - 1].info; if (containerSymbolsInfo.symbolsInfo == undefined) { containerSymbolsInfo.symbolsInfo = []; } symbols = containerSymbolsInfo.symbolsInfo; } let symbolStr = [symbol.name, ...symbol.type, ...this.toStringList()].join(' '); let resSymbol; if (this._symbolMap.has(symbolStr)) { symbols[this._symbolMap.get(symbolStr)].overwrite(symbol); resSymbol = symbols[this._symbolMap.get(symbolStr)]; } else { this._symbolMap.set(symbolStr, symbols.length); symbols.push(symbol); resSymbol = symbol; } return resSymbol; } getContainerDocumentPath(uri) { if (this._stack.containersInfo.length <= 0) { return undefined; } return this._stack.containersInfo[this._stack.containersInfo.length - 1].symbol.getSymbolDocumentPath(uri); } pop(endPosition) { if (this._stack.containersInfo.length <= 0) { genutils_1.ConnectionLogger.error(`ContainerStack is already empty!`); return; } this._stack.containersInfo[this._stack.containersInfo.length - 1].position = endPosition; this._stack.containersInfo.pop(); } toStringList() { return this._stack.containersInfo.map(e => e.symbol.name); } pushImportItem(importItemToken) { let importParts = importItemToken.text.split('::'); let importHierPath = [importParts[0], ...this.toStringList()].join(' '); if (!this._importMap.has(importHierPath)) { this._importMap.set(importHierPath, { allIncluded: false, index: undefined }); } let importInfo = this._importMap.get(importHierPath); if (importInfo.allIncluded) { return; } let importsInfo; if (this._stack.containersInfo.length <= 0) { if (this._stack.fileInfo.importsInfo == undefined) { this._stack.fileInfo.importsInfo = []; } importsInfo = this._stack.fileInfo.importsInfo; } else { let containerSymbolsInfo = this._stack.containersInfo[this._stack.containersInfo.length - 1].info; if (containerSymbolsInfo.importsInfo == undefined) { containerSymbolsInfo.importsInfo = []; } importsInfo = containerSymbolsInfo.importsInfo; } if (importInfo.index == undefined) { importInfo.index = importsInfo.length; importsInfo.push({ pkg: importParts[0], symbolsText: [] }); } if (importParts[1] == "*") { importInfo.allIncluded = true; importsInfo[importInfo.index].symbolsText = ["*"]; } else { importsInfo[importInfo.index].symbolsText.push(importParts[1]); } } pushExportItem(exportItemToken) { let exportParts = exportItemToken.text.split('::'); let exportHierPath = [exportParts[0], ...this.toStringList()].join(' '); if (!this._exportMap.has(exportHierPath)) { this._exportMap.set(exportHierPath, { allIncluded: false, index: undefined }); } else if (exportParts[0] == "*") { return; } if (exportParts[0] == "*") { if (this._stack.containersInfo.length <= 0) { this._stack.fileInfo.exportsInfo = [{ pkg: exportParts[0], symbolsText: ["*"] }]; } else { this._stack.containersInfo[this._stack.containersInfo.length - 1].info.exportsInfo = [{ pkg: exportParts[0], symbolsText: ["*"] }]; } return; } let exportInfo = this._exportMap.get(exportHierPath); if (exportInfo.allIncluded) { return; } let exportsInfo; if (this._stack.containersInfo.length <= 0) { if (this._stack.fileInfo.exportsInfo == undefined) { this._stack.fileInfo.exportsInfo = []; } exportsInfo = this._stack.fileInfo.exportsInfo; } else { let containerSymbolsInfo = this._stack.containersInfo[this._stack.containersInfo.length - 1].info; if (containerSymbolsInfo.exportsInfo == undefined) { containerSymbolsInfo.exportsInfo = []; } exportsInfo = containerSymbolsInfo.exportsInfo; } if (exportInfo.index == undefined) { exportInfo.index = exportsInfo.length; exportsInfo.push({ pkg: exportParts[0], symbolsText: [] }); } if (exportParts[1] == "*") { exportInfo.allIncluded = true; exportsInfo[exportInfo.index].symbolsText = ["*"]; } else { exportsInfo[exportInfo.index].symbolsText.push(exportParts[1]); } } } class SystemVerilogParser { constructor() { this._completionGrammarEngine = new grammar_engine_1.GrammarEngine(svcompletion_grammar_1.svcompletion_grammar, "meta.invalid.systemverilog"); this._anonStructUnionCount = 0; this._anonEnumCount = 0; } _debugContainerInfo(containerInfo, symIndex) { if (symIndex == SystemVerilogParser.ContainerInfoIndex.Symbols) { if (containerInfo.symbolsInfo == undefined) { return; } for (let symbol of containerInfo.symbolsInfo) { genutils_1.ConnectionLogger.log(`DEBUG: symbol "${symbol.name}" of type ${symbol.type}`); } } else if (symIndex == SystemVerilogParser.ContainerInfoIndex.Imports) { if (containerInfo.importsInfo == undefined) { return; } for (let importItem of containerInfo.importsInfo) { genutils_1.ConnectionLogger.log(`DEBUG: imports from "${importItem[0]}" are ${importItem[1]}`); } } else if (symIndex == SystemVerilogParser.ContainerInfoIndex.Containers) { if (containerInfo.containersInfo == undefined) { return; } for (let childContainerInfo of containerInfo.containersInfo) { let symbol = childContainerInfo.symbol; genutils_1.ConnectionLogger.log(`DEBUG: container symbol "${symbol.name}" of type ${symbol.type}`); let containerSymbolsInfo = childContainerInfo.info; for (let si = 0; si < Object.entries(SystemVerilogParser.ContainerInfoIndex).length; si++) { this._debugContainerInfo(containerSymbolsInfo, si); } } } else if (symIndex == SystemVerilogParser.ContainerInfoIndex.Exports) { if (containerInfo.exportsInfo == undefined) { return; } for (let exportItem of containerInfo.exportsInfo) { genutils_1.ConnectionLogger.log(`DEBUG: exports from "${exportItem[0]}" are ${exportItem[1]}`); } } else { genutils_1.ConnectionLogger.error(`Unsupported SystemVerilogParser.ContainerInfoIndex ${symIndex}`); } } _debugFileInfo(symIndex) { if (symIndex == SystemVerilogParser.FileInfoIndex.Containers) { if (this._fileSymbolsInfo.containersInfo == undefined) { return; } for (let containerInfo of this._fileSymbolsInfo.containersInfo) { let symbol = containerInfo.symbol; genutils_1.ConnectionLogger.log(`DEBUG: container symbol "${symbol.name}" of type ${symbol.type}`); let containerSymbolsInfo = containerInfo.info; for (let si = 0; si < Object.entries(SystemVerilogParser.ContainerInfoIndex).length; si++) { this._debugContainerInfo(containerSymbolsInfo, si); } } } else if (symIndex == SystemVerilogParser.FileInfoIndex.Includes) { if ((this._fileSymbolsInfo.includesInfo == undefined) || (this._fileSymbolsInfo.includesInfo.length <= 0)) { genutils_1.ConnectionLogger.log(`DEBUG: no includes in ${this._documentPath}`); return; } for (let include of this._fileSymbolsInfo.includesInfo) { genutils_1.ConnectionLogger.log(`DEBUG: ${include} included in ${this._documentPath}`); } } else if (symIndex == SystemVerilogParser.FileInfoIndex.Imports) { if ((this._fileSymbolsInfo.importsInfo == undefined) || (this._fileSymbolsInfo.importsInfo.length <= 0)) { genutils_1.ConnectionLogger.log(`DEBUG: no global imports in ${this._documentPath}`); return; } for (let importItem of this._fileSymbolsInfo.importsInfo) { genutils_1.ConnectionLogger.log(`DEBUG: global imports from "${importItem[0]}" are ${importItem[1]}`); } } else if (symIndex == SystemVerilogParser.FileInfoIndex.Exports) { if ((this._fileSymbolsInfo.exportsInfo == undefined) || (this._fileSymbolsInfo.exportsInfo.length <= 0)) { genutils_1.ConnectionLogger.log(`DEBUG: no global exports in ${this._documentPath}`); return; } for (let exportItem of this._fileSymbolsInfo.exportsInfo) { genutils_1.ConnectionLogger.log(`DEBUG: global exports from "${exportItem[0]}" are ${exportItem[1]}`); } } else if (symIndex == SystemVerilogParser.FileInfoIndex.Symbols) { if (this._fileSymbolsInfo.symbolsInfo == undefined) { return; } for (let symbol of this._fileSymbolsInfo.symbolsInfo) { genutils_1.ConnectionLogger.log(`DEBUG: symbol "${symbol.name}" of type ${symbol.type}`); } } else { genutils_1.ConnectionLogger.error(`Unsupported SystemVerilogParser.FileInfoIndex ${symIndex}`); } } tokenize(_text, includeFilePaths, userDefinesMacroInfo) { try { let preprocParser = new svpreprocessor_1.SystemVerilogPreprocessor(); let preprocInfo = preprocParser.parse(this._document, includeFilePaths, this._preprocCache, userDefinesMacroInfo); if (preprocInfo.includes.size > 0) { this._fileSymbolsInfo.includesInfo = [...preprocInfo.includes]; } let postText = preprocInfo.postTokens.map(tok => tok.text).join(''); let tokens = this._completionGrammarEngine.tokenize(postText); let parseTokens = tokens.map(token => { return { text: token.text, scopes: token.scopes, startTokenIndex: undefined, endTokenIndex: undefined }; }); let tokenOrder = []; let currParseToken = 0; let tokenText = ""; let tokenOrderIndex = 0; let tokenOrderFile; for (let i = 0; i < preprocInfo.postTokens.length; i++) { if ((tokenOrderIndex < preprocInfo.tokenOrder.length) && (preprocInfo.tokenOrder[tokenOrderIndex].tokenNum == i)) { if ((tokenText != "") && (parseTokens[currParseToken].text.trim() != "")) { genutils_1.ConnectionLogger.error(`assumption about tokens not split across files might be broken for ${this._documentPath} at ${preprocInfo.tokenOrder[tokenOrderIndex].tokenNum}`); } tokenOrderFile = preprocInfo.tokenOrder[tokenOrderIndex].file; tokenOrderIndex++; } if (tokenText == "") { parseTokens[currParseToken].startTokenIndex = preprocInfo.postTokens[i].index; if (tokenOrderFile != undefined) { tokenOrder.push({ file: tokenOrderFile, tokenNum: currParseToken }); } tokenOrderFile = undefined; } tokenText += preprocInfo.postTokens[i].text; if (tokenText.length >= parseTokens[currParseToken].text.length) { if ((tokenText.length > parseTokens[currParseToken].text.length) || (tokenText != parseTokens[currParseToken].text)) { genutils_1.ConnectionLogger.error(`Assumption made for token re-ranging broken for token "${parseTokens[currParseToken].text}"`); } parseTokens[currParseToken].endTokenIndex = preprocInfo.postTokens[i].endIndex; currParseToken++; tokenText = ""; } } return [parseTokens, tokenOrder, preprocInfo.symbols]; } catch (error) { genutils_1.ConnectionLogger.error(error); return [[], [], []]; } } _getElem(list, index) { let _index = (index == undefined) ? list.length - 1 : index; return (list.length > _index) && (_index >= 0) ? list[_index] : undefined; } _getTokenOrderIndex(token) { let tokenOrderIndex; for (let i = this._tokenOrder.length - 1; i >= 0; i--) { if (token >= this._tokenOrder[i].tokenNum) { tokenOrderIndex = i; break; } } return tokenOrderIndex; } _getEndPosition(token) { let _token = token == undefined ? this._currTokenNum : token; let tokenOrderIndex = this._getTokenOrderIndex(_token); if (tokenOrderIndex == undefined) { genutils_1.ConnectionLogger.error(`Could not figure out the source file for the given token. Falling back to default`); let endPos = this._document.positionAt(this._svtokens[_token].endTokenIndex); return { line: endPos.line, character: endPos.character }; } let document = this._getDocumentFromTokenOrderIndex(tokenOrderIndex); if (document == undefined) { genutils_1.ConnectionLogger.error(`Could not figure out the source file for the given token. Falling back to default`); let endPos = this._document.positionAt(this._svtokens[_token].endTokenIndex); return { line: endPos.line, character: endPos.character }; } let refDocumentPath = this._containerStack.getContainerDocumentPath(document.uri); let endPos = (this._document.uri == refDocumentPath) ? this._document.positionAt(this._svtokens[_token].endTokenIndex) : document.positionAt(this._svtokens[_token].endTokenIndex); return (this._document.uri == refDocumentPath) ? { line: endPos.line, character: endPos.character } : { file: refDocumentPath, line: endPos.line, character: endPos.character }; } _getDefLocations(startToken, endToken) { let tokenOrderIndex = this._getTokenOrderIndex(startToken); if (tokenOrderIndex == undefined) { genutils_1.ConnectionLogger.error(`Could not figure out the source file for the given range. Falling back to default`); return node_1.Range.create(this._document.positionAt(this._svtokens[startToken].startTokenIndex), this._document.positionAt(this._svtokens[endToken].endTokenIndex + 1)); } let tokenOrderIndices = [tokenOrderIndex]; tokenOrderIndex++; while ((tokenOrderIndex < this._tokenOrder.length) && (endToken >= this._tokenOrder[tokenOrderIndex].tokenNum)) { tokenOrderIndices.push(tokenOrderIndex); tokenOrderIndex++; } let document = this._getDocumentFromTokenOrderIndex(tokenOrderIndices[0]); if (document == undefined) { genutils_1.ConnectionLogger.error(`Could not find the document for the given range. Falling back to default`); return node_1.Range.create(this._document.positionAt(this._svtokens[startToken].startTokenIndex), this._document.positionAt(this._svtokens[endToken].endTokenIndex + 1)); } let defLocations = (this._document.uri == document.uri) ? [] : [document.uri]; let currToken = startToken; for (let i = 1; i < tokenOrderIndices.length; i++) { defLocations.push(node_1.Range.create(document.positionAt(this._svtokens[currToken].startTokenIndex), document.positionAt(this._svtokens[this._tokenOrder[tokenOrderIndices[i]].tokenNum - 1].endTokenIndex + 1))); currToken = this._tokenOrder[tokenOrderIndices[i]].tokenNum; } defLocations.push(node_1.Range.create(document.positionAt(this._svtokens[currToken].startTokenIndex), document.positionAt(this._svtokens[endToken].endTokenIndex + 1))); if (defLocations.length == 1) { defLocations = defLocations[0]; } return defLocations; } _getDocumentFromTokenOrderIndex(tokenOrderIndex) { let document; let file = this._documentPath; if (tokenOrderIndex == undefined) { genutils_1.ConnectionLogger.error(`Could not figure out the source file for the given range. Falling back to default`); return undefined; } else { file = this._tokenOrder[tokenOrderIndex].file; } if (file == this._documentPath) { document = this._document; } else { let shortFile; for (let [sfile, fileInfo] of this._preprocCache) { if (fileInfo.file == file) { shortFile = sfile; break; } } if (shortFile) { document = this._preprocCache.get(shortFile).doc; } else { genutils_1.ConnectionLogger.error(`Could not find include cache for ${file}`); return undefined; } } return document; } _createSymbol(symToken, symbolType, tokenRange, symbolText) { let document = this._getDocumentFromTokenOrderIndex(this._getTokenOrderIndex(symToken)); if (document == undefined) { return; } let symbolName = symbolText || this._svtokens[symToken].text; let symbolRange = node_1.Range.create(document.positionAt(this._svtokens[symToken].startTokenIndex), document.positionAt(this._svtokens[symToken].endTokenIndex + 1)); return new svsymbol_1.SystemVerilogSymbol(symbolName, tokenRange ? this._getDefLocations(tokenRange[0], tokenRange[1]) : undefined, document.uri == this._document.uri ? symbolRange : [document.uri, symbolRange], this._containerStack.toStringList(), symbolType); } _pushSymbol(symToken, symbolType, tokenRange, symbolText) { let symbol = this._createSymbol(symToken, symbolType, tokenRange, symbolText); symbol = this._containerStack.pushSymbol(symbol); return symbol; } _pushContainerSymbol(symToken, symbolType, tokenRange, symbolText) { let containerSymbol = this._createSymbol(symToken, symbolType, tokenRange, symbolText); containerSymbol = this._containerStack.push(containerSymbol); return containerSymbol; } _notIgnorableScope() { let scope = this._getElem(this._svtokens[this._currTokenNum].scopes); return (scope != "comment.block.systemverilog") && (scope != "comment.line.systemverilog") && (scope != "meta.whitespace.systemverilog"); } _nextNonIgnorableScope() { this._currTokenNum++; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { if (this._notIgnorableScope()) { return this._currTokenNum; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } return undefined; } _printDebugInfo(blockId) { if (DEBUG_MODE != 1) { return; } let pos = this._document.positionAt(this._svtokens[this._currTokenNum].startTokenIndex); genutils_1.ConnectionLogger.log(`DEBUG: Found ${blockId} at ${pos.line}, ${pos.character}`); } _processTypeReference() { let typeName = "#Unknown"; let typeToken = this._currTokenNum; let scopeDepth = this._svtokens[typeToken].scopes.length - 1; this._nextNonIgnorableScope(); let prevToken; let simpleIdExpression = false; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { if ((this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "parantheses.begin.systemverilog") && (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "parantheses.block.systemverilog")) { this._currTokenNum--; break; } if (this._notIgnorableScope()) { let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1); if (scope.startsWith("identifier.")) { simpleIdExpression = (prevToken == undefined); prevToken = this._currTokenNum; } else if ((scope != undefined) && (scope != "parantheses.end.systemverilog")) { simpleIdExpression = false; prevToken = this._currTokenNum; } } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } else if (simpleIdExpression) { typeName = this._svtokens[prevToken].text; } return typeName; } _processGenericPortList(scopesList, portType) { let genericPortSymbol; let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1; this._currTokenNum++; let startToken; let endToken; let prevIdToken; let prevToken; let portDataType; let portDataTypeToken; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { if (scopesList.indexOf(this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth)) < 0) { this._currTokenNum--; break; } let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1); if (this._notIgnorableScope()) { if (startToken != undefined) { if (endToken != undefined) { if ((scope == "operator.comma.systemverilog") || (scope == "operator.close_parantheses.systemverilog")) { genericPortSymbol.defLocations = this._getDefLocations(startToken, prevToken); startToken = undefined; endToken = undefined; genericPortSymbol = undefined; } } else { if ((scope == "operator.equals.systemverilog") || (scope == "operator.comma.systemverilog") || (scope == "operator.close_parantheses.systemverilog")) { let types = [portType].concat(portDataType || (portDataTypeToken == undefined ? [] : this._svtokens[portDataTypeToken].text)); genericPortSymbol = this._pushSymbol(prevIdToken, types, [startToken, prevToken]); if (scope != "operator.equals.systemverilog") { startToken = undefined; endToken = undefined; genericPortSymbol = undefined; portDataType = undefined; portDataTypeToken = undefined; } else { endToken = prevToken; } } else if (scope == "keyword.struct_union.systemverilog") { portDataType = this._processStructUnionDeclaration(); } else if (scope == "keyword.enum.systemverilog") { portDataType = this._processEnumDeclaration(); } else if (scope.startsWith("identifier.") && (this._svtokens[this._currTokenNum].text == "type")) { portDataType = this._processTypeReference(); } } } else { startToken = this._currTokenNum; } if (scope.startsWith("identifier.")) { portDataTypeToken = prevIdToken; prevIdToken = this._currTokenNum; } prevToken = this._currTokenNum; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } if (genericPortSymbol) { genericPortSymbol.defLocations = this._getDefLocations(startToken, prevToken); } } _processParameterPortList() { this._processGenericPortList(["parameter.list.systemverilog", "parameter.expression.systemverilog"], "parameter-port"); } _processPortList() { this._processGenericPortList(["port.list.systemverilog", "port.expression.systemverilog"], "port"); } _processContainerHeader() { //TBD Anonymous program? let containerSymbol; let containerTypeToken = this._currTokenNum; let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1; if (this._svtokens[containerTypeToken].scopes[scopeDepth] != "keyword.container.systemverilog") { return false; } this._printDebugInfo("container header"); this._currTokenNum++; let paramPortListProcessed = false; let portListProcessed = false; let prevToken; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { if (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "container.header.systemverilog") { this._currTokenNum--; break; } let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1); if (containerSymbol) { if ((scope == "keyword.import.systemverilog") && !paramPortListProcessed && !portListProcessed) { this._processImportExport(); } else if (scope == "operator.hash_open_parantheses.systemverilog" && !paramPortListProcessed && !portListProcessed) { this._processParameterPortList(); paramPortListProcessed = true; } else if (scope == "operator.open_parantheses.systemverilog" && !portListProcessed) { this._processPortList(); portListProcessed = true; } } else { if ((scope == "identifier.simple.systemverilog") || (scope == "identifier.escaped.systemverilog")) { if ((this._svtokens[this._currTokenNum].text != "static") && (this._svtokens[this._currTokenNum].text != "automatic")) { containerSymbol = this._pushContainerSymbol(this._currTokenNum, [this._svtokens[containerTypeToken].text]); } } } if (this._notIgnorableScope()) { prevToken = this._currTokenNum; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } if (containerSymbol) { containerSymbol.defLocations = this._getDefLocations(containerTypeToken, prevToken); } return true; } _processPackageHeader() { let packageSymbol; let packageKeywordToken = this._currTokenNum; let scopeDepth = this._svtokens[packageKeywordToken].scopes.length - 1; if (this._svtokens[packageKeywordToken].scopes[scopeDepth] != "keyword.package.systemverilog") { return false; } this._printDebugInfo("package header"); this._currTokenNum++; let prevToken; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { if (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "package.header.systemverilog") { this._currTokenNum--; break; } let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1); if (((scope == "identifier.simple.systemverilog") || (scope == "identifier.escaped.systemverilog")) && (this._svtokens[this._currTokenNum].text != "static") && (this._svtokens[this._currTokenNum].text != "automatic")) { packageSymbol = this._pushContainerSymbol(this._currTokenNum, [this._svtokens[packageKeywordToken].text]); } if (this._notIgnorableScope()) { prevToken = this._currTokenNum; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } if (packageSymbol) { packageSymbol.defLocations = this._getDefLocations(packageKeywordToken, prevToken); } return true; } _processRoutineHeader() { let routineSymbol; let routineTypeToken = this._currTokenNum; let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1; this._currTokenNum++; let portListProcessed = false; let prevIdToken; let prevToken; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { if (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "routine.header.systemverilog") { this._currTokenNum--; break; } if (portListProcessed) { continue; } let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1); if ((scope == "operator.open_parantheses.systemverilog") || (scope == "operator.semicolon.systemverilog")) { //ConnectionLogger.log(`DEBUG: Processing routine ${this._svtokens[prevIdToken].text}`); routineSymbol = this._pushContainerSymbol(prevIdToken, [this._svtokens[routineTypeToken].text]); if (scope == "operator.open_parantheses.systemverilog") { this._processPortList(); portListProcessed = true; } } else if ((scope == "identifier.simple.systemverilog") || (scope == "identifier.escaped.systemverilog")) { prevIdToken = this._currTokenNum; } if (this._notIgnorableScope()) { prevToken = this._currTokenNum; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } if (routineSymbol) { routineSymbol.defLocations = this._getDefLocations(routineTypeToken, prevToken); } } _processEndIdentifier() { let _currTokenNum = this._currTokenNum; this._currTokenNum--; let nextToken = this._nextNonIgnorableScope(); let scopeDepth = (nextToken != undefined) ? this._svtokens[nextToken].scopes.length - 1 : 0; if ((nextToken != undefined) && (this._svtokens[nextToken].scopes[scopeDepth] == "operator.ternary.systemverilog") && (this._svtokens[nextToken].text == ":")) { nextToken = this._nextNonIgnorableScope(); if ((nextToken == undefined) || ((this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "identifier.simple.systemverilog") && (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "identifier.escaped.systemverilog"))) { this._currTokenNum = _currTokenNum; return false; } return true; } else { this._currTokenNum = _currTokenNum; return false; } } _processStartIdentifier() { let _currTokenNum = this._currTokenNum; this._currTokenNum--; let startToken = this._nextNonIgnorableScope(); if (startToken == undefined) { this._currTokenNum = _currTokenNum; return false; } let scopeDepth = this._svtokens[startToken].scopes.length - 1; if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") && (this._svtokens[startToken].scopes[scopeDepth] != "identifier.escaped.systemverilog")) { this._currTokenNum = _currTokenNum; return false; } let nextToken = this._nextNonIgnorableScope(); if ((nextToken == undefined) || (this._getElem(this._svtokens[nextToken].scopes, scopeDepth) != "operator.ternary.systemverilog") || (this._svtokens[nextToken].text != ":")) { this._currTokenNum = _currTokenNum; return false; } nextToken = this._nextNonIgnorableScope(); if (nextToken == undefined) { this._currTokenNum = _currTokenNum; return false; } return true; } _processDimension() { let _currTokenNum = this._currTokenNum; let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1; this._currTokenNum++; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth); if (scope == undefined) { this._currTokenNum = _currTokenNum; return false; } else if (scope != "dimension.expression.systemverilog") { this._currTokenNum--; break; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } return true; } _processParamPortDeclaration() { let _currTokenNum = this._currTokenNum; let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1; this._currTokenNum++; let nextToken = this._nextNonIgnorableScope(); if ((nextToken == undefined) || (this._getElem(this._svtokens[nextToken].scopes, scopeDepth) != "parantheses.begin.systemverilog")) { this._currTokenNum = _currTokenNum; return false; } this._currTokenNum++; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth); if (scope == undefined) { this._currTokenNum = _currTokenNum; return false; } else if (scope != "parantheses.block.systemverilog") { this._currTokenNum--; break; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } return true; } /* = ["const"] ["var"] ["static"|"automatic"] integer_vector_type ["signed"|"unsigned"] {packed_dimension} {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] integer_atom_type ["signed"|unsigned"] {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] non_integer_type {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] struct_union ["packed"] ["signed"|"unsigned"] "{" struct_union_member {"," struct_union_member} "}" {packed_dimension} {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] "string"|"chandle" {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] "virtual" ["interface"] interface_identifier [parameter_value_assignment] ["." modport_identifier] {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] [class_scope|package_scope] type_identifier {packed_dimension} {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] ps_class_identifier [parameter_value_assignment] {"::" class_identifier [parameter_value_asisgnment]} {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] "event" {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] ps_covergroup_identifier {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] "type" "("...")" {list_of_variable_decl_assignments} ";" | ["const"] ["var"] ["static"|"automatic"] ["signed"|"unsigned"] {packed_dimension} {list_of_variable_decl_assignments} ";" | "typedef" ... | "nettype" ... */ _processRoutineVarDeclaration() { let _currTokenNum = this._currTokenNum; let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1; this._printDebugInfo("var declaration"); let startToken; let prevToken; let prevIdToken; let anonTypeName; let dataTypeToken; let waitForEnd = false; let symbolPushed = false; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth); if (scope == undefined) { this._currTokenNum = _currTokenNum; return false; } if (this._notIgnorableScope()) { if (this._processPreprocessor() || this._processAttributeInstance()) { continue; } if (startToken == undefined) { startToken = this._currTokenNum; if (["assign", "unique", "unique0", "priority", "case", "casex", "casez", "if", "void", "disable", "forever", "repeat", "while", "for", "do", "foreach", "return", "break", "continue", "fork", "begin", "wait", "wait_order", "assert", "assume", "cover", "restrict", "randcase", "randsequence", "expect"].indexOf(this._svtokens[startToken].text) >= 0) { this._currTokenNum = _currTokenNum; return false; } } if ((scope == "operator.comma.systemverilog") || (scope == "operator.semicolon.systemverilog")) { waitForEnd = false; if ((prevIdToken != undefined) && (startToken != undefined)) { if (prevIdToken == startToken) { this._currTokenNum = _currTokenNum; return false; } let types = ["variable", anonTypeName || (dataTypeToken == undefined ? this._svtokens[startToken].text : this._svtokens[dataTypeToken].text)]; this._pushSymbol(prevIdToken, types, [startToken, prevToken]); //TBD range symbolPushed = true; } else { this._currTokenNum = _currTokenNum; return false; } prevToken = undefined; if (scope == "operator.semicolon.systemverilog") { break; } } else if (!waitForEnd) { if (scope == "operator.equals.systemverilog") { waitForEnd = true; } else if (scope == "keyword.struct_union.systemverilog") { anonTypeName = this._processStructUnionDeclaration(); } else if (scope == "keyword.enum.systemverilog") { anonTypeName = this._processEnumDeclaration(); } else if (scope.startsWith("identifier.") && (this._svtokens[this._currTokenNum].text == "type")) { anonTypeName = this._processTypeReference(); } else if (scope.startsWith("identifier.")) { dataTypeToken = prevIdToken; prevIdToken = this._currTokenNum; } else if (scope == "operator.open_bracket.systemverilog") { if (!this._processDimension()) { this._currTokenNum = _currTokenNum; return false; } } else if ((scope == "operator.other.systemverilog") && (this._svtokens[this._currTokenNum].text == "#")) { if (!this._processParamPortDeclaration()) { this._currTokenNum = _currTokenNum; return false; } } else if (symbolPushed) { this._ignoreTillSemiColon(); return true; } else { this._currTokenNum = _currTokenNum; return false; } } prevToken = this._currTokenNum; } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } return true; } _processRoutineBody() { this._currTokenNum++; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { let scope = this._getElem(this._svtokens[this._currTokenNum].scopes); if (this._notIgnorableScope()) { //ConnectionLogger.log(`DEBUG: Routine body parsing at ${this._svtokens[this._currTokenNum].text}`); if ((scope == "identifier.simple.systemverilog") && ((this._svtokens[this._currTokenNum].text == "endfunction") || (this._svtokens[this._currTokenNum].text == "endtask"))) { this._containerStack.pop(this._getEndPosition()); break; } if (!this._processRoutineVarDeclaration() && !this._processParamDeclaration()) { //ConnectionLogger.log(`DEBUG: Routine ignoring statement at ${this._svtokens[this._currTokenNum].text}`); this._currTokenNum--; this._ignoreStatement(); continue; } } } if (this._currTokenNum == this._svtokens.length) { this._currTokenNum--; } else { this._processEndIdentifier(); } } _processRoutine() { let startToken = this._currTokenNum; let scopeDepth = this._svtokens[startToken].scopes.length - 1; if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.routine.systemverilog") { return false; } this._printDebugInfo("routine"); this._processRoutineHeader(); this._processRoutineBody(); return true; } _processParamDeclaration() { let parameterTypeToken = this._currTokenNum; let scopeDepth = this._svtokens[parameterTypeToken].scopes.length - 1; if (this._svtokens[parameterTypeToken].scopes[scopeDepth] != "keyword.parameter.systemverilog") { return false; } this._printDebugInfo("param declaration"); this._currTokenNum++; let parameterSymbol; let prevIdToken; let prevToken; let paramDataType; let paramDataTypeToken; for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) { if ((this._svtokens[this._currTokenNum].scopes.length <= scopeDepth) || ((this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "parameter.declaration.systemverilog") && (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "parameter.expression.systemverilog"))) { this._currTokenNum--; break; } let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1); if (this._notIgnorableScope()) { if (!parameterSymbol) { if ((scope == "operator.equals.systemverilog") || (scope == "operator.semicolon.syst