UNPKG

yini-parser

Version:

Node.js parser for YINI — a clean, structured INI alternative with types, simple section nesting, comments, and strict mode.

944 lines 52.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const env_1 = require("../config/env"); const YiniParserVisitor_1 = __importDefault(require("../grammar/YiniParserVisitor")); const extractSignificantYiniLine_1 = require("../parsers/extractSignificantYiniLine"); const parseBoolean_1 = __importDefault(require("../parsers/parseBoolean")); const parseNull_1 = __importDefault(require("../parsers/parseNull")); const parseNumber_1 = __importDefault(require("../parsers/parseNumber")); const parseSectionHeader_1 = __importDefault(require("../parsers/parseSectionHeader")); const parseString_1 = __importDefault(require("../parsers/parseString")); const print_1 = require("../utils/print"); const string_1 = require("../utils/string"); const yiniHelpers_1 = require("../yiniHelpers"); const ErrorDataHandler_1 = require("./ErrorDataHandler"); /** * This interface defines a complete generic visitor for a parse tree produced * by `YiniParser`. * * @param <IResult> The return type of the visit operation. Use `void` for * operations with no return type. */ class YINIVisitor extends YiniParserVisitor_1.default { constructor(errorHandler, isStrict) { super(); //export default class YINIVisitor extends YiniParserVisitor<any> { this.reversedTree = []; this.errorHandler = null; this.lastActiveSectionAtLevels = []; this.lastActiveSectionNameAtLevels = []; // Last active section name at each level. this.numOfLevelOnes = 0; // Num of Level-1 sections. this.level = 0; this.prevLevel = 0; this.prevSectionName = ''; // For error reporting purposes. this.meta_numOfSections = 0; // For stats. this.meta_numOfMembers = 0; // For stats. this.meta_numOfChains = 0; // For stats. this.meta_maxLevelSection = 0; // For stats. // private existingSectionTitles: Map<string, boolean> = new Map() this.existingSectionTitlesAtLevels = []; this.hasDefinedSectionTitle = (sectionName, level) => { const mapAtCurrentLevel = this.existingSectionTitlesAtLevels[level - 1]; return mapAtCurrentLevel === null || mapAtCurrentLevel === void 0 ? void 0 : mapAtCurrentLevel.has(sectionName); }; this.setDefineSectionTitle = (sectionName, level) => { let mapAtCurrentLevel = this.existingSectionTitlesAtLevels[level - 1]; if (!mapAtCurrentLevel) { mapAtCurrentLevel = new Map(); this.existingSectionTitlesAtLevels[level - 1] = mapAtCurrentLevel; } mapAtCurrentLevel.set(sectionName, true); }; this.pushOnTree = (ctx, sReslult) => { if ((0, env_1.isDebug)()) { console.log(); (0, print_1.debugPrint)('--- In pushOnTree(..) --------'); (0, print_1.debugPrint)('sReslult:'); (0, print_1.printObject)(sReslult); } const key = sReslult.level + '-' + sReslult.name; (0, print_1.debugPrint)('KKKKKK, key = ' + key); // if (this.existingSectionTitles.has(key)) { if (this.hasDefinedSectionTitle(key, sReslult.level)) { this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Section name already exists', 'Cannot redefine section name: "' + sReslult.name + '" at level ' + sReslult.level + '.'); } else { if (sReslult.members === undefined) { (0, print_1.debugPrint)('This sReslult does not hold any valid members (=undefined)'); } else { // this.existingSectionTitles.set(key, true) this.setDefineSectionTitle(key, sReslult.level); // printObject(this.existingSectionTitles) } } // if ( // sReslult.level === 0 && // (!sReslult.name || sReslult.name === 'undefined') // ) { // // NOTE: This is a nasty fix, should try to do another way! // debugPrint('HIT, Doing NASTY fix!!') // // A memberless section, e.g. `^ Section` and then input ends. // // Lift up the member in "members" to top. // // --- Get the key-name of the entry in "members" ---------- // // "members": { // // "Title": {} // // } // const sectionName = Object.keys(sReslult.members)[0] // // --------------------------------------------------------- // debugPrint('sectionName = ' + sectionName) // const chain: IChainContainer = { // originLevel: 1, // chain: { [sectionName]: {} }, // } // this.reversedTree.push(chain) // } else { const chain = { originLevel: sReslult.level, chain: { [(0, string_1.trimBackticks)(sReslult.name)]: sReslult.members }, }; this.reversedTree.push(chain); // } this.meta_numOfChains++; (0, print_1.debugPrint)('this.reversedTree: [list]'); (0, print_1.printObject)(this.reversedTree); (0, print_1.debugPrint)('--- /end of pushOnTree(..) --------'); }; this.getDepthOfLevels = () => { return this.lastActiveSectionNameAtLevels.length; }; this.setLastActiveSection = (atLevel, sectionName) => { if (atLevel >= 1) { this.lastActiveSectionNameAtLevels[atLevel - 1] = sectionName; } else { // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. this.errorHandler.pushOrBail(null, 'Internal-Error', 'Invalid section level (<1), level: ' + atLevel + ', sectionName: "' + sectionName + '"'); } }; /** * Visit a parse tree produced by `YiniParser.yini`. * @param ctx the parse tree * @return the visitor result */ // visitYini?: (ctx: YiniContext) => IResult; // visitYini = (ctx: YiniContext): IResult => { this.visitYini = (ctx, isStrict = false) => { var _a; if (!this.errorHandler) { // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. new ErrorDataHandler_1.ErrorDataHandler().pushOrBail(null, 'Fatal-Error', 'Has no ErrorDataHandler instance when calling visitYini(..)', 'Something in the code is done incorrectly in order for this to happen... :S'); } (0, print_1.debugPrint)(); (0, print_1.debugPrint)('abcde99'); (0, env_1.isDebug)() && console.log(); (0, print_1.debugPrint)('-> Entered visitYini(..) in YINIVisitor'); (0, print_1.debugPrint)('QQQQ'); (_a = ctx.section_list()) === null || _a === void 0 ? void 0 : _a.forEach((section) => { // ctx?.section_list()?.forEach((section: any) => { (0, print_1.debugPrint)('\nStart of each element in forEeach(..) of section_list():'); const topSectionResult = this.visitSection(section); this.pushOnTree(ctx, topSectionResult); const topSectionName = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.name; const topSectionMembers = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.members; const topSectionLevel = topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.level; // This must have a value of 1. (0, print_1.debugPrint)('\ntopSectionResult (visitSection(..)):'); if ((0, env_1.isDebug)()) { console.log(topSectionResult); } (0, print_1.debugPrint)('Found section head, topSectionName = "' + topSectionName + '"'); topSectionMembers && (0, print_1.debugPrint)('Num of Props of topSectionResult?.members: ' + Object.keys(topSectionResult === null || topSectionResult === void 0 ? void 0 : topSectionResult.members).length); (0, print_1.debugPrint)('topSectionMembers:'); if ((0, env_1.isDebug)()) { console.log(topSectionMembers); } if (topSectionName) { (0, print_1.debugPrint)(); (0, print_1.debugPrint)('-- Just extracted TOP/FIRST section info ---------------------------'); (0, print_1.debugPrint)(' TOP/FIRST topSectionName = ' + topSectionName); (0, print_1.debugPrint)(' topSectionLevel = ' + topSectionLevel); (0, print_1.debugPrint)(' this.level = ' + this.level); (0, print_1.debugPrint)('Mounted/assigned section onto resultSections...'); } (0, print_1.debugPrint)('\n=== resultSections: ====================================='); if ((0, env_1.isDebug)()) { console.log('2222222222222'); console.log(`lastActiveSectionAtLevels[${this.level - 1}]`); (0, print_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]); } (0, print_1.debugPrint)('==============================================\n'); (0, print_1.debugPrint)('End of each element in forEeach(..) of section_list().'); (0, print_1.debugPrint)(); }); const syntaxTree = this.reversedTree.reverse(); if ((0, env_1.isDebug)()) { console.log(); console.log('========================================================================='); console.log('=== syntaxTree: =========================================================='); (0, print_1.printObject)(syntaxTree); console.log('========================================================================='); console.log('========================================================================='); console.log(); } const hasTerminal = !!ctx.terminal_line(); // Returns an Intermediate Tree (could even be an AST). const syntaxTreeC = { // _base: this.resultSections, _syntaxTree: syntaxTree, // The Intermediate Tree, or AST. _hasTerminal: hasTerminal, _meta_numOfSections: this.meta_numOfSections, _meta_numOfMembers: this.meta_numOfMembers, _meta_numOfChains: this.meta_numOfChains, }; return syntaxTreeC; }; /** * Will visit here on EVERY section. * @param ctx the parse tree * @returns { [sectionName]: sectionObj } */ // visitSection?: (ctx: SectionContext) => IResult; this.visitSection = (ctx) => { // let headMarkerType: TSectionHeaderType = // 'Classic-Header-Marker' var _a, _b, _c; (0, env_1.isDebug)() && console.log(); (0, print_1.debugPrint)('-> Entered visitSection(..)'); const res = {}; (0, print_1.debugPrint)('start'); (0, print_1.debugPrint)('XXXX0:ctx.getText() = ' + ctx.getText()); (0, print_1.debugPrint)('XXXX1:ctx.SECTION_HEAD() = ' + ctx.SECTION_HEAD()); (0, print_1.debugPrint)('XXXX1:SECTION_HEAD().getText() = ' + ((_a = ctx.SECTION_HEAD()) === null || _a === void 0 ? void 0 : _a.getText().trim())); (0, print_1.debugPrint)('end\n'); let line = ''; try { (0, print_1.debugPrint)('S1'); line = ((_b = ctx.SECTION_HEAD()) === null || _b === void 0 ? void 0 : _b.getText().trim()) || ''; (0, print_1.debugPrint)('S2, line: >>>' + line + '<<<'); } catch (error) { const msgWhat = `Unexpected syntax while parsing a member or section head`; const msgWhy = `Found unexpected syntax while trying to read a key-value pair or a section header (such as a section marker or section name).`; // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. this.errorHandler.pushOrBail(ctx, 'Syntax-Error', msgWhat, msgWhy); } // If no section head can be found in the above SECTION_HEAD(), // try alternative method of reading the section content. (0, print_1.debugPrint)('S3, line: >>>' + line + '<<<'); if (!line) { (0, print_1.debugPrint)(); (0, print_1.debugPrint)('Nothing in SECTION_HEAD() is found, trying to read the section content directly...'); (0, print_1.debugPrint)('--- Start: parse line from section content-----------------'); // const sectionContent = '' + ctx.getText().trim() const sectionContent = ctx.getText().trim(); (0, print_1.debugPrint)('Section content: ' + ctx.getText()); line = (0, extractSignificantYiniLine_1.extractYiniLine)(sectionContent); // const contentLines = splitLines(sectionContent) // if (isDebug()) { // console.log('contentLines:') // printObject(contentLines) // } // // contentLines.forEach((row: string) => { // for (let row of contentLines) { // debugPrint('---') // debugPrint('row (a): >>>' + row + '<<<') // row = stripNLAndAfter(row) // debugPrint('row (b): >>>' + row + '<<<') // row = stripCommentsAndAfter(row) // debugPrint('row (c): >>>' + row + '<<<') // row = row.trim() // debugPrint('row (d): >>>' + row + '<<<') // if (row) { // debugPrint( // 'Found some content in split row (non-comments).', // ) // debugPrint('Split row: >>>' + row + '<<<') // // Use this as input in line. // line = row // debugPrint('Will use row as line input') // break // } // } // debugPrint( // '--- End: parse line from section content-----------------', // ) // debugPrint() } (0, print_1.debugPrint)('S4, line: >>>' + line + '<<<'); if (!line) { (0, print_1.debugPrint)('*** ERROR: Nothing to parse in section line'); } this.prevLevel = this.level; let { sectionName, sectionLevel } = (0, parseSectionHeader_1.default)(line, this.errorHandler, ctx); this.level = sectionLevel; this.meta_numOfSections++; // --------------------------------------------------------------- let nestDirection; if (this.level === this.prevLevel) { nestDirection = 'same'; } else if (this.level < this.prevLevel) { nestDirection = 'lower'; } else { nestDirection = 'higher'; } (0, print_1.debugPrint)('-- In visitSection(..) ---------------------------'); (0, print_1.debugPrint)(' sectionName = ' + sectionName); (0, print_1.debugPrint)(' sectionLevel = ' + sectionLevel); (0, print_1.debugPrint)(' this.level = ' + this.level); (0, print_1.debugPrint)(' this.prevLevel = ' + this.prevLevel); (0, print_1.debugPrint)(' this.prevSectionName = ' + this.prevSectionName); (0, print_1.debugPrint)(' nestDirection = ' + nestDirection); (0, print_1.debugPrint)(' this.numOfLevelOnes = ' + this.numOfLevelOnes); (0, print_1.debugPrint)('this.getDepthOfLevels() = ' + this.getDepthOfLevels()); (0, print_1.debugPrint)(); if (nestDirection === 'higher') { (0, print_1.debugPrint)(`Is level skipping: ${this.level - this.prevLevel} >= 2?`); // if (Math.abs(this.prevLevel - this.level) >= 2) { if (this.level - this.prevLevel >= 2) { if (this.level === 2) { // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid section header level ' + this.level + ', with section name "' + sectionName, 'A section header may not start directly at level ' + this.level + ', skipping previous section levels. Please start with one level further down.'); } else { // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid section level jump of section header "' + sectionName + '"', 'Section header name "' + sectionName + '" with level ' + this.level + ' may not jump over (skip) intermediate section levels, from section header name "' + this.prevSectionName + '" with level ' + this.prevLevel + '. Section levels should increase one at a time. Please adjust your section headers accordingly.'); } } } this.prevSectionName = sectionName; (0, print_1.debugPrint)('About to visit members of section...'); let members; if (!ctx.section_members()) { (0, print_1.debugPrint)('(!) Section has no members!'); } else { members = this.visitSection_members(ctx.section_members()); } // --------------------------------------------------------------- (_c = ctx.children) === null || _c === void 0 ? void 0 : _c.forEach((child) => { (0, print_1.debugPrint)('* child: ' + child); }); if (this.level === 1) { this.numOfLevelOnes++; } //------------------------ // if (nestDirection === 'higher') { // debugPrint( // `Is level skipping: ${this.level - this.prevLevel} >= 2?`, // ) // // if (Math.abs(this.prevLevel - this.level) >= 2) { // if (this.level - this.prevLevel >= 2) { // // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. // this.errorHandler!.pushOrBail( // ctx, // 'Syntax-Error', // 'Invalid section level jump of section header "' + // sectionName + // '"', // 'Section header name "' + // sectionName + // '" with level ' + // this.prevLevel + // ' may not jump over previous section levels, from a section with level ' + // this.level + // ' (section name: "' + // this.prevSectionName + // '").', // ) // } // } // this.prevSectionName = sectionName if (nestDirection !== 'higher') { (0, print_1.debugPrint)('About to reset result'); (0, print_1.printObject)({ [sectionName]: members }); (0, print_1.debugPrint)(`Current lastActiveSectionAtLevels[${this.level - 1}]`); (0, print_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]); if ( // (level === 0 && !sectionName) || // (sectionName === 'undefined' && !!members) sectionLevel === 0 && sectionName === 'undefined' && !!members) { (0, print_1.debugPrint)('HIT2!!!!'); (0, print_1.debugPrint)('(!) Detected a member (that does not have a sectionName), but a memberless object in "members"'); sectionName = Object.keys(members)[0]; (0, print_1.debugPrint)('sectionName = ' + sectionName); members = {}; // this.lastActiveSectionAtLevels[0] = { [sectionName]: {} } // this.pushOnTree({ level: 1, name: sectionName, members: {} }) (0, print_1.debugPrint)('(!) Skipping mounted since this is actually a memberless section'); (0, print_1.debugPrint)(); (0, print_1.debugPrint)('<- Leaving visitSection(..) EARLY'); if ((0, env_1.isDebug)()) { console.log('returning (a memberless section):'); console.log({ level: 1, name: sectionName, members: members, }); console.log(); } return { level: 1, name: sectionName, members: members, }; } else { // Mount as append this.lastActiveSectionAtLevels[this.level - 1] = { [sectionName]: Object.assign({}, members), }; this.pushOnTree(ctx, { level: sectionLevel, name: sectionName, members, }); // this.lastActiveSectionNameAtLevels.push(sectionName) (0, print_1.debugPrint)('Mounted as append'); } (0, print_1.debugPrint)(`After: lastActiveSectionAtLevels[${this.level - 1}]`); (0, print_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]); if ((0, env_1.isDebug)()) { console.log(`After append lastActiveSectionAtLevels[${this.level - 1}]`); (0, print_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]); (0, print_1.debugPrint)('Before this.lastActiveSectionNameAtLevels:'); (0, print_1.printObject)(this.lastActiveSectionNameAtLevels); // Reset. let i = this.level; while (this.lastActiveSectionNameAtLevels[i]) { this.lastActiveSectionNameAtLevels[i++] = undefined; } (0, print_1.debugPrint)('After this.lastActiveSectionNameAtLevels:'); (0, print_1.printObject)(this.lastActiveSectionNameAtLevels); } (0, print_1.debugPrint)('HIT!!! - Just a lower or same level section, a continues full (nested) section,'); (0, print_1.debugPrint)(`Has above in lastActiveSectionAtLevels[${this.level - 1}]`); (0, print_1.debugPrint)(' this.level: ' + this.level); (0, print_1.debugPrint)('this.prevLevel: ' + this.prevLevel); (0, print_1.debugPrint)(' this.level: ' + this.level); (0, print_1.debugPrint)(); (0, print_1.debugPrint)(' HERE.... Should mount section to correct section at this.level: ' + this.level); //this.lastActiveSectionNameAtLevels[this.level - 1] = sectionName (0, print_1.debugPrint)(); (0, print_1.debugPrint)('Resetted local result'); sectionName = ''; members = undefined; } //------------------------ (0, print_1.debugPrint)(); if ((0, env_1.isDebug)()) { if (members) { (0, print_1.printObject)({ [sectionName]: members }); this.lastActiveSectionAtLevels[this.level - 1] = Object.assign({}, members); // this.lastActiveSectionNameAtLevels[this.level - 1] = sectionName (0, print_1.debugPrint)('Mounted as assigned'); (0, print_1.debugPrint)(`lastActiveSectionAtLevels[${this.level - 1}]`); (0, print_1.printObject)(this.lastActiveSectionAtLevels[this.level - 1]); } } (0, print_1.debugPrint)('-----------------------'); if ((0, env_1.isDebug)()) { console.log('At end of visitSection(..), this.lastActiveSectionNameAtLevels:'); (0, print_1.printObject)(this.lastActiveSectionNameAtLevels); (0, print_1.debugPrint)(' this.level: ' + this.level); (0, print_1.debugPrint)('this.prevLevel: ' + this.prevLevel); (0, print_1.debugPrint)(' this.level: ' + this.level); (0, print_1.debugPrint)('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); (0, print_1.debugPrint)('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); console.log(); } (0, print_1.debugPrint)('<- Leaving visitSection(..)'); if ((0, env_1.isDebug)()) { console.log('returning:'); console.log({ sectionLevel: sectionLevel, name: sectionName, members: members, }); console.log(); } return { level: sectionLevel, name: sectionName, members: members, }; }; /** * Visit a parse tree produced by `YiniParser.bad_member`. * @param ctx the parse tree * @return the visitor result */ this.visitBad_member = (ctx) => { ctx.REST; this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid or malformed member found.', `Offending text: ${ctx.getText()}`); }; /** * Visit a parse tree produced by `YiniParser.section_members`. * In here will mount object onto members object. * @param ctx the parse tree * @returns { key: value, ... } */ // visitSection_members = (ctx: Section_membersContext): Record<string, any> => { // visitSection_members = (ctx: Section_membersContext): any => { this.visitSection_members = (ctx) => { (0, env_1.isDebug)() && console.log(); (0, print_1.debugPrint)('************************************************************'); (0, print_1.debugPrint)('-> Entered visitSection_members(..)'); const members = {}; (0, print_1.debugPrint)('Will loop through each member (or section head)...'); ctx.member_list().forEach((member) => { const { type, key, value } = this.visitMember(member); (0, print_1.debugPrint)('+++++++++++++++++++++++++++++++++++++++++++++++++++++'); (0, print_1.debugPrint)('* Item of member_list:'); if ((0, env_1.isDebug)()) { console.log(value); } (0, print_1.debugPrint)(' type = >>>' + type + '<<<'); (0, print_1.debugPrint)(' key = >>>' + key + '<<<'); (0, print_1.debugPrint)('value = >>>' + value + '<<<'); (0, print_1.debugPrint)('value[key] = >>>' + (value === null || value === void 0 ? void 0 : value[key]) + '<<<'); (0, print_1.debugPrint)('--'); if (key === '') { (0, print_1.debugPrint)('Skipping this member, due to key = ""'); } else { if (members[key] !== undefined) { // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Key already exists in this section scope (in this main section), key name: ' + key); } else { this.meta_numOfMembers++; // if ((value?.type as TDataType) === 'Null') { if (type === 'Null') { members[key] = null; } else { (0, env_1.isDebug)() && console.log(); // NOTE: (!) Only if nested section. (0, print_1.debugPrint)('About to mount a single member or section onto members...'); (0, env_1.isDebug)() && console.log({ [key]: value }); // if ((type as TDataType) === 'Object') { // const isExistingSectionName = // this.hasDefinedSectionTitle(key, this.level) // debugPrint(' type = "' + type + '"') // debugPrint('this.level = "' + this.level + '"') // debugPrint( // 'DDDDDDDD: sectionName / objectKey: ' + key, // ) // debugPrint( // 'Is already defined at this level? ' + // isExistingSectionName, // ) // if (!isExistingSectionName) { // this.setDefineSectionTitle(key, this.level) // } // } Object.assign(members, { [key]: value }); (0, print_1.debugPrint)('+ Added member or section onto members: "' + key + '"'); } } } }); if ((0, env_1.isDebug)()) { (0, print_1.debugPrint)('~~~ After mounting in visitSection_members(..) ~~~~~~~~~~'); (0, print_1.debugPrint)('this.resultSections:'); (0, print_1.debugPrint)('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'); } //@todo handle member colon list // ctx..member_colon_list().forEach((mcl) => { // const { key, value } = this.visit(mcl) // members[key] = value // }) (0, print_1.debugPrint)(); (0, print_1.debugPrint)('<- Leaving visitSection_members(..)'); if ((0, env_1.isDebug)()) { console.log('returning:'); console.log(members); console.log(); } return members; }; /** * Visit every single section or member (any key-value pair such as * key=value or key=[...] etc.). * @returns { type: resultType, key: resultKey, value: resultValue, }: IResult */ // visitMember?: (ctx: MemberContext) => IResult; this.visitMember = (ctx) => { var _a, _b, _c, _d; (0, env_1.isDebug)() && console.log(); (0, print_1.debugPrint)('-> Entered visitMember(..)'); (0, print_1.debugPrint)(' key = ' + ((_a = ctx.KEY()) === null || _a === void 0 ? void 0 : _a.getText().trim())); (0, print_1.debugPrint)('Or, section head = ' + ((_b = ctx.SECTION_HEAD()) === null || _b === void 0 ? void 0 : _b.getText().trim()) + ' (head WITHOUT any members (ONLY detected here))'); (0, print_1.debugPrint)(' ctx.value() = ' + ctx.value()); // For logging and debugging purposes. let entityType = 'Unknown'; let resultType = undefined; let resultKey = ''; let resultValue = {}; let followingSection = null; // NOTE: (!) It can never be both a key and section head. if ((_c = ctx.KEY()) === null || _c === void 0 ? void 0 : _c.getText().trim()) { entityType = 'Member-Key'; try { resultKey = ctx.KEY().getText(); } catch (error) { (0, print_1.debugPrint)('in catch..'); const msg = `Unexpected syntax while parsing a member (key-value pair)`; // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. this.errorHandler.pushOrBail(ctx, 'Syntax-Error', msg); } const result = ctx.value() ? this.visitValue(ctx.value()) : null; resultType = result === null || result === void 0 ? void 0 : result.type; resultValue = result === null || result === void 0 ? void 0 : result.value; (0, print_1.debugPrint)(' type = ' + resultType + ' @visitValue(..)'); (0, print_1.debugPrint)('value = ' + resultValue + ' @visitValue(..)'); } else if ((_d = ctx.SECTION_HEAD()) === null || _d === void 0 ? void 0 : _d.getText().trim()) { entityType = 'Section-Head'; //NOTE: There might be an issue here that some subsection gets missing!! // const line = '' + ctx.SECTION_HEAD().getText().trim() const line = ctx.SECTION_HEAD().getText().trim(); (0, print_1.debugPrint)('(!) Detected a section head instead: ' + line); followingSection = this.visitSection(ctx); // Object.assign(members, sectionObj) (0, print_1.debugPrint)('Got constructed object of builtSection (visitSection(..):'); if ((0, env_1.isDebug)()) { console.log(followingSection); } //@todo (Is this fixed now? 2025-07-10) Mount the nested object correctly! resultType = 'Object'; // resultValue[nestedSection?.name] = nestedSection?.members resultValue = (followingSection === null || followingSection === void 0 ? void 0 : followingSection.members) || {}; resultKey = followingSection.name; (0, print_1.debugPrint)("resultKey = '" + resultKey + "'"); (0, print_1.debugPrint)('resultValue:'); if ((0, env_1.isDebug)()) { (0, print_1.printObject)(resultValue); } (0, print_1.debugPrint)('Mounted/assigned a section onto resultValue...'); // Object.assign(value, { dummy: 6767 }) // Object.assign(resultValue, { // dummy: 'That was detected a section head instead!', // }) (0, print_1.debugPrint)(); } (0, print_1.debugPrint)(); (0, print_1.debugPrint)("entity = '" + entityType + "'"); (0, print_1.debugPrint)("resultType = '" + resultType + "'"); (0, print_1.debugPrint)("resultKey = '" + resultKey + "'"); if (resultKey) { (0, print_1.debugPrint)(); (0, print_1.debugPrint)('Has a key... Validate it either as a simple or a backticked ident...'); if ((0, string_1.isEnclosedInBackticks)(resultKey)) { if (!(0, yiniHelpers_1.isValidBacktickedIdent)(resultKey)) { this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid key name of this member, backticked key/identifier: "' + resultKey + '"', 'Section name should be backticked like e.g. `My section name`.'); } resultKey = (0, string_1.trimBackticks)(resultKey); (0, print_1.debugPrint)("resultKey = '" + resultKey + "' (trimBackticks)"); } else { if (!(0, yiniHelpers_1.isValidSimpleIdent)(resultKey)) { this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Invalid key name of this member, key/identifier: "' + resultKey + '"', 'Section name must start with: A-Z, a-z, or _, unless enclosed in backticks e.g. `' + resultKey + '`, `My key name`.'); } } } if (resultValue === undefined) { (0, print_1.debugPrint)('Detected value as undefined'); if (!this.isStrict) { (0, print_1.debugPrint)('Overloading undefined value with null'); resultValue = null; } else { this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Encountered an empty/missing value in strict mode', 'Expected a value but found nothing, strict mode does not allow implicit null.', 'If you intend to have a null value, please specify "null" explicitly as the value.'); } } (0, print_1.debugPrint)('*** Constructed JS object ***'); (0, print_1.debugPrint)('resultValue:'); if ((0, env_1.isDebug)()) { console.log(resultValue); } (0, print_1.debugPrint)(); (0, print_1.debugPrint)('<- About to leave visitMember(..)'); if ((0, env_1.isDebug)()) { console.log('returning:'); console.log({ type: resultType, key: resultKey, value: resultValue, }); console.log(); } if (!resultType && !resultKey) { // Note, after pushing processing may continue or exit, depending on the error and/or the bail threshold. this.errorHandler.pushOrBail(ctx, 'Syntax-Error', 'Unknown input'); } // if (!isValidSimpleIdent(resultKey)) { // if (resultType !== 'Object' && !isValidSimpleIdent(resultKey)) { // this.errorHandler!.pushOrBail( // ctx, // 'Syntax-Error', // 'Invalid name of this key of a member, key name: "' + // resultKey + // '"', // 'Key name must start with: A-Z, a-z, or _, unless enclosed in backticks e.g. `' + // resultKey + // '`, `My key name`.', // ) // } (0, print_1.debugPrint)(); (0, print_1.debugPrint)('<- Leaving visitMember(..)'); if ((0, env_1.isDebug)()) { console.log('returning:'); console.log({ type: resultType, key: resultKey, value: resultValue, }); console.log(); } return { type: resultType, key: resultKey, value: resultValue, }; }; /** * Visit a parse tree produced by `YiniParser.member_colon_list`. * @param ctx the parse tree * @return the visitor result */ //visitMember_colon_list?: (ctx: Member_colon_listContext) => IResult this.visitMember_colon_list = (ctx) => { (0, env_1.isDebug)() && console.log(); (0, print_1.debugPrint)('-> Entered visitMember_colon_list(..)'); const key = ctx.KEY().getText(); const values = this.visit(ctx.elements()); return { key, value: values }; }; /** * Visit a parse tree produced by `YiniParser.value`. * @param ctx the parse tree * @return the visitor result */ // visitValue?: (ctx: ValueContext) => IResult this.visitValue = (ctx) => { (0, env_1.isDebug)() && console.log(); (0, print_1.debugPrint)('-> Entered visitValue(..)'); if (ctx.string_literal()) return this.visit(ctx.string_literal()); if (ctx.number_literal()) return this.visit(ctx.number_literal()); if (ctx.boolean_literal()) return this.visit(ctx.boolean_literal()); if (ctx.null_literal()) return this.visit(ctx.null_literal()); if (ctx.object_literal()) return this.visit(ctx.object_literal()); if (ctx.list_in_brackets()) return this.visit(ctx.list_in_brackets()); // if (ctx.string_concat()) return this.visit(ctx.string_concat()) return null; }; /** * Visit a parse tree produced by `YiniParser.string_literal`. * @param ctx the parse tree * @return the visitor result */ // visitString_literal?: (ctx: String_literalContext) => Result this.visitString_literal = (ctx) => { (0, print_1.debugPrint)('-> Entered visitString_literal(..)'); const raw = ctx.getText(); (0, print_1.debugPrint)('raw = >>>' + raw + '<<<'); const value = (0, parseString_1.default)(raw); return { type: 'String', value }; }; /** * Visit a parse tree produced by `YiniParser.number_literal`. * @param ctx the parse tree * @return the visitor result */ // visitNumber_literal?: (ctx: Number_literalContext) => IResult this.visitNumber_literal = (ctx) => { (0, print_1.debugPrint)('-> Entered visitNumber_literal(..)'); const txt = ctx.getText(); const { type, value } = (0, parseNumber_1.default)(txt); return { type, value }; }; /** * Visit a parse tree produced by `YiniParser.boolean_literal`. * @param ctx the parse tree * @return the visitor result */ //visitBoolean_literal?: (ctx: Boolean_literalContext) => IResult this.visitBoolean_literal = (ctx) => { (0, print_1.debugPrint)('-> Entered visitBoolean_literal(..)'); const txt = ctx.getText().toLowerCase(); // return ['true', 'yes', 'on'].includes(text) as IResult const value = (0, parseBoolean_1.default)(txt); return { type: 'Boolean', value }; }; /** * Visit a parse tree produced by `YiniParser.null_literal`. * @param ctx the parse tree * @return the visitor result */ this.visitNull_literal = (ctx) => { (0, print_1.debugPrint)('-> Entered visitNull_literal(..)'); const txt = ctx.getText(); const value = (0, parseNull_1.default)(txt); return { type: 'Null', value }; }; /** * Visit a parse tree produced by `YiniParser.object_literal`. * @param ctx the parse tree * @return the visitor result */ // visitObject_literal?: (ctx: Object_literalContext) => IResult this.visitObject_literal = (ctx) => { const members = ctx.objectMemberList() ? this.visit(ctx.objectMemberList()) : {}; return { type: 'Object', value: members }; }; /** * Visit a parse tree produced by `YiniParser.objectMemberList`. * @param ctx the parse tree * @return the visitor result */ //visitObjectMemberList?: (ctx: ObjectMemberListContext) => IResult this.visitObjectMemberList = (ctx) => { const obj = {}; ctx.objectMember_list().forEach((member) => { const { key, value } = this.visit(member); obj[key] = value; }); return obj; }; /** * Visit a parse tree produced by `YiniParser.objectMember`. * @param ctx the parse tree * @return the visitor result */ // visitObjectMember?: (ctx: ObjectMemberContext) => IResult this.visitObjectMember = (ctx) => { const key = ctx.KEY().getText(); const value = ctx.value() ? this.visit(ctx.value()) : null; return { key, value }; }; /** * Visit a parse tree produced by `YiniParser.list`. * @param ctx the parse tree * @return the visitor result */ // visitList?: (ctx: ListContext) => IResult this.visitList = (ctx) => this.visit(ctx.list_in_brackets()); /** * Visit a parse tree produced by `YiniParser.list_in_brackets`. * @param ctx the parse tree * @return the visitor result */ // visitList_in_brackets?: (ctx: List_in_bracketsContext) => IResult this.visitList_in_brackets = (ctx) => { (0, print_1.debugPrint)('-> Entered visitList_in_brackets(..)'); let elements = []; if (!ctx.elements()) { (0, print_1.debugPrint)('Detected elements() is [], in list brackets'); // elements = [] return { type: 'List', value: [] }; } else { (0, print_1.debugPrint)('Detected elements() has items, in list brackets'); elements = this.visit(ctx.elements()); } (0, print_1.debugPrint)('<- Leaving visitList_in_brackets(..)'); if ((0, env_1.isDebug)()) { console.log('returning:'); console.log({ type: 'List', value: elements.value }); console.log(); } return { type: 'List', value: elements.value }; }; /** * Visit a parse tree produced by `YiniParser.elements`. * @param ctx the parse tree * @return the visitor result */ this.visitElements = (ctx) => { (0, print_1.debugPrint)('-> Entered visitElements(..)'); const firstElem = ctx.element(); let elements = []; (0, print_1.debugPrint)(' element = ' + firstElem); (0, print_1.debugPrint)(' element.getText() = ' + firstElem.getText()); (0, print_1.debugPrint)(' elements = ' + !!ctx.elements()); const resultElem = ctx.element() ? this.visitElement(ctx.element()) : null; const resultTypeElem = resultElem === null || resultElem === void 0 ? void 0 : resultElem.type; const resultValueElem = resultElem === null || resultElem === void 0 ? void 0 : resultElem.value; (0, print_1.debugPrint)(' elem type = ' + resultTypeElem + ' @visitElements(..)'); (0, print_1.debugPrint)(' elem value = ' + resultValueElem + ' @visitElements(..)'); const resultElems = ctx.elements() ? this.visitElements(ctx.elements()) : null; const resultTypeElems = resultElems === null || resultElems === void 0 ? void 0 : resultElems.type; const resultValueElems = resultElems === null || resultElems === void 0 ? void 0 : resultElems.value; (0, print_1.debugPrint)(' elems type = ' + resultTypeElems + ' @visitElements(..)'); (0, print_1.debugPrint)(' elems value = ' + resultValueElems + ' @visitElements(..)'); if (!ctx.elements()) { (0, print_1.debugPrint)('In visitElements(.