@imc-trading/svlangserver
Version:
A language server for systemverilog
1,012 lines • 144 kB
JavaScript
"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