yini-parser 1.0.0-alpha.6 → 1.0.0-alpha.7x

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/YINI.js CHANGED
@@ -17,9 +17,20 @@ class YINI {
17
17
  }
18
18
  YINI.filePath = ''; // Used in error reporting.
19
19
  /**
20
- * @param yiniContent YINI code as a string, can be multiple lines.
21
- * @note The order of properties (members) in each JavaScript object (section) may differ from the order in the input YINI content.
22
- * @returns The parsed JavaScript object.
20
+ * Parse YINI content into a JavaScript object.
21
+ *
22
+ * @param yiniContent YINI code as a string (multi‑line content supported).
23
+ * @param strictMode If `true`, enforce strict parsing rules (e.g. require `/END`, disallow trailing commas).
24
+ * @param bailSensitivity Controls how errors and warnings are handled:
25
+ * - `'auto'` : Auto‑select level (strict→1, lenient→0)
26
+ * - `0` / `'Ignore-Errors'` : Continue parsing despite errors; log them and attempt recovery.
27
+ * - `1` / `'Abort-on-Errors'` : Stop parsing on the first error.
28
+ * - `2` / `'Abort-Even-on-Warnings'`: Stop parsing on the first warning **or** error.
29
+ * @param includeMetaData If `true`, return additional metadata (e.g. warnings, statistics) alongside the parsed object.
30
+ *
31
+ * @note The order of properties in each output object may differ from their order in the YINI source.
32
+ *
33
+ * @returns A JavaScript object representing the parsed YINI content.
23
34
  */
