"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.systemverilog")) {
                        let types = [this._svtokens[parameterTypeToken].text].concat(paramDataType || (paramDataTypeToken == undefined ? [] : this._svtokens[paramDataTypeToken].text));
                        parameterSymbol = this._pushSymbol(prevIdToken, types);
                    }
                    else if (scope == "keyword.struct_union.systemverilog") {
                        paramDataType = this._processStructUnionDeclaration();
                    }
                    else if (scope == "keyword.enum.systemverilog") {
                        paramDataType = this._processEnumDeclaration();
                    }
                    else if (scope.startsWith("identifier.") && (this._svtokens[this._currTokenNum].text == "type")) {
                        paramDataType = this._processTypeReference();
                    }
                    else if (scope.startsWith("identifier.")) {
                        paramDataTypeToken = prevIdToken;
                        prevIdToken = this._currTokenNum;
                    }
                }
                prevToken = this._currTokenNum;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        if (parameterSymbol) {
            parameterSymbol.defLocations = this._getDefLocations(parameterTypeToken, prevToken);
        }
        return true;
    }
    _processModPortDeclaration() {
        let modportKeywordToken = this._currTokenNum;
        let scopeDepth = this._svtokens[modportKeywordToken].scopes.length - 1;
        if (this._svtokens[modportKeywordToken].scopes[scopeDepth] != "keyword.modport.systemverilog") {
            return false;
        }
        this._printDebugInfo("modport declaration");
        this._currTokenNum++;
        let modportToken;
        let modportSymbol;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "modport.declaration.systemverilog") {
                this._currTokenNum--;
                break;
            }
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if ((scope == "operator.semicolon.systemverilog")) {
                    break;
                }
                else {
                    if (modportToken != undefined) {
                        if (scope == "operator.open_parantheses.systemverilog") {
                            this._processPortList(); //TBD handle import_export functions
                            this._containerStack.pop(this._getEndPosition());
                            modportSymbol.defLocations = this._getDefLocations(modportToken, this._currTokenNum),
                                modportToken = undefined;
                        }
                    }
                    else {
                        if ((scope == "identifier.simple.systemverilog") || (scope == "identifier.escaped.systemverilog")) {
                            modportToken = this._currTokenNum;
                            modportSymbol = this._pushContainerSymbol(modportToken, [this._svtokens[modportKeywordToken].text]);
                        }
                    }
                }
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        if (modportToken != undefined) {
            this._containerStack.pop(this._getEndPosition());
            modportSymbol.defLocations = this._getDefLocations(modportToken, this._currTokenNum);
        }
        return true;
    }
    _processStructUnionMemberList() {
        let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1 - 1;
        this._currTokenNum++;
        let startToken;
        let memberToken;
        let prevIdToken;
        let prevToken;
        let memberSymbol;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if ((this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "struct_union_member_list.body.systemverilog") &&
                (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "struct_union_member.expression.systemverilog")) {
                this._currTokenNum--;
                break;
            }
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if (startToken == undefined) {
                    startToken = this._currTokenNum;
                    if (scope == "keyword.struct_union.systemverilog") {
                        //let anonTypeName: string = this._processStructUnionDeclaration();
                        this._processStructUnionDeclaration();
                        continue;
                    }
                    else if (scope == "keyword.enum.systemverilog") {
                        //let anonTypeName: string = this._processEnumDeclaration();
                        this._processEnumDeclaration();
                        continue;
                    }
                }
                if (scope == "operator.equals.systemverilog") {
                    memberSymbol = this._pushSymbol(prevIdToken, ["struct_union_member"]);
                    memberToken = prevIdToken;
                }
                else if (scope == "operator.semicolon.systemverilog") {
                    if (memberToken != undefined) {
                        memberSymbol.defLocations = this._getDefLocations(startToken, prevToken);
                        memberToken = undefined;
                    }
                    else {
                        memberSymbol = this._pushSymbol(prevIdToken, ["struct_union_member"], [startToken, prevToken]);
                    }
                    startToken = undefined;
                }
                else if ((scope == "identifier.simple.systemverilog") || (scope == "identifier.escaped.systemverilog")) {
                    prevIdToken = this._currTokenNum;
                }
                prevToken = this._currTokenNum;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        if (memberToken != undefined) {
            memberSymbol.defLocations = this._getDefLocations(startToken, prevToken);
        }
    }
    _processStructUnionDeclaration() {
        let structUnionTypeToken = this._currTokenNum;
        let scopeDepth = this._svtokens[structUnionTypeToken].scopes.length - 1;
        this._currTokenNum++;
        let structUnionName = `#AnonymousStructUnion${this._anonStructUnionCount}`;
        let structSymbol = this._pushContainerSymbol(structUnionTypeToken, [this._svtokens[structUnionTypeToken].text], undefined, structUnionName);
        this._anonStructUnionCount++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "struct_union.declaration.systemverilog") {
                this._currTokenNum--;
                break;
            }
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if (scope == "struct_union_member_list.begin.systemverilog") {
                    this._processStructUnionMemberList();
                }
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        this._containerStack.pop(this._getEndPosition());
        structSymbol.defLocations = this._getDefLocations(structUnionTypeToken, this._currTokenNum);
        return structUnionName;
    }
    _processEnumList(enumName) {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1 - 1;
        this._currTokenNum++;
        let memberToken;
        let prevToken;
        let memberSymbol;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if ((this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "enum_list.body.systemverilog") &&
                (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "enum.expression.systemverilog")) {
                this._currTokenNum--;
                break;
            }
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if ((scope == "identifier.simple.systemverilog") || (scope == "identifier.escaped.systemverilog")) {
                    if (memberToken == undefined) {
                        memberToken = this._currTokenNum;
                        memberSymbol = this._pushSymbol(memberToken, ["enum_member", enumName]);
                    }
                }
                else if ((scope == "operator.comma.systemverilog") ||
                    (scope == "enum_list.end.systemverilog")) {
                    if (memberToken != undefined) {
                        memberSymbol.defLocations = this._getDefLocations(memberToken, prevToken),
                            memberToken = undefined;
                    }
                }
                prevToken = this._currTokenNum;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        if (memberToken != undefined) {
            memberSymbol.defLocations = this._getDefLocations(memberToken, prevToken);
        }
    }
    _processEnumDeclaration() {
        let enumKeywordToken = this._currTokenNum;
        let scopeDepth = this._svtokens[enumKeywordToken].scopes.length - 1;
        this._currTokenNum++;
        let enumName = `#AnonymousEnum${this._anonEnumCount}`;
        this._anonEnumCount++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "enum.declaration.systemverilog") {
                this._currTokenNum--;
                break;
            }
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if (scope == "enum_list.begin.systemverilog") {
                    this._processEnumList(enumName);
                }
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        return enumName;
    }
    _processTypeDef() {
        let typedefKeywordToken = this._currTokenNum;
        let scopeDepth = this._svtokens[typedefKeywordToken].scopes.length - 1;
        if (this._svtokens[typedefKeywordToken].scopes[scopeDepth] != "keyword.typedef.systemverilog") {
            return false;
        }
        this._printDebugInfo("typedef");
        this._currTokenNum++;
        let prevIdToken;
        let prevToken;
        let typedefSymbol;
        let anonTypeName;
        let typeToken;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "typedef.declaration.systemverilog") {
                this._currTokenNum--;
                break;
            }
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if (scope == "operator.semicolon.systemverilog") {
                    typedefSymbol = this._pushSymbol(prevIdToken, [this._svtokens[typedefKeywordToken].text].concat([anonTypeName || (typeToken == undefined ? "#Unknown" : this._svtokens[typeToken].text)]));
                }
                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.")) {
                    typeToken = prevIdToken;
                    prevIdToken = this._currTokenNum;
                }
                prevToken = this._currTokenNum;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        if (typedefSymbol) {
            typedefSymbol.defLocations = this._getDefLocations(typedefKeywordToken, prevToken);
        }
        return true;
    }
    _ignoreBlockStatement(validScopes) {
        let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1;
        this._currTokenNum++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            //ConnectionLogger.log(`DEBUG: HERE with scopeDepth=${scopeDepth} with validScopes=[${validScopes.join(',')}] and for token "${this._svtokens[this._currTokenNum].text}" and scopes [${this._svtokens[this._currTokenNum].scopes.join(', ')}]`);
            if (validScopes.indexOf(this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth)) < 0) {
                this._currTokenNum--;
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
    }
    _ignoreParanthesizedExpression() {
        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 == "parantheses.begin.systemverilog") {
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
            return;
        }
        this._currTokenNum++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth);
            if (scope != "parantheses.block.systemverilog") {
                this._currTokenNum--;
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
    }
    _ignoreTillSemiColon() {
        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 == "operator.semicolon.systemverilog") {
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
    }
    _ignoreTillColon() {
        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 == "operator.ternary.systemverilog") && (this._svtokens[this._currTokenNum].text == ":")) {
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
    }
    _ignoreActionBlock() {
        let _currTokenNum = this._currTokenNum;
        let nextToken = this._nextNonIgnorableScope();
        if ((nextToken != undefined) && (this._getElem(this._svtokens[nextToken].scopes) == "identifier.simple.systemverilog") && (this._svtokens[nextToken].text == "else")) {
            this._ignoreStatement();
        }
        else {
            this._currTokenNum = _currTokenNum;
            this._ignoreStatement();
            _currTokenNum = this._currTokenNum;
            nextToken = this._nextNonIgnorableScope();
            if ((nextToken != undefined) && (this._getElem(this._svtokens[nextToken].scopes) == "identifier.simple.systemverilog") && (this._svtokens[nextToken].text == "else")) {
                this._ignoreStatement();
            }
            else {
                this._currTokenNum = _currTokenNum;
            }
        }
    }
    _ignoreStatement() {
        this._currTokenNum++;
        this._processStartIdentifier();
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes);
            let tokenText = this._svtokens[this._currTokenNum].text;
            if (this._notIgnorableScope()) {
                if (scope == "keyword.case.systemverilog") {
                    this._ignoreBlockStatement(["case.body.systemverilog"]);
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "if")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreStatement();
                    let _currTokenNum = this._currTokenNum;
                    let nextToken = this._nextNonIgnorableScope();
                    if ((nextToken != undefined) && (this._getElem(this._svtokens[nextToken].scopes) == "identifier.simple.systemverilog") && (this._svtokens[nextToken].text == "else")) {
                        this._currTokenNum++;
                        this._ignoreStatement();
                    }
                    else {
                        this._currTokenNum = _currTokenNum;
                    }
                    break;
                }
                else if (scope == "keyword.disable.systemverilog") {
                    this._ignoreTillSemiColon();
                    break;
                }
                else if (scope == "operator.trigger.systemverilog") {
                    this._ignoreTillSemiColon();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "forever")) {
                    this._ignoreStatement();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "repeat")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreStatement();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "while")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreStatement();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "for")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreStatement();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "do")) {
                    this._ignoreStatement();
                    this._ignoreStatement();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "foreach")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreStatement();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") &&
                    ((tokenText == "return") || (tokenText == "break") || (tokenText == "continue"))) {
                    this._ignoreTillSemiColon();
                    break;
                }
                else if (scope == "keyword.fork.systemverilog") {
                    this._ignoreBlockStatement(["fork.body.systemverilog"]);
                    break;
                }
                else if (scope == "keyword.begin.systemverilog") {
                    this._ignoreBlockStatement(["begin.block.systemverilog"]);
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "wait")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreStatement();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "wait_order")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreActionBlock();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "assert")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreActionBlock();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "assume")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreActionBlock();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "cover")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreActionBlock();
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "restrict")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreTillSemiColon();
                    break;
                }
                else if (scope == "keyword.randsequence.systemverilog") {
                    this._ignoreBlockStatement(["randsequence.body.systemverilog"]);
                    break;
                }
                else if ((scope == "identifier.simple.systemverilog") && (tokenText == "expect")) {
                    this._ignoreParanthesizedExpression();
                    this._ignoreActionBlock();
                    break;
                }
                else if (scope == "operator.semicolon.systemverilog") {
                    break;
                }
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
    }
    _processPreprocessor() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "macro.call.systemverilog") &&
            (this._svtokens[startToken].scopes[scopeDepth] != "macro.identifier.systemverilog")) {
            return false;
        }
        this._printDebugInfo("preprocessor");
        if (this._svtokens[startToken].scopes[scopeDepth] == "macro.identifier.systemverilog") {
            if (this._svtokens[startToken].text == "`include") {
                //TBD store include file
                let nextToken = this._nextNonIgnorableScope();
                if (nextToken != undefined) {
                    if (this._getElem(this._svtokens[nextToken].scopes, scopeDepth) == "operator.comparison.systemverilog") {
                        nextToken = this._nextNonIgnorableScope();
                        if (nextToken != undefined) {
                            this._nextNonIgnorableScope();
                        }
                    }
                }
            }
            else if ((this._svtokens[startToken].text == "`define") || (this._svtokens[startToken].text == "`pragma")) {
                // treating `pragma as single lined statements (otherwise ambiguous processing)
                //skip till end of line without "\"
                this._currTokenNum++;
                for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
                    let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth);
                    if ((scope == "meta.whitespace.systemverilog") && (/\n|\r/.exec(this._svtokens[this._currTokenNum].text))) {
                        break;
                    }
                    else if (scope == "operator.backslash.systemverilog") {
                        this._currTokenNum++;
                        if ((this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) == "meta.whitespace.systemverilog") &&
                            ((this._svtokens[this._currTokenNum].text.startsWith("\n")) ||
                                (this._svtokens[this._currTokenNum].text.startsWith("\r")))) {
                            break;
                        }
                        else {
                            this._currTokenNum--;
                        }
                    }
                }
                if (this._currTokenNum == this._svtokens.length) {
                    this._currTokenNum--;
                }
            }
            else if (["`undef", "`ifdef", "`elsif", "`ifndef", "`default_nettype", "`unconnected_drive", "`begin_keywords"].indexOf(this._svtokens[startToken].text) >= 0) {
                this._nextNonIgnorableScope();
            }
            else if (this._svtokens[startToken].text == "`timescale") {
                this._currTokenNum++;
                let timePrecisionStart = false;
                for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
                    let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth);
                    if (this._notIgnorableScope()) {
                        if (timePrecisionStart) {
                            if (scope == "identifier.simple.systemverilog") {
                                break;
                            }
                            else if (scope == "literal.time.systemverilog") {
                                break;
                            }
                        }
                        else {
                            if (scope == "operator.arithmetic.systemverilog") {
                                timePrecisionStart = true;
                            }
                        }
                    }
                }
                if (this._currTokenNum == this._svtokens.length) {
                    this._currTokenNum--;
                }
            }
            else if (this._svtokens[startToken].text == "`line") {
                for (let i = 0; i < 3; i++) {
                    let nextToken = this._nextNonIgnorableScope();
                    if (nextToken == undefined) {
                        break;
                    }
                }
            }
            // ignore `undefineall, `else, `endif, `nounconnected_drive, `celldefine, `endcelldefine, `__FILE__, `__LINE__, `end_keywords and user macros
        }
        return true;
    }
    _processAttributeInstance() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "attribute.begin.systemverilog") {
            return false;
        }
        this._printDebugInfo("attribute instance");
        this._currTokenNum++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if ((this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "attribute.inst.systemverilog") &&
                (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "attribute.expression.systemverilog")) {
                this._currTokenNum--;
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        return true;
    }
    _processSimpleKeywords() {
        let keywordToken = this._currTokenNum;
        let scopeDepth = this._svtokens[keywordToken].scopes.length - 1;
        if ((this._svtokens[keywordToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (["endinterface", "endmodule", "endpackage", "endprogram"].indexOf(this._svtokens[keywordToken].text) < 0)) {
            return false;
        }
        this._printDebugInfo("simple keywords");
        if (["endinterface", "endmodule", "endpackage", "endprogram"].indexOf(this._svtokens[keywordToken].text) >= 0) {
            this._currTokenNum++;
            this._processEndIdentifier();
            if (this._currTokenNum == this._svtokens.length) {
                this._currTokenNum--;
            }
            this._containerStack.pop(this._getEndPosition());
        }
        return true;
    }
    _processPortDeclaration() {
        let portTypeToken = this._currTokenNum;
        let scopeDepth = this._svtokens[portTypeToken].scopes.length - 1;
        if (this._svtokens[portTypeToken].scopes[scopeDepth] != "keyword.port_direction.systemverilog") {
            return false;
        }
        this._printDebugInfo("port declaration");
        this._currTokenNum++;
        let prevIdToken;
        let startToken;
        let prevToken;
        let portDataType;
        let portDataTypeToken;
        let portSymbol;
        let assignExprOn = false;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            if ((this._svtokens[this._currTokenNum].scopes.length <= scopeDepth) ||
                (!assignExprOn && (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "port_declaration.list.systemverilog")) ||
                (assignExprOn && (this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth) != "port_declaration.expression.systemverilog"))) {
                this._currTokenNum--;
                break;
            }
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                //TBD: process port list
                if ((scope == "operator.comma.systemverilog") ||
                    (scope == "operator.semicolon.systemverilog")) {
                    if (assignExprOn) {
                        portSymbol.defLocations = this._getDefLocations(startToken, prevToken);
                        portSymbol = undefined;
                        assignExprOn = false;
                    }
                    else {
                        let types = ["port"].concat(portDataType || (portDataTypeToken == undefined ? [] : this._svtokens[portDataTypeToken].text));
                        this._pushSymbol(prevIdToken, types, [startToken, prevToken]);
                    }
                    startToken = undefined;
                }
                else if (scope == "operator.equals.systemverilog") {
                    let types = ["port"].concat(portDataType || (portDataTypeToken == undefined ? [] : this._svtokens[portDataTypeToken].text));
                    portSymbol = this._pushSymbol(prevIdToken, types);
                    assignExprOn = true;
                }
                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 if (scope.startsWith("identifier.")) {
                    portDataTypeToken = prevIdToken;
                    prevIdToken = this._currTokenNum;
                }
                prevToken = this._currTokenNum;
                if (startToken == undefined) {
                    startToken = this._currTokenNum;
                }
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        if (portSymbol) {
            portSymbol.defLocations = this._getDefLocations(portTypeToken, prevToken);
        }
        return true;
    }
    _processParameterOverride() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.defparam.systemverilog") {
            return false;
        }
        this._printDebugInfo("parameter override");
        this._ignoreBlockStatement(["defparam.statement.systemverilog"]);
        return true;
    }
    _processCheckerDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.checker.systemverilog") {
            return false;
        }
        this._printDebugInfo("checker declaration");
        this._ignoreBlockStatement(["checker.declaration.systemverilog"]);
        this._processEndIdentifier();
        return true;
    }
    _processImportExport() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "keyword.import.systemverilog") &&
            (this._svtokens[startToken].scopes[scopeDepth] != "keyword.export.systemverilog")) {
            return false;
        }
        this._printDebugInfo("import export");
        this._currTokenNum++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (scope == "identifier.scoped.systemverilog") {
                if (this._svtokens[startToken].scopes[scopeDepth] == "keyword.export.systemverilog") {
                    this._containerStack.pushExportItem(this._svtokens[this._currTokenNum]);
                }
                else {
                    this._containerStack.pushImportItem(this._svtokens[this._currTokenNum]);
                }
            }
            else if (scope == "operator.semicolon.systemverilog") {
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        return true;
    }
    _processExternConstraintDeclaration() {
        let _currTokenNum = this._currTokenNum;
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] == "identifier.simple.systemverilog") && (this._svtokens[startToken].text == "static")) {
            let nextToken = this._nextNonIgnorableScope();
            if (nextToken != undefined) {
                startToken = nextToken;
                scopeDepth = this._svtokens[startToken].scopes.length - 1;
            }
            else {
                this._currTokenNum = _currTokenNum;
                return false;
            }
        }
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.constraint.systemverilog") {
            this._currTokenNum = _currTokenNum;
            return false;
        }
        this._printDebugInfo("constraint declaration");
        this._ignoreBlockStatement(["constraint.declaration.systemverilog", "constraint.body.systemverilog"]);
        this._processEndIdentifier();
        return true;
    }
    _processClassDeclaration() {
        let _currTokenNum = this._currTokenNum;
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] == "identifier.simple.systemverilog") && (this._svtokens[startToken].text == "virtual")) {
            let nextToken = this._nextNonIgnorableScope();
            if (nextToken != undefined) {
                startToken = nextToken;
                scopeDepth = this._svtokens[startToken].scopes.length - 1;
            }
            else {
                this._currTokenNum = _currTokenNum;
                return false;
            }
        }
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.class.systemverilog") {
            this._currTokenNum = _currTokenNum;
            return false;
        }
        this._printDebugInfo("class declaration");
        this._ignoreBlockStatement(["class.declaration.systemverilog"]);
        this._processEndIdentifier();
        return true;
    }
    _processCoverGroupDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.covergroup.systemverilog") {
            return false;
        }
        this._printDebugInfo("covergroup declaration");
        this._ignoreBlockStatement(["covergroup.declaration.systemverilog"]);
        this._processEndIdentifier();
        return true;
    }
    _processPropertyDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.property.systemverilog") {
            return false;
        }
        this._printDebugInfo("property declaration");
        this._ignoreBlockStatement(["property.declaration.systemverilog"]);
        this._processEndIdentifier();
        return true;
    }
    _processSequenceDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.sequence.systemverilog") {
            return false;
        }
        this._printDebugInfo("sequence declaration");
        this._ignoreBlockStatement(["sequence.declaration.systemverilog"]);
        this._processEndIdentifier();
        return true;
    }
    _processLetDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.let.systemverilog") {
            return false;
        }
        this._printDebugInfo("let declaration");
        this._ignoreBlockStatement(["let.statement.systemverilog"]);
        return true;
    }
    _processClockingDeclaration() {
        let _currTokenNum = this._currTokenNum;
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] == "identifier.simple.systemverilog") &&
            ((this._svtokens[startToken].text == "default") || (this._svtokens[startToken].text == "global"))) {
            let nextToken = this._nextNonIgnorableScope();
            if (nextToken != undefined) {
                startToken = nextToken;
                scopeDepth = this._svtokens[startToken].scopes.length - 1;
            }
            else {
                this._currTokenNum = _currTokenNum;
                return false;
            }
        }
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") || (this._svtokens[startToken].text != "clocking")) {
            this._currTokenNum = _currTokenNum;
            return false;
        }
        let nextToken = this._nextNonIgnorableScope();
        if (nextToken == undefined) {
            this._currTokenNum = _currTokenNum;
            return false;
        }
        else {
            startToken = nextToken;
            scopeDepth = this._svtokens[startToken].scopes.length - 1;
        }
        this._printDebugInfo("clocking declaration");
        let scope = this._getElem(this._svtokens[startToken].scopes, scopeDepth);
        if ((scope == "identifier.simple.systemverilog") || (scope == "identifier.escaped.systemverilog")) {
            nextToken = this._nextNonIgnorableScope();
            if (nextToken == undefined) {
                this._currTokenNum = _currTokenNum;
                return false;
            }
            else {
                startToken = nextToken;
                scopeDepth = this._svtokens[startToken].scopes.length - 1;
            }
            scope = this._getElem(this._svtokens[startToken].scopes, scopeDepth);
            if ((scope != "operator.other.systemverilog") || (this._svtokens[startToken].text != "@")) {
                this._currTokenNum--;
                this._ignoreTillSemiColon();
                return true;
            }
        }
        // clocking .. endclocking
        this._currTokenNum++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth);
            if ((scope == "identifier.simple.systemverilog") && (this._svtokens[this._currTokenNum].text == "endclocking")) {
                break;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        this._processEndIdentifier();
        return true;
    }
    _processDefaultDisableItem() {
        let _currTokenNum = this._currTokenNum;
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (this._svtokens[startToken].text != "default")) {
            return false;
        }
        else {
            let nextToken = this._nextNonIgnorableScope();
            if (nextToken != undefined) {
                startToken = nextToken;
                scopeDepth = this._svtokens[startToken].scopes.length - 1;
            }
            else {
                this._currTokenNum = _currTokenNum;
                return false;
            }
        }
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (this._svtokens[startToken].text != "disable")) {
            this._currTokenNum = _currTokenNum;
            return false;
        }
        this._printDebugInfo("default disable");
        this._ignoreTillSemiColon();
        return true;
    }
    _processAssertionStatement() {
        let _currTokenNum = this._currTokenNum;
        this._processStartIdentifier();
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        let startTokenText = this._svtokens[startToken].text;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            ["assert", "assume", "cover", "restrict"].indexOf(startTokenText) < 0) {
            this._currTokenNum = _currTokenNum;
            return false;
        }
        this._printDebugInfo("assertion statement");
        this._ignoreParanthesizedExpression();
        if ((startTokenText == "assert") || (startTokenText == "assume")) {
            this._ignoreActionBlock();
        }
        else {
            this._ignoreStatement();
        }
        return true;
    }
    _processBindDirective() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (this._svtokens[startToken].text != "bind")) {
            return false;
        }
        this._printDebugInfo("bind directive");
        this._ignoreTillSemiColon();
        return true;
    }
    _processContinuousAssign() {
        //TBD continuous assign lvalues extraction
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.assign.systemverilog") {
            return false;
        }
        this._printDebugInfo("continuous assignment");
        this._ignoreBlockStatement(["continuous.block.systemverilog", "continuous.expression.systemverilog"]);
        return true;
    }
    _processAlias() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (this._svtokens[startToken].text != "alias")) {
            return false;
        }
        this._printDebugInfo("alias");
        this._ignoreTillSemiColon();
        return true;
    }
    _processSequentialBlock() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (["always", "always_comb", "always_ff", "always_latch", "initial", "final"].indexOf(this._svtokens[startToken].text) < 0)) {
            return false;
        }
        this._printDebugInfo("sequential block");
        this._ignoreStatement();
        return true;
    }
    _processGenerateBlock() {
        //let _currTokenNum = this._currTokenNum;
        this._currTokenNum++;
        let startToken;
        if (this._processStartIdentifier()) {
            startToken = this._currTokenNum;
        }
        else {
            this._currTokenNum--;
            startToken = this._nextNonIgnorableScope();
            if (startToken == undefined) {
                return;
            }
        }
        let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1;
        if (this._getElem(this._svtokens[startToken].scopes, scopeDepth) == "keyword.begin.systemverilog") {
            this._printDebugInfo("generate block");
            this._currTokenNum++;
            if (this._processEndIdentifier()) {
                this._currTokenNum++;
            }
            for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
                let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
                if (this._notIgnorableScope()) {
                    if (scope == "keyword.end.systemverilog") {
                        this._currTokenNum++;
                        this._processEndIdentifier();
                        break;
                    }
                    if (this._processPreprocessor() ||
                        this._processAttributeInstance() ||
                        this._processGenerateItem() ||
                        this._processVarInstDeclaration()) {
                        continue;
                    }
                    //TBD Error on else?
                }
            }
            if (this._currTokenNum == this._svtokens.length) {
                this._currTokenNum--;
            }
        }
        else {
            this._printDebugInfo("generate statement");
            for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
                //let scope: string = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth);
                if (this._notIgnorableScope()) {
                    if (this._processPreprocessor() ||
                        this._processAttributeInstance()) {
                        continue;
                    }
                    if (this._processGenerateItem() ||
                        this._processVarInstDeclaration()) {
                    }
                    //TBD Error on else?
                    break;
                }
            }
            if (this._currTokenNum == this._svtokens.length) {
                this._currTokenNum--;
            }
        }
    }
    _processLoopGenerateConstruct() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (this._svtokens[startToken].text != "for")) {
            return false;
        }
        this._printDebugInfo("for generate");
        this._ignoreParanthesizedExpression();
        this._processGenerateBlock();
        return true;
    }
    _processIfGenerateConstruct() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (this._svtokens[startToken].text != "if")) {
            return false;
        }
        this._printDebugInfo("if generate");
        this._ignoreParanthesizedExpression();
        this._processGenerateBlock();
        let _currTokenNum = this._currTokenNum;
        let nextToken = this._nextNonIgnorableScope();
        if ((nextToken != undefined) && ((this._getElem(this._svtokens[nextToken].scopes, scopeDepth) == "identifier.simple.systemverilog") && (this._svtokens[nextToken].text == "else"))) {
            this._processGenerateBlock();
        }
        else {
            this._currTokenNum = _currTokenNum;
        }
        return true;
    }
    _processCaseGenerateConstruct() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._getElem(this._svtokens[startToken].scopes, scopeDepth) != "keyword.case.systemverilog") {
            return false;
        }
        this._printDebugInfo("case generate");
        this._currTokenNum++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if (scope == "keyword.endcase.systemverilog") {
                    break;
                }
                this._ignoreTillColon();
                this._processGenerateBlock();
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        return true;
    }
    _processEmptyStatement() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "operator.semicolon.systemverilog") {
            return false;
        }
        this._printDebugInfo("empty statement");
        this._currTokenNum++;
        return true;
    }
    _processNonStandardBeginEndBlock() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.begin.systemverilog") {
            return false;
        }
        this._printDebugInfo("non-standard begin-end block");
        this._currTokenNum++;
        if (this._processEndIdentifier()) {
            this._currTokenNum++;
        }
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if (scope == "keyword.end.systemverilog") {
                    this._currTokenNum++;
                    this._processEndIdentifier();
                    break;
                }
                if (this._processPreprocessor() ||
                    this._processAttributeInstance() ||
                    this._processGenerateItem() ||
                    this._processVarInstDeclaration()) {
                    continue;
                }
                //TBD Error on else?
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        return true;
    }
    _processExternTFDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "identifier.simple.systemverilog") ||
            (this._svtokens[startToken].text != "extern")) {
            return false;
        }
        this._printDebugInfo("extern tf declaration");
        let nextToken = this._nextNonIgnorableScope();
        while ((nextToken != undefined) && (this._getElem(this._svtokens[nextToken].scopes, scopeDepth) == "keyword.routine.systemverilog")) {
            nextToken = this._nextNonIgnorableScope();
        }
        if (nextToken != undefined) {
            this._ignoreBlockStatement(["routine.header.systemverilog"]);
        }
        return true;
    }
    _printParsingFailedMessage() {
        let pos = this._document.positionAt(this._svtokens[this._currTokenNum].startTokenIndex);
        genutils_1.ConnectionLogger.warn(`Parsing failed at token "${this._svtokens[this._currTokenNum].text}" (${pos.line}, ${pos.character}) with scopes [${this._svtokens[this._currTokenNum].scopes.join(",")}] in file ${this._documentPath}`);
    }
    _processGenerateRegion() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.generate.systemverilog") {
            return false;
        }
        this._printDebugInfo("generate region");
        this._currTokenNum++;
        for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
            let scope = this._getElem(this._svtokens[this._currTokenNum].scopes, scopeDepth + 1);
            if (this._notIgnorableScope()) {
                if (this._svtokens[this._currTokenNum].scopes.length <= scopeDepth) {
                    break;
                }
                if (scope == "keyword.endgenerate.systemverilog") {
                    break;
                }
                if (this._processPreprocessor() ||
                    this._processAttributeInstance() ||
                    this._processGenerateItem() ||
                    this._processVarInstDeclaration()) {
                    continue;
                }
                else {
                    this._printParsingFailedMessage();
                }
            }
        }
        return true;
    }
    _processElaborationSystemTask() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "system.identifier.systemverilog") &&
            (this._svtokens[startToken].scopes[scopeDepth] != "system.task.systemverilog")) {
            return false;
        }
        this._printDebugInfo("elab system task");
        this._ignoreTillSemiColon();
        return true;
    }
    _isDriveStrength() {
        let _startTokenNum = this._currTokenNum;
        let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1;
        let nextToken = this._nextNonIgnorableScope();
        if ((nextToken == undefined) || (this._getElem(this._svtokens[nextToken].scopes, scopeDepth + 1) != "identifier.simple.systemverilog") ||
            (["supply0", "supply1", "strong0", "strong1", "pull0", "pull1", "weak0", "weak1", "highz0", "highz1"].indexOf(this._svtokens[nextToken].text) < 0)) {
            this._currTokenNum = _startTokenNum;
            return false;
        }
        nextToken = this._nextNonIgnorableScope();
        if ((nextToken == undefined) || (this._getElem(this._svtokens[nextToken].scopes, scopeDepth + 1) != "operator.comma.systemverilog")) {
            this._currTokenNum = _startTokenNum;
            return false;
        }
        nextToken = this._nextNonIgnorableScope();
        if ((nextToken == undefined) || (this._getElem(this._svtokens[nextToken].scopes, scopeDepth + 1) != "identifier.simple.systemverilog") ||
            (["supply0", "supply1", "strong0", "strong1", "pull0", "pull1", "weak0", "weak1", "highz0", "highz1"].indexOf(this._svtokens[nextToken].text) < 0)) {
            this._currTokenNum = _startTokenNum;
            return false;
        }
        nextToken = this._nextNonIgnorableScope();
        if ((nextToken == undefined) || (this._getElem(this._svtokens[nextToken].scopes, scopeDepth + 1) != "parantheses.end.systemverilog")) {
            this._currTokenNum = _startTokenNum;
            return false;
        }
        return true;
    }
    //TBD nettype
    _isInstance() {
        let _startTokenNum = this._currTokenNum;
        let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1;
        // 1st token based decisions
        this._currTokenNum--;
        let startToken = this._nextNonIgnorableScope();
        if (startToken == undefined) {
            this._currTokenNum = _startTokenNum;
            return [undefined, undefined];
        }
        if (["supply0", "supply1", "tri", "triand", "trior", "trireg", "tri0", "tri1", "uwire", "wire", "wand", "wor",
            "interconnect", "const", "var", "static", "automatic", "rand", "genvar",
            "bit", "logic", "reg", "byte", "shortint", "int", "longint", "integer", "time",
            "shortreal", "real", "realtime", "struct", "union", "enum", "string", "chandle",
            "virtual", "interface", "event", "type"].indexOf(this._svtokens[startToken].text) >= 0) {
            this._currTokenNum = _startTokenNum;
            return [false, this._svtokens[startToken].text];
        }
        else if (["cmos", "rmos", "bufif0", "bufif1", "notif0", "notif1",
            "nmos", "pmos", "rnmos", "rpmos", "and", "nand", "or", "nor", "xor", "xnor", "buf", "not",
            "tranif0", "trainf1", "rtranif1", "rtranif0", "tran", "rtran", "pulldown", "pullup"].indexOf(this._svtokens[startToken].text) >= 0) {
            this._currTokenNum = _startTokenNum;
            return [true, this._svtokens[startToken].text];
        }
        let _currTokenNum = this._currTokenNum;
        let prevToken;
        for (; _currTokenNum < this._svtokens.length; _currTokenNum++) {
            let scope = this._getElem(this._svtokens[_currTokenNum].scopes, scopeDepth);
            if (this._notIgnorableScope()) {
                if ((prevToken != undefined) && (scope == "parantheses.begin.systemverilog") &&
                    ((this._getElem(this._svtokens[prevToken].scopes, scopeDepth) != "operator.other.systemverilog") ||
                        (this._svtokens[prevToken].text != "#"))) {
                    if (this._isDriveStrength()) {
                        this._currTokenNum = _startTokenNum;
                        return [true, this._svtokens[startToken].text];
                    }
                }
                else if ((scope == "operator.comma.systemverilog") || (scope == "operator.semicolon.systemverilog")) {
                    this._currTokenNum = _startTokenNum;
                    if ((prevToken != undefined) && this._getElem(this._svtokens[prevToken].scopes, scopeDepth) == "parantheses.block.systemverilog") {
                        return [true, this._svtokens[startToken].text];
                    }
                    else {
                        return [false, this._svtokens[startToken].text];
                    }
                }
                prevToken = _currTokenNum;
            }
        }
        this._currTokenNum == _startTokenNum;
        return [undefined, undefined];
    }
    _processVarInstDeclaration() {
        let _currTokenNum = this._currTokenNum;
        let scopeDepth = this._svtokens[this._currTokenNum].scopes.length - 1;
        //let [isInstance, type]: [Boolean, string] = this._isInstance();
        let isInstance = this._isInstance()[0];
        if (isInstance == undefined) {
            this._currTokenNum = _currTokenNum;
            return false;
        }
        this._printDebugInfo("var inst declaration");
        let symType = isInstance ? "instance" : "variable";
        let startToken;
        let prevToken;
        let prevIdToken;
        let anonTypeName;
        let dataTypeToken;
        let waitForEnd = 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 ((scope == "operator.comma.systemverilog") ||
                    (scope == "operator.semicolon.systemverilog")) {
                    waitForEnd = false;
                    if ((prevIdToken != undefined) && (startToken != undefined)) {
                        if (prevIdToken == startToken) {
                            //unnamed instantiation
                            return true;
                        }
                        else if (this._getElem(this._svtokens[prevToken].scopes, scopeDepth) == "parantheses.block.systemverilog") {
                            //TBD
                        }
                        else {
                            //TBD
                        }
                        let types = [symType, anonTypeName || (dataTypeToken == undefined ? this._svtokens[startToken].text : this._svtokens[dataTypeToken].text)];
                        this._pushSymbol(prevIdToken, types, [startToken, prevToken]); //TBD range
                    }
                    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;
                    }
                    /*TBD if (!scope.startsWith("identifier.") &&
                        !scope.startsWith("literal.") &&
                        !scope.startsWith("operator.") &&
                        (scope != "keyword.struct_union.systemverilog") &&
                        (scope != "keyword.enum.systemverilog") &&
                        (scope != "dimension.expression.systemverilog") &&
                        (scope != "parantheses.begin.systemverilog") &&
                        (scope != "parantheses.block.systemverilog")) {
                        this._printDebugInfo(`${scope} error check`);
                        this._currTokenNum = _currTokenNum;
                        return false;
                    }*/
                }
                prevToken = this._currTokenNum;
            }
        }
        if (this._currTokenNum == this._svtokens.length) {
            this._currTokenNum--;
        }
        return true;
    }
    _processModuleCommonItem() {
        if (this._processRoutine() ||
            this._processCheckerDeclaration() ||
            this._processImportExport() ||
            this._processExternConstraintDeclaration() ||
            this._processClassDeclaration() ||
            this._processParamDeclaration() ||
            this._processCoverGroupDeclaration() ||
            this._processPropertyDeclaration() ||
            this._processSequenceDeclaration() ||
            this._processLetDeclaration() ||
            this._processClockingDeclaration() ||
            this._processDefaultDisableItem() ||
            this._processAssertionStatement() ||
            this._processBindDirective() ||
            this._processContinuousAssign() ||
            this._processAlias() ||
            this._processSequentialBlock() ||
            this._processLoopGenerateConstruct() ||
            this._processIfGenerateConstruct() ||
            this._processCaseGenerateConstruct() ||
            this._processEmptyStatement() ||
            this._processNonStandardBeginEndBlock()) {
            return true;
        }
        return false;
    }
    _processGenerateItem() {
        if (this._processParameterOverride() ||
            this._processModuleCommonItem() ||
            this._processExternTFDeclaration() ||
            this._processGenerateRegion() ||
            this._processElaborationSystemTask() ||
            this._processTypeDef()) {
            return true;
        }
        return false;
    }
    _processSpecifyBlock() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.specify.systemverilog") {
            return false;
        }
        this._printDebugInfo("specify block");
        this._ignoreBlockStatement(["specify.declaration.systemverilog"]);
        return true;
    }
    _processSpecparamDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if (this._svtokens[startToken].scopes[scopeDepth] != "keyword.specparam.systemverilog") {
            return false;
        }
        this._printDebugInfo("specparam declaration");
        this._ignoreBlockStatement(["specparam.statement.systemverilog"]);
        return true;
    }
    _processTimeunitsDeclaration() {
        let startToken = this._currTokenNum;
        let scopeDepth = this._svtokens[startToken].scopes.length - 1;
        if ((this._svtokens[startToken].scopes[scopeDepth] != "simple.identifier.systemverilog") ||
            ((this._svtokens[startToken].text != "timeunit") && (this._svtokens[startToken].text != "timeprecision"))) {
            return false;
        }
        this._printDebugInfo("timeunits declaration");
        this._ignoreTillSemiColon();
        return true;
    }
    parse(document, includeFilePaths, preprocCache, userDefinesMacroInfo, _precision = "full", _maxDepth = -1, text) {
        try {
            this._document = document;
            this._documentPath = genutils_1.uriToPath(document.uri);
            this._preprocCache = preprocCache;
            this._fileSymbolsInfo = {};
            let preprocSymbols;
            [this._svtokens, this._tokenOrder, preprocSymbols] = this.tokenize(text || this._document.getText(), includeFilePaths, userDefinesMacroInfo);
            if (preprocSymbols.length > 0) {
                this._fileSymbolsInfo.symbolsInfo = preprocSymbols;
            }
            this._containerStack = new ContainerStack(this._fileSymbolsInfo);
            this._currTokenNum = 0;
            for (; this._currTokenNum < this._svtokens.length; this._currTokenNum++) {
                if (this._notIgnorableScope()) {
                    this._printDebugInfo("token");
                    if (this._processPreprocessor() ||
                        this._processAttributeInstance() ||
                        this._processSimpleKeywords() ||
                        this._processPortDeclaration() ||
                        this._processGenerateItem() ||
                        this._processSpecifyBlock() ||
                        this._processSpecparamDeclaration() ||
                        this._processContainerHeader() ||
                        this._processPackageHeader() ||
                        this._processTimeunitsDeclaration() ||
                        this._processModPortDeclaration() ||
                        this._processVarInstDeclaration()) {
                        continue;
                    }
                    else {
                        this._printParsingFailedMessage();
                    }
                }
            }
            if (DEBUG_MODE == 1) {
                let symbols = SystemVerilogParser.fileAllSymbols(this._fileSymbolsInfo, false);
                for (let symbol of symbols) {
                    genutils_1.ConnectionLogger.log(`DEBUG: found Symbol ${symbol.name} of type ${symbol.type} in document ${this._documentPath}`);
                }
            }
            let pkgdeps = new Set();
            for (let svtoken of this._svtokens) {
                let scope = this._getElem(svtoken.scopes);
                if (scope == "identifier.scoped.systemverilog") {
                    let parts = svtoken.text.split('::');
                    pkgdeps.add(parts[0]);
                }
            }
            if (DEBUG_MODE == 1) {
                if (pkgdeps) {
                    genutils_1.ConnectionLogger.log(`DEBUG: found pkgdeps ${[...pkgdeps].join(', ')} in document ${this._documentPath}`);
                }
            }
            //TBD DEBUG
            //for (let si: number = 0; si < this._fileSymbolsInfo.length; si++) {
            //    this._debugFileInfo(si);
            //}
            //for (let cntrInfo of <SystemVerilogParser.SystemVerilogContainersInfo>(this._fileSymbolsInfo[SystemVerilogParser.FileInfoIndex.Containers])) {
            //    ConnectionLogger.log(`DEBUG: Processing ${cntrInfo[0].name} container from ${this._document.uri}`);
            //    this._debugContainerInfo(cntrInfo[1], SystemVerilogParser.ContainerInfoIndex.Imports);
            //    this._debugContainerInfo(cntrInfo[1], SystemVerilogParser.ContainerInfoIndex.Exports);
            //}
            return [this._fileSymbolsInfo, [...pkgdeps]];
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [{}, []];
        }
    }
    static preprocCacheToJSON(preprocCache) {
        try {
            return Array.from(preprocCache.entries()).map(e => [e[0], [e[1].file, svpreprocessor_1.SystemVerilogPreprocessor.preprocIncInfoToJSON(e[1].info), e[1].doc]]);
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return new Map();
        }
    }
    static preprocCacheFromJSON(preprocCacheJSON) {
        try {
            return new Map(preprocCacheJSON.map(e => [e[0], { file: e[1][0], info: svpreprocessor_1.SystemVerilogPreprocessor.preprocIncInfoFromJSON(e[0], e[1][1]), doc: node_1.TextDocument.create(e[1][2]._uri, e[1][2]._languageId, e[1][2]._version, e[1][2]._content) }]));
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return new Map();
        }
    }
}
exports.SystemVerilogParser = SystemVerilogParser;
(function (SystemVerilogParser) {
    let ContainerInfoIndex;
    (function (ContainerInfoIndex) {
        ContainerInfoIndex[ContainerInfoIndex["Symbols"] = 0] = "Symbols";
        ContainerInfoIndex[ContainerInfoIndex["Imports"] = 1] = "Imports";
        ContainerInfoIndex[ContainerInfoIndex["Containers"] = 2] = "Containers";
        ContainerInfoIndex[ContainerInfoIndex["Exports"] = 3] = "Exports";
    })(ContainerInfoIndex = SystemVerilogParser.ContainerInfoIndex || (SystemVerilogParser.ContainerInfoIndex = {}));
    let FileInfoIndex;
    (function (FileInfoIndex) {
        FileInfoIndex[FileInfoIndex["Containers"] = 0] = "Containers";
        FileInfoIndex[FileInfoIndex["Includes"] = 1] = "Includes";
        FileInfoIndex[FileInfoIndex["Imports"] = 2] = "Imports";
        FileInfoIndex[FileInfoIndex["Exports"] = 3] = "Exports";
        FileInfoIndex[FileInfoIndex["Symbols"] = 4] = "Symbols";
    })(FileInfoIndex = SystemVerilogParser.FileInfoIndex || (SystemVerilogParser.FileInfoIndex = {}));
    function fileTopSymbols(fileSymbolsInfo, strict = false) {
        try {
            let symbols = [];
            if ((fileSymbolsInfo.symbolsInfo != undefined) &&
                (fileSymbolsInfo.symbolsInfo.length > 0)) {
                let topSymbols = fileSymbolsInfo.symbolsInfo.filter(sym => { return !sym.name.startsWith('#'); });
                if (strict) {
                    symbols = symbols.concat(topSymbols.filter(sym => { return node_1.Range.is(sym.symLocation); }));
                }
                else {
                    symbols = symbols.concat(topSymbols);
                }
            }
            return symbols;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.fileTopSymbols = fileTopSymbols;
    function fileContainers(fileSymbolsInfo) {
        try {
            if ((fileSymbolsInfo.containersInfo != undefined) &&
                (fileSymbolsInfo.containersInfo.length > 0)) {
                return fileSymbolsInfo.containersInfo;
            }
            return [];
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.fileContainers = fileContainers;
    function fileAllSymbols(fileSymbolsInfo, strict = true) {
        try {
            let symbols = fileTopSymbols(fileSymbolsInfo, strict);
            if ((fileSymbolsInfo.containersInfo != undefined) &&
                (fileSymbolsInfo.containersInfo.length > 0)) {
                for (let containerInfo of fileSymbolsInfo.containersInfo) {
                    let cntnrSymbols = containerAllSymbols(containerInfo);
                    if (strict) {
                        symbols = symbols.concat(cntnrSymbols.filter(sym => { return node_1.Range.is(sym.symLocation); }));
                    }
                    else {
                        symbols = symbols.concat(cntnrSymbols);
                    }
                }
            }
            return symbols;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.fileAllSymbols = fileAllSymbols;
    function containerAllContainers(containerSymbolsInfo) {
        try {
            let symbols = [];
            if (containerSymbolsInfo.containersInfo != undefined) {
                for (let container of containerSymbolsInfo.containersInfo) {
                    if (!container.symbol.name.startsWith('#')) {
                        symbols.push(container.symbol);
                    }
                    symbols = symbols.concat(containerAllContainers(container.info));
                }
            }
            return symbols;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.containerAllContainers = containerAllContainers;
    function containerContainers(containerInfo) {
        try {
            if ((containerInfo.info.containersInfo != undefined) &&
                (containerInfo.info.containersInfo.length > 0)) {
                return containerInfo.info.containersInfo;
            }
            return [];
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.containerContainers = containerContainers;
    function containerTopSymbols(containerInfo) {
        try {
            let symbols = [containerInfo.symbol];
            if ((containerInfo.info.symbolsInfo != undefined) &&
                (containerInfo.info.symbolsInfo.length > 0)) {
                symbols = symbols.concat(containerInfo.info.symbolsInfo);
            }
            return symbols;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.containerTopSymbols = containerTopSymbols;
    function containerAllSymbols(containerInfo, topOnly = false) {
        try {
            let symbols = [];
            if (!containerInfo.symbol.name.startsWith('#') && !topOnly) {
                symbols.push(containerInfo.symbol);
            }
            if ((containerInfo.info.symbolsInfo != undefined) &&
                (containerInfo.info.symbolsInfo.length > 0)) {
                let cntnrSymbols = containerInfo.info.symbolsInfo;
                symbols = symbols.concat(cntnrSymbols.filter(sym => { return !sym.name.startsWith('#'); }));
            }
            if ((containerInfo.info.containersInfo != undefined) &&
                (containerInfo.info.containersInfo.length > 0)) {
                for (let childContainerInfo of containerInfo.info.containersInfo) {
                    if (topOnly) {
                        symbols.push(childContainerInfo.symbol);
                    }
                    else {
                        symbols = symbols.concat(containerAllSymbols(childContainerInfo));
                    }
                }
            }
            return symbols;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.containerAllSymbols = containerAllSymbols;
    function fileAllContainers(fileSymbolsInfo) {
        try {
            let symbols = [];
            if (fileSymbolsInfo.containersInfo != undefined) {
                for (let container of fileSymbolsInfo.containersInfo) {
                    if (!container.symbol.name.startsWith('#')) {
                        symbols.push(container.symbol);
                    }
                    symbols = symbols.concat(containerAllContainers(container.info));
                }
            }
            return symbols;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.fileAllContainers = fileAllContainers;
    function findFileContainer(fileSymbolsInfo, cntnrName) {
        try {
            if (fileSymbolsInfo.containersInfo != undefined) {
                return fileSymbolsInfo.containersInfo.find(cntnr => { return cntnr.symbol.name == cntnrName; });
            }
            return undefined;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return undefined;
        }
    }
    SystemVerilogParser.findFileContainer = findFileContainer;
    function findContainerSymbol(containerSymbolsInfo, symbolName, findContainer) {
        try {
            if (!findContainer &&
                (containerSymbolsInfo.symbolsInfo != undefined)) {
                let symbol = containerSymbolsInfo.symbolsInfo.find(sym => { return sym.name == symbolName; });
                if (symbol != undefined) {
                    return symbol;
                }
            }
            if (containerSymbolsInfo.containersInfo != undefined) {
                for (let container of containerSymbolsInfo.containersInfo) {
                    if (container.symbol.name == symbolName) {
                        if (findContainer) {
                            return container;
                        }
                        else {
                            return container.symbol;
                        }
                    }
                    if (findContainer) {
                        let subContainerInfo = (findContainerSymbol(container.info, symbolName, findContainer));
                        if (subContainerInfo.symbol != undefined) {
                            return subContainerInfo;
                        }
                    }
                    else {
                        let symbol = (findContainerSymbol(container.info, symbolName, findContainer));
                        if (symbol != undefined) {
                            return symbol;
                        }
                    }
                }
            }
            if (findContainer) {
                return { symbol: undefined, position: undefined, info: {} };
            }
            else {
                return undefined;
            }
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return undefined;
        }
    }
    SystemVerilogParser.findContainerSymbol = findContainerSymbol;
    function getInstSymbolsInContainer(containerSymbolsInfo) {
        try {
            let instSymbols = [];
            if (containerSymbolsInfo.symbolsInfo != undefined) {
                instSymbols = containerSymbolsInfo.symbolsInfo.filter(sym => sym.type[0] == "instance");
            }
            return instSymbols;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.getInstSymbolsInContainer = getInstSymbolsInContainer;
    function findSymbol(fileSymbolsInfo, symbolName, findContainer) {
        try {
            if (!findContainer &&
                (fileSymbolsInfo.symbolsInfo != undefined)) {
                let symbol = fileSymbolsInfo.symbolsInfo.find(sym => { return sym.name == symbolName; });
                if (symbol != undefined) {
                    return symbol;
                }
            }
            if (fileSymbolsInfo.containersInfo != undefined) {
                for (let container of fileSymbolsInfo.containersInfo) {
                    if (container.symbol.name == symbolName) {
                        if (findContainer) {
                            return container;
                        }
                        else {
                            return container.symbol;
                        }
                    }
                    if (findContainer) {
                        let subContainerInfo = (findContainerSymbol(container.info, symbolName, findContainer));
                        if (subContainerInfo.symbol != undefined) {
                            return subContainerInfo;
                        }
                    }
                    else {
                        let symbol = (findContainerSymbol(container.info, symbolName, findContainer));
                        if (symbol != undefined) {
                            return symbol;
                        }
                    }
                }
            }
            if (findContainer) {
                return { symbol: undefined, position: undefined, info: {} };
            }
            else {
                return undefined;
            }
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return undefined;
        }
    }
    SystemVerilogParser.findSymbol = findSymbol;
    function jsonToPosition(jsonPosition) {
        let result;
        if (typeof jsonPosition[0] === "number") {
            result = { line: jsonPosition[0], character: (jsonPosition[1]) };
        }
        else {
            result = { file: (jsonPosition[0]), line: (jsonPosition[1][0]), character: (jsonPosition[1][1]) };
        }
        return result;
    }
    SystemVerilogParser.jsonToPosition = jsonToPosition;
    function jsonToFileSymbolsInfo(file, jsonFileSymbolsInfo) {
        try {
            let fileSymbolsInfo = {};
            if (jsonFileSymbolsInfo.length > FileInfoIndex.Containers) {
                if (jsonFileSymbolsInfo[FileInfoIndex.Containers] != undefined) {
                    fileSymbolsInfo.containersInfo = [];
                    for (let jsonContainerInfo of jsonFileSymbolsInfo[FileInfoIndex.Containers]) {
                        fileSymbolsInfo.containersInfo.push({
                            symbol: svsymbol_1.SystemVerilogSymbol.fromJSON(file, (jsonContainerInfo[0][0])),
                            position: jsonToPosition((jsonContainerInfo[0][1])),
                            info: _jsonToContainerSymbolsInfo(file, (jsonContainerInfo[1]))
                        });
                    }
                }
            }
            if (jsonFileSymbolsInfo.length > FileInfoIndex.Includes) {
                fileSymbolsInfo.includesInfo = (jsonFileSymbolsInfo[FileInfoIndex.Includes]);
            }
            if (jsonFileSymbolsInfo.length > FileInfoIndex.Imports) {
                if (jsonFileSymbolsInfo[FileInfoIndex.Imports] != undefined) {
                    fileSymbolsInfo.importsInfo = [];
                    for (let importInfo of (jsonFileSymbolsInfo[FileInfoIndex.Imports])) {
                        fileSymbolsInfo.importsInfo.push({ pkg: importInfo[0], symbolsText: importInfo[1] });
                    }
                }
            }
            if (jsonFileSymbolsInfo.length > FileInfoIndex.Exports) {
                if (jsonFileSymbolsInfo[FileInfoIndex.Exports] != undefined) {
                    fileSymbolsInfo.exportsInfo = [];
                    for (let exportInfo of (jsonFileSymbolsInfo[FileInfoIndex.Exports])) {
                        fileSymbolsInfo.exportsInfo.push({ pkg: exportInfo[0], symbolsText: exportInfo[1] });
                    }
                }
            }
            if (jsonFileSymbolsInfo.length > FileInfoIndex.Symbols) {
                if (jsonFileSymbolsInfo[FileInfoIndex.Symbols] != undefined) {
                    fileSymbolsInfo.symbolsInfo = [];
                    for (let symbol of (jsonFileSymbolsInfo[FileInfoIndex.Symbols])) {
                        fileSymbolsInfo.symbolsInfo.push(svsymbol_1.SystemVerilogSymbol.fromJSON(file, symbol));
                    }
                }
            }
            return fileSymbolsInfo;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return {};
        }
    }
    SystemVerilogParser.jsonToFileSymbolsInfo = jsonToFileSymbolsInfo;
    function _containerSymbolsInfoToJson(containerSymbolsInfo) {
        let result = [];
        if (containerSymbolsInfo.symbolsInfo == undefined) {
            if ((containerSymbolsInfo.importsInfo != undefined) ||
                (containerSymbolsInfo.containersInfo != undefined) ||
                (containerSymbolsInfo.exportsInfo != undefined)) {
                result.push([]);
            }
        }
        else {
            result.push(containerSymbolsInfo.symbolsInfo.map(ci => ci.toJSON()));
        }
        if (containerSymbolsInfo.importsInfo == undefined) {
            if ((containerSymbolsInfo.containersInfo != undefined) ||
                (containerSymbolsInfo.exportsInfo != undefined)) {
                result.push([]);
            }
        }
        else {
            result.push(containerSymbolsInfo.importsInfo.map(im => [im.pkg, im.symbolsText]));
        }
        if (containerSymbolsInfo.containersInfo == undefined) {
            if (containerSymbolsInfo.exportsInfo != undefined) {
                result.push([]);
            }
        }
        else {
            result.push(containerSymbolsInfo.containersInfo.map(ci => _containerInfoToJson(ci)));
        }
        if (containerSymbolsInfo.exportsInfo != undefined) {
            result.push(containerSymbolsInfo.exportsInfo.map(ex => [ex.pkg, ex.symbolsText]));
        }
        return result;
    }
    function _positionToJson(pos) {
        let result;
        if (pos.file == undefined) {
            result = [pos.line, pos.character];
        }
        else {
            result = [pos.file, [pos.line, pos.character]];
        }
        return result;
    }
    function _containerInfoToJson(containerInfo) {
        return [[containerInfo.symbol.toJSON(), _positionToJson(containerInfo.position)], _containerSymbolsInfoToJson(containerInfo.info)];
    }
    function fileSymbolsInfoToJson(fileSymbolsInfo) {
        try {
            let fileSymbolsInfoJson = [];
            if ((fileSymbolsInfo.containersInfo != undefined) ||
                (fileSymbolsInfo.includesInfo != undefined) ||
                (fileSymbolsInfo.importsInfo != undefined) ||
                (fileSymbolsInfo.exportsInfo != undefined) ||
                (fileSymbolsInfo.symbolsInfo != undefined)) {
                if (fileSymbolsInfo.containersInfo != undefined) {
                    fileSymbolsInfoJson.push(fileSymbolsInfo.containersInfo.map(ci => _containerInfoToJson(ci)));
                }
                else {
                    fileSymbolsInfoJson.push(undefined);
                }
            }
            if ((fileSymbolsInfo.includesInfo != undefined) ||
                (fileSymbolsInfo.importsInfo != undefined) ||
                (fileSymbolsInfo.exportsInfo != undefined) ||
                (fileSymbolsInfo.symbolsInfo != undefined)) {
                if (fileSymbolsInfo.includesInfo != undefined) {
                    fileSymbolsInfoJson.push(fileSymbolsInfo.includesInfo);
                }
                else {
                    fileSymbolsInfoJson.push(undefined);
                }
            }
            if ((fileSymbolsInfo.importsInfo != undefined) ||
                (fileSymbolsInfo.exportsInfo != undefined) ||
                (fileSymbolsInfo.symbolsInfo != undefined)) {
                if (fileSymbolsInfo.importsInfo != undefined) {
                    const importsInfoJSON = fileSymbolsInfo.importsInfo.map(im => [im.pkg, im.symbolsText]);
                    fileSymbolsInfoJson.push(importsInfoJSON);
                }
                else {
                    fileSymbolsInfoJson.push(undefined);
                }
            }
            if ((fileSymbolsInfo.exportsInfo != undefined) ||
                (fileSymbolsInfo.symbolsInfo != undefined)) {
                if (fileSymbolsInfo.exportsInfo != undefined) {
                    const exportsInfoJSON = fileSymbolsInfo.exportsInfo.map(ex => [ex.pkg, ex.symbolsText]);
                    fileSymbolsInfoJson.push(exportsInfoJSON);
                }
                else {
                    fileSymbolsInfoJson.push(undefined);
                }
            }
            if (fileSymbolsInfo.symbolsInfo != undefined) {
                if (fileSymbolsInfo.symbolsInfo != undefined) {
                    fileSymbolsInfoJson.push(fileSymbolsInfo.symbolsInfo.map(sym => sym.toJSON()));
                }
                else {
                    fileSymbolsInfoJson.push(undefined);
                }
            }
            return fileSymbolsInfoJson;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.fileSymbolsInfoToJson = fileSymbolsInfoToJson;
    function preprocToFileSymbolsInfo(symbols, includes) {
        try {
            let fileSymbolsInfo = {};
            fileSymbolsInfo.symbolsInfo = symbols;
            fileSymbolsInfo.includesInfo = includes == undefined ? undefined : [...includes];
            return fileSymbolsInfo;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return {};
        }
    }
    SystemVerilogParser.preprocToFileSymbolsInfo = preprocToFileSymbolsInfo;
    function containerImports(containerSymbolsInfo, topOnly = false) {
        try {
            let containerImportsInfo = [];
            if (containerSymbolsInfo.importsInfo != undefined) {
                containerImportsInfo = containerSymbolsInfo.importsInfo;
            }
            if (!topOnly && (containerSymbolsInfo.containersInfo != undefined)) {
                for (let cntnrInfo of containerSymbolsInfo.containersInfo) {
                    containerImportsInfo = containerImportsInfo.concat(containerImports(cntnrInfo.info));
                }
            }
            return containerImportsInfo;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.containerImports = containerImports;
    function fileAllImports(fileSymbolsInfo) {
        try {
            let fileImportsInfo = [];
            if (fileSymbolsInfo.importsInfo != undefined) {
                fileImportsInfo = fileSymbolsInfo.importsInfo;
            }
            if (fileSymbolsInfo.containersInfo != undefined) {
                for (let cntnrInfo of fileSymbolsInfo.containersInfo) {
                    fileImportsInfo = fileImportsInfo.concat(containerImports(cntnrInfo.info));
                }
            }
            return fileImportsInfo;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.fileAllImports = fileAllImports;
    function containerExports(containerSymbolsInfo) {
        try {
            let containerExportsInfo = [];
            if (containerSymbolsInfo.exportsInfo != undefined) {
                containerExportsInfo = containerSymbolsInfo.exportsInfo;
            }
            if (containerSymbolsInfo.containersInfo != undefined) {
                for (let cntnrInfo of containerSymbolsInfo.containersInfo) {
                    containerExportsInfo = containerExportsInfo.concat(containerExports(cntnrInfo.info));
                }
            }
            return containerExportsInfo;
        }
        catch (error) {
            genutils_1.ConnectionLogger.error(error);
            return [];
        }
    }
    SystemVerilogParser.containerExports = containerExports;
})(SystemVerilogParser = exports.SystemVerilogParser || (exports.SystemVerilogParser = {}));
