From b5ea11ad561cc8adb2723da9e211b6ad3fd839c5 Mon Sep 17 00:00:00 2001 From: Liam Barry Allan Date: Wed, 9 Feb 2022 16:31:43 -0500 Subject: [PATCH] Support for complex structs (#60) --- src/language/parser.js | 64 +++++++++++++++++++++++++++--------------- tests/suite/index.js | 40 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 23 deletions(-) diff --git a/src/language/parser.js b/src/language/parser.js index 8b74f895..72718c2d 100644 --- a/src/language/parser.js +++ b/src/language/parser.js @@ -232,6 +232,9 @@ module.exports = class Parser { /** @type {Cache[]} */ let scopes = []; + /** @type {Declaration[]} Free format struct scopes. Used for free-format only */ + let dsScopes = []; + // Global scope bits scopes.push(new Cache()); @@ -389,36 +392,40 @@ module.exports = class Parser { case `DCL-DS`: if (currentItem === undefined) { - if (!parts.includes(`TEMPLATE`)) { - currentItem = new Declaration(`struct`); - currentItem.name = partsLower[1]; - currentItem.keywords = parts.slice(2); - currentItem.description = currentDescription.join(` `); - currentItem.tags = currentTags; - - currentItem.position = { - path: file, - line: lineNumber - } + currentItem = new Declaration(`struct`); + currentItem.name = partsLower[1]; + currentItem.keywords = parts.slice(2); + currentItem.description = currentDescription.join(` `); + currentItem.tags = currentTags; - currentGroup = `structs`; - // Does the keywords include a keyword that makes end-ds useless? - if (currentItem.keywords.some(keyword => oneLineTriggers[`DCL-DS`].some(trigger => keyword.startsWith(trigger)))) { - scope.structs.push(currentItem); - resetDefinition = true; - } else { - currentItem.readParms = true; - } + currentItem.position = { + path: file, + line: lineNumber + } - currentDescription = []; + currentGroup = `structs`; + // Does the keywords include a keyword that makes end-ds useless? + if (currentItem.keywords.some(keyword => oneLineTriggers[`DCL-DS`].some(trigger => keyword.startsWith(trigger)))) { + scope.structs.push(currentItem); + } else { + currentItem.readParms = true; + dsScopes.push(currentItem); } + + resetDefinition = true; + + currentDescription = []; + } else { + } break; case `END-DS`: - if (currentItem && currentItem.type === `struct`) { - scope.structs.push(currentItem); - resetDefinition = true; + if (dsScopes.length === 1) { + scope.structs.push(dsScopes.pop()); + } else + if (dsScopes.length > 1) { + dsScopes[dsScopes.length - 2].subItems.push(dsScopes.pop()); } break; @@ -589,6 +596,13 @@ module.exports = class Parser { } } else { + if (!currentItem) { + if (dsScopes.length >= 1) { + // We do this as there can be many levels to data structures in free format + currentItem = dsScopes[dsScopes.length - 1]; + } + } + if (currentItem && [`procedure`, `struct`].includes(currentItem.type)) { if (currentItem.readParms) { if (parts[0].startsWith(`DCL`)) @@ -611,6 +625,10 @@ module.exports = class Parser { currentItem.subItems.push(currentSub); currentSub = undefined; + + if (currentItem.type === `struct`) { + resetDefinition = true; + } } } } diff --git a/tests/suite/index.js b/tests/suite/index.js index c7b90107..3aaeaefc 100644 --- a/tests/suite/index.js +++ b/tests/suite/index.js @@ -1918,5 +1918,45 @@ module.exports = { const scope = Obj_List.scope; assert.strictEqual(scope.subroutines.length, 1); assert.strictEqual(scope.variables.length, 1); + }, + + subds1: async () => { + const lines = [ + `**FREE`, + ``, + `Dcl-Ds DsChangingNodeRole Qualified;`, + ` *n Int(10) Inz(0);`, + ` *n VarChar(20) Inz('Primary Node');`, + ` *n Int(10) Inz(1);`, + ` *n VarChar(20) Inz('Backup node');`, + ` *n Int(10) Inz(-1);`, + ` *n VarChar(20) Inz('Replicate Node');`, + ` *n Int(10) Inz(-2);`, + ` *n VarChar(20) Inz('Changing Node');`, + ` *n Int(10) Inz(-3);`, + ` *n VarChar(20) Inz('*List');`, + ` *n Int(10) Inz(-4);`, + ` *n VarChar(20) Inz('Peer Node');`, + ` Dcl-Ds Role Dim(1) Pos(1);`, + ` Values Int(10);`, + ` Descriotion VarChar(20);`, + ` End-Ds Role;`, + `End-Ds DsChangingNodeRole;`, + ``, + `Return;`, + ``, + ].join(`\n`); + + const parser = new Parser(); + const cache = await parser.getDocs(URI, lines); + + assert.strictEqual(cache.structs.length, 1); + + const DsChangingNodeRole = cache.find(`DsChangingNodeRole`); + assert.strictEqual(DsChangingNodeRole.name, `DsChangingNodeRole`); + assert.strictEqual(DsChangingNodeRole.position.line, 2); + + assert.strictEqual(DsChangingNodeRole.subItems.length, 13); + assert.strictEqual(DsChangingNodeRole.subItems[12].name, `Role`); } } \ No newline at end of file