24
35
  YINI.parse = (yiniContent, strictMode = false, bailSensitivity = 'auto', includeMetaData = false) => {
25
36
  (0, system_1.debugPrint)('-> Entered static parse(..) in class YINI\n');
@@ -66,9 +77,20 @@ YINI.parse = (yiniContent, strictMode = false, bailSensitivity = 'auto', include
66
77
  return result;
67
78
  };
68
79
  /**
80
+ * Parse a YINI file into a JavaScript object.
81
+ *
69
82
  * @param yiniFile Path to the YINI file.
70
- * @note The order of properties (members) in each JavaScript object (section) may differ from the order in the input YINI file.
71
- * @returns The parsed JavaScript object.
83
+ * @param strictMode If `true`, enforce strict parsing rules (e.g. require `/END`, disallow trailing commas).
84
+ * @param bailSensitivity Controls how errors and warnings are handled:
85
+ * - `'auto'` : Auto‑select level (strict→1, lenient→0)
86
+ * - `0` / `'Ignore-Errors'` : Continue parsing despite errors; log them and attempt recovery.
87
+ * - `1` / `'Abort-on-Errors'` : Stop parsing on the first error.
88
+ * - `2` / `'Abort-Even-on-Warnings'`: Stop parsing on the first warning **or** error.
89
+ * @param includeMetaData If `true`, return additional metadata (e.g. warnings, statistics) alongside the parsed object.
90
+ *
91
+ * @note The order of properties in each output object may differ from their order in the YINI source.
92
+ *
93
+ * @returns A JavaScript object representing the parsed YINI content.
72
94
  */
73
95
  YINI.parseFile = (filePath, strictMode = false, bailSensitivity = 'auto', includeMetaData = false) => {
74
96
  (0, system_1.debugPrint)('Current directory = ' + process.cwd());
@@ -95,13 +95,12 @@ class ErrorDataHandler {
95
95
  this.emitInternalError(msgWhat, msgWhy, msgHint);
96
96
  if (this.persistThreshold === '1-Abort-on-Errors' ||
97
97
  this.persistThreshold === '2-Abort-Even-on-Warnings') {
98
- if (process.env.NODE_ENV === 'test') {
99
- // In test, throw an error instead of exiting.
100
- throw new Error(`Internal-Error: ${msgWhat}`);
101
- }
102
- else {
103
- process.exit(2);
104
- }
98
+ // if (process.env.NODE_ENV === 'test') {
99
+ // In test, throw an error instead of exiting.
100
+ throw new Error(`Internal-Error: ${msgWhat}`);
101
+ // } else {
102
+ // process.exit(2)
103
+ // }
105
104
  }
106
105
  break;
107
106
  case 'Syntax-Error':
@@ -109,26 +108,24 @@ class ErrorDataHandler {
109
108
  this.emitSyntaxError(msgWhat, msgWhy, msgHint);
110
109
  if (this.persistThreshold === '1-Abort-on-Errors' ||
111
110
  this.persistThreshold === '2-Abort-Even-on-Warnings') {
112
- if (process.env.NODE_ENV === 'test') {
113
- // In test, throw an error instead of exiting.
114
- throw new Error(`Syntax-Error: ${'' + msgWhat}`);
115
- }
116
- else {
117
- process.exit(3);
118
- }
111
+ // if (process.env.NODE_ENV === 'test') {
112
+ // In test, throw an error instead of exiting.
113
+ throw new Error(`Syntax-Error: ${'' + msgWhat}`);
114
+ // } else {
115
+ // process.exit(3)
116
+ // }
119
117
  }
120
118
  break;
121
119
  case 'Syntax-Warning':
122
120
  this.numSyntaxWarnings++;
123
121
  this.emitSyntaxWarning(msgWhat, msgWhy, msgHint);
124
122
  if (this.persistThreshold === '2-Abort-Even-on-Warnings') {
125
- if (process.env.NODE_ENV === 'test') {
126
- // In test, throw an error instead of exiting.
127
- throw new Error(`Syntax-Warning: ${msgWhat}`);
128
- }
129
- else {
130
- process.exit(4);
131
- }
123
+ // if (process.env.NODE_ENV === 'test') {
124
+ // In test, throw an error instead of exiting.
125
+ throw new Error(`Syntax-Warning: ${msgWhat}`);
126
+ // } else {
127
+ // process.exit(4)
128
+ // }
132
129
  }
133
130
  break;
134
131
  case 'Notice':
@@ -143,17 +140,16 @@ class ErrorDataHandler {
143
140
  this.numFatalErrors++;
144
141
  this.emitFatalError(msgWhat, msgWhy, msgHint);
145
142
  // CANNOT recover fatal errors, will lead to an exit!
146
- if (process.env.NODE_ENV === 'test') {
147
- // In test, throw an error instead of exiting.
148
- throw new Error(`Internal-Error: ${msgWhat}`);
149
- }
150
- else {
151
- process.exit(1);
152
- // (!) Not sure about the below yet, if it's preferable in this case...
153
- // Use this instead of process.exit(1), this will
154
- // lead to that the current thread(s) will exit as well.
155
- // process.exitCode = 1
156
- }
143
+ // if (process.env.NODE_ENV === 'test') {
144
+ // In test, throw an error instead of exiting.
145
+ throw new Error(`Internal-Error: ${msgWhat}`);
146
+ // } else {
147
+ // process.exit(1)
148
+ // (!) Not sure about the below yet, if it's preferable in this case...
149
+ // Use this instead of process.exit(1), this will
150
+ // lead to that the current thread(s) will exit as well.
151
+ // process.exitCode = 1
152
+ // }
157
153
  }
158
154
  };
159
155
  this.emitFatalError = (msgWhat = 'Something went wrong!', msgWhy = '', msgHint = '') => {
@@ -136,13 +136,13 @@ export default class YINIVisitor<IResult> extends YiniParserVisitor<IResult> {
136
136
  * @param ctx the parse tree
137
137
  * @return the visitor result
138
138
  */
139
- visitElements?: (ctx: ElementsContext) => IResult;
139
+ visitElements: (ctx: ElementsContext) => IResult;
140
140
  /**
141
141
  * Visit a parse tree produced by `YiniParser.element`.
142
142
  * @param ctx the parse tree
143
143
  * @return the visitor result
144
144
  */
145
- visitElement: (ctx: ElementContext) => IResult;
145
+ visitElement: (ctx: ElementContext) => any;
146
146
  /**
147
147
  * Visit a parse tree produced by `YiniParser.string_concat`.
148
148
  * @param ctx the parse tree
@@ -779,7 +779,8 @@ class YINIVisitor extends YiniParserVisitor_1.default {
779
779
  return this.visit(ctx.null_literal());
780
780
  if (ctx.object_literal())
781
781
  return this.visit(ctx.object_literal());
782
- // if (ctx.list()) return this.visit(ctx.list())
782
+ if (ctx.list_in_brackets())
783
+ return this.visit(ctx.list_in_brackets());
783
784
  // if (ctx.string_concat()) return this.visit(ctx.string_concat())
784
785
  return null;
785
786
  };
@@ -883,8 +884,80 @@ class YINIVisitor extends YiniParserVisitor_1.default {
883
884
  */
884
885
  // visitList_in_brackets?: (ctx: List_in_bracketsContext) => IResult
885
886
  this.visitList_in_brackets = (ctx) => {
886
- const elements = ctx.elements() ? this.visit(ctx.elements()) : [];
887
- return { type: 'List', value: elements };
887
+ (0, system_1.debugPrint)('-> Entered visitList_in_brackets(..)');
888
+ let elements = [];
889
+ if (!ctx.elements()) {
890
+ (0, system_1.debugPrint)('Detected elements() is [], in list brackets');
891
+ // elements = []
892
+ return { type: 'List', value: [] };
893
+ }
894
+ else {
895
+ (0, system_1.debugPrint)('Detected elements() has items, in list brackets');
896
+ elements = this.visit(ctx.elements());
897
+ }
898
+ (0, system_1.debugPrint)('<- Leaving visitList_in_brackets(..)');
899
+ if ((0, env_1.isDebug)()) {
900
+ console.log('returning:');
901
+ console.log({ type: 'List', value: elements.value });
902
+ console.log();
903
+ }
904
+ return { type: 'List', value: elements.value };
905
+ };
906
+ /**
907
+ * Visit a parse tree produced by `YiniParser.elements`.
908
+ * @param ctx the parse tree
909
+ * @return the visitor result
910
+ */
911
+ this.visitElements = (ctx) => {
912
+ (0, system_1.debugPrint)('-> Entered visitElements(..)');
913
+ const firstElem = ctx.element();
914
+ let elements = [];
915
+ (0, system_1.debugPrint)(' element = ' + firstElem);
916
+ (0, system_1.debugPrint)(' element.getText() = ' + firstElem.getText());
917
+ (0, system_1.debugPrint)(' elements = ' + !!ctx.elements());
918
+ const resultElem = ctx.element()
919
+ ? this.visitElement(ctx.element())
920
+ : null;
921
+ const resultTypeElem = resultElem === null || resultElem === void 0 ? void 0 : resultElem.type;
922
+ const resultValueElem = resultElem === null || resultElem === void 0 ? void 0 : resultElem.value;
923
+ (0, system_1.debugPrint)(' elem type = ' + resultTypeElem + ' @visitElements(..)');
924
+ (0, system_1.debugPrint)(' elem value = ' + resultValueElem + ' @visitElements(..)');
925
+ const resultElems = ctx.elements()
926
+ ? this.visitElements(ctx.elements())
927
+ : null;
928
+ const resultTypeElems = resultElems === null || resultElems === void 0 ? void 0 : resultElems.type;
929
+ const resultValueElems = resultElems === null || resultElems === void 0 ? void 0 : resultElems.value;
930
+ (0, system_1.debugPrint)(' elems type = ' +
931
+ resultTypeElems +
932
+ ' @visitElements(..)');
933
+ (0, system_1.debugPrint)(' elems value = ' +
934
+ resultValueElems +
935
+ ' @visitElements(..)');
936
+ if (!ctx.elements()) {
937
+ (0, system_1.debugPrint)('In visitElements(..) detected that elements() has no elements');
938
+ elements = undefined;
939
+ }
940
+ else {
941
+ (0, system_1.debugPrint)('In visitElements(..) detected elements in elements()');
942
+ elements = this.visit(ctx.elements());
943
+ if ((0, env_1.isDebug)()) {
944
+ console.log('result of visited elements:');
945
+ (0, system_1.printObject)(elements);
946
+ }
947
+ }
948
+ const returnValues = elements
949
+ ? [resultElem].concat(elements.value)
950
+ : [resultElem];
951
+ (0, system_1.debugPrint)('<- Leaving visitElements(..)');
952
+ if ((0, env_1.isDebug)()) {
953
+ console.log('returnValues:');
954
+ (0, system_1.printObject)(returnValues);
955
+ }
956
+ return {
957
+ type: 'List',
958
+ // value: [resultElem].concat(elements.value),
959
+ value: returnValues,
960
+ };
888
961
  };
889
962
  /**
890
963
  * Visit a parse tree produced by `YiniParser.element`.
@@ -892,12 +965,33 @@ class YINIVisitor extends YiniParserVisitor_1.default {
892
965
  * @return the visitor result
893
966
  */
894
967
  // visitElement?: (ctx: ElementContext) => IResult
968
+ // visitElement = (ctx: ElementContext): IResult => {
895
969
  this.visitElement = (ctx) => {
970
+ (0, system_1.debugPrint)('-> Entered visitElement(..)');
971
+ // if (ctx.value()) {
972
+ // return this.visit(ctx.value())
973
+ // } else {
974
+ // return { type: 'Null', value: null } as IResult
975
+ // }
976
+ let result;
896
977
  if (ctx.value()) {
897
- return this.visit(ctx.value());
978
+ result = this.visit(ctx.value());
898
979
  }
899
980
  else {
900
- return { type: 'Null', value: null };
981
+ result = { type: 'Null', value: null };
982
+ }
983
+ (0, system_1.debugPrint)('<- Leaving visitElement(..)');
984
+ if ((0, env_1.isDebug)()) {
985
+ console.log('returning:');
986
+ (0, system_1.printObject)(result);
987
+ console.log();
988
+ }
989
+ //return 'value'
990
+ switch (result.type) {
991
+ case 'String':
992
+ return `${result.value}`;
993
+ default:
994
+ return result.value;
901
995
  }
902
996
  };
903
997
  this.errorHandler = errorHandler;
@@ -81,7 +81,10 @@ YiniLexer.literalNames = [null, null,
81
81
  "']'", "'{'",
82
82
  "'}'", "'+'",
83
83
  "'$'", "'%'",
84
- "'@'", "';'"];
84
+ "'@'", "';'",
85
+ null, null,
86
+ null, "'{}'",
87
+ "'[]'"];
85
88
  YiniLexer.symbolicNames = [null, "YINI_MARKER",
86
89
  "SECTION_HEAD",
87
90
  "TERMINAL_TOKEN",
@@ -67,6 +67,8 @@ export default class YiniParser extends Parser {
67
67
  static readonly RULE_string_literal = 16;
68
68
  static readonly RULE_string_concat = 17;
69
69
  static readonly RULE_boolean_literal = 18;
70
+ static readonly RULE_empty_object = 19;
71
+ static readonly RULE_empty_list = 20;
70
72
  static readonly literalNames: (string | null)[];
71
73
  static readonly symbolicNames: (string | null)[];
72
74
  static readonly ruleNames: string[];
@@ -96,6 +98,8 @@ export default class YiniParser extends Parser {
96
98
  string_literal(): String_literalContext;
97
99
  string_concat(): String_concatContext;
98
100
  boolean_literal(): Boolean_literalContext;
101
+ empty_object(): Empty_objectContext;
102
+ empty_list(): Empty_listContext;
99
103
  static readonly _serializedATN: number[];
100
104
  private static __ATN;
101
105
  static get _ATN(): ATN;
@@ -183,7 +187,7 @@ export declare class Object_literalContext extends ParserRuleContext {
183
187
  CC(): TerminalNode;
184
188
  NL_list(): TerminalNode[];
185
189
  NL(i: number): TerminalNode;
186
- EMPTY_OBJECT(): TerminalNode;
190
+ empty_object(): Empty_objectContext;
187
191
  get ruleIndex(): number;
188
192
  accept<Result>(visitor: YiniParserVisitor<Result>): Result;
189
193
  }
@@ -195,7 +199,7 @@ export declare class ObjectMemberListContext extends ParserRuleContext {
195
199
  COMMA(i: number): TerminalNode;
196
200
  NL_list(): TerminalNode[];
197
201
  NL(i: number): TerminalNode;
198
- EMPTY_OBJECT(): TerminalNode;
202
+ empty_object(): Empty_objectContext;
199
203
  get ruleIndex(): number;
200
204
  accept<Result>(visitor: YiniParserVisitor<Result>): Result;
201
205
  }
@@ -224,7 +228,7 @@ export declare class List_in_bracketsContext extends ParserRuleContext {
224
228
  CB(): TerminalNode;
225
229
  NL_list(): TerminalNode[];
226
230
  NL(i: number): TerminalNode;
227
- EMPTY_LIST(): TerminalNode;
231
+ empty_list(): Empty_listContext;
228
232
  get ruleIndex(): number;
229
233
  accept<Result>(visitor: YiniParserVisitor<Result>): Result;
230
234
  }
@@ -281,3 +285,23 @@ export declare class Boolean_literalContext extends ParserRuleContext {
281
285
  get ruleIndex(): number;
282
286
  accept<Result>(visitor: YiniParserVisitor<Result>): Result;
283
287
  }
288
+ export declare class Empty_objectContext extends ParserRuleContext {
289
+ constructor(parser?: YiniParser, parent?: ParserRuleContext, invokingState?: number);
290
+ EMPTY_OBJECT(): TerminalNode;
291
+ OC(): TerminalNode;
292
+ CC(): TerminalNode;
293
+ NL_list(): TerminalNode[];
294
+ NL(i: number): TerminalNode;
295
+ get ruleIndex(): number;
296
+ accept<Result>(visitor: YiniParserVisitor<Result>): Result;
297
+ }
298
+ export declare class Empty_listContext extends ParserRuleContext {
299
+ constructor(parser?: YiniParser, parent?: ParserRuleContext, invokingState?: number);
300
+ EMPTY_LIST(): TerminalNode;
301
+ OB(): TerminalNode;
302
+ CB(): TerminalNode;
303
+ NL_list(): TerminalNode[];
304
+ NL(i: number): TerminalNode;
305
+ get ruleIndex(): number;
306
+ accept<Result>(visitor: YiniParserVisitor<Result>): Result;
307
+ }