yini-parser 1.0.2-beta → 1.1.0-beta
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/CHANGELOG.md +28 -0
- package/README.md +83 -98
- package/dist/YINI.d.ts +34 -11
- package/dist/YINI.js +206 -93
- package/dist/core/ASTBuilder.d.ts +191 -0
- package/dist/core/ASTBuilder.js +827 -0
- package/dist/core/ErrorDataHandler.d.ts +19 -19
- package/dist/core/ErrorDataHandler.js +258 -150
- package/dist/core/objectBuilder.d.ts +9 -3
- package/dist/core/objectBuilder.js +126 -163
- package/dist/core/types.d.ts +234 -44
- package/dist/core/types.js +7 -33
- package/dist/grammar/YiniLexer.d.ts +54 -48
- package/dist/grammar/YiniLexer.js +324 -289
- package/dist/grammar/YiniParser.d.ts +167 -150
- package/dist/grammar/YiniParser.js +1241 -1202
- package/dist/grammar/YiniParserVisitor.d.ts +59 -45
- package/dist/grammar/YiniParserVisitor.js +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +286 -26
- package/dist/parseEntry.d.ts +3 -2
- package/dist/parseEntry.js +352 -81
- package/dist/parsers/extractHeaderParts.d.ts +3 -2
- package/dist/parsers/extractHeaderParts.js +1 -0
- package/dist/parsers/parseBoolean.d.ts +1 -1
- package/dist/parsers/parseBoolean.js +2 -1
- package/dist/parsers/parseNumber.d.ts +8 -3
- package/dist/parsers/parseNumber.js +21 -7
- package/dist/parsers/parseSectionHeader.d.ts +3 -2
- package/dist/parsers/parseSectionHeader.js +1 -0
- package/dist/utils/number.d.ts +3 -0
- package/dist/utils/number.js +18 -0
- package/dist/utils/object.d.ts +55 -0
- package/dist/utils/object.js +85 -0
- package/dist/utils/string.d.ts +21 -1
- package/dist/utils/string.js +39 -4
- package/dist/utils/system.d.ts +15 -0
- package/dist/utils/system.js +21 -0
- package/dist/yiniHelpers.d.ts +3 -0
- package/dist/yiniHelpers.js +43 -7
- package/package.json +1 -1
- package/dist/core/YINIVisitor.d.ts +0 -158
- package/dist/core/YINIVisitor.js +0 -1008
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const number_1 = require("../utils/number");
|
|
3
4
|
const print_1 = require("../utils/print");
|
|
5
|
+
/**
|
|
6
|
+
* @property {string | undefined} [tag]
|
|
7
|
+
* This parameter is for debugging only. Its
|
|
8
|
+
* contents may change at any time and should not
|
|
9
|
+
* be relied upon for any significant purpose.
|
|
10
|
+
*/
|
|
4
11
|
const parseNumberLiteral = (txt) => {
|
|
5
12
|
(0, print_1.debugPrint)('-> Entered parseNumberLiteral(..), txt: ' + txt);
|
|
6
13
|
if (/^[+-]?(?:\d+\.\d*|\d*\.?\d+)e[+-]?\d+$/i.test(txt)) {
|
|
7
14
|
// Exp. numbers
|
|
8
15
|
(0, print_1.debugPrint)('* Identified as an exp number');
|
|
9
16
|
return {
|
|
10
|
-
|
|
17
|
+
tag: 'From exp number, Number-Float',
|
|
11
18
|
// value: parseInt(txt.replace('#', '0x'), 16),
|
|
12
19
|
value: parseFloat(txt),
|
|
13
20
|
};
|
|
@@ -18,7 +25,7 @@ const parseNumberLiteral = (txt) => {
|
|
|
18
25
|
(0, print_1.debugPrint)('* Identified as a hex number');
|
|
19
26
|
(0, print_1.debugPrint)('parsed out HEX: ' + txt.replace(/0[xX]|#/, ''));
|
|
20
27
|
return {
|
|
21
|
-
|
|
28
|
+
tag: 'From hex number, Number-Integer',
|
|
22
29
|
// value: parseInt(txt.replace('#', '0x'), 16),
|
|
23
30
|
value: parseInt(txt.replace(/0[xX]|#/, ''), 16),
|
|
24
31
|
};
|
|
@@ -29,7 +36,7 @@ const parseNumberLiteral = (txt) => {
|
|
|
29
36
|
(0, print_1.debugPrint)('* Identified as a bin number');
|
|
30
37
|
(0, print_1.debugPrint)('parsed out BIN: ' + txt.replace(/0[bB]|%/, ''));
|
|
31
38
|
return {
|
|
32
|
-
|
|
39
|
+
tag: 'From bin number, Number-Integer',
|
|
33
40
|
value: parseInt(txt.replace(/0[bB]|%/, ''), 2),
|
|
34
41
|
};
|
|
35
42
|
}
|
|
@@ -39,7 +46,7 @@ const parseNumberLiteral = (txt) => {
|
|
|
39
46
|
(0, print_1.debugPrint)('* Identified as a oct number');
|
|
40
47
|
(0, print_1.debugPrint)('parsed out OCT: ' + txt.replace(/0[oO]/, ''));
|
|
41
48
|
return {
|
|
42
|
-
|
|
49
|
+
tag: 'From oct number, Number-Integer',
|
|
43
50
|
value: parseInt(txt.replace(/0[oO]/, ''), 8),
|
|
44
51
|
};
|
|
45
52
|
}
|
|
@@ -52,18 +59,25 @@ const parseNumberLiteral = (txt) => {
|
|
|
52
59
|
txt = txt.replace(/[eE]/g, 'B');
|
|
53
60
|
(0, print_1.debugPrint)('Converter to AB form: ' + txt.replace(/0[zZ]/, ''));
|
|
54
61
|
return {
|
|
55
|
-
|
|
62
|
+
tag: 'From doz (duodecimal) number, Number-Integer',
|
|
56
63
|
value: parseInt(txt.replace(/0[zZ]/, ''), 12),
|
|
57
64
|
};
|
|
58
65
|
}
|
|
59
66
|
// In a regex literal the dot must be escaped (\.) to match a literal '.'
|
|
60
67
|
if (/\./.test(txt)) {
|
|
61
68
|
(0, print_1.debugPrint)('* Identified as a float number');
|
|
62
|
-
return {
|
|
69
|
+
return {
|
|
70
|
+
tag: 'From float number, Number-Float',
|
|
71
|
+
value: parseFloat(txt),
|
|
72
|
+
};
|
|
63
73
|
}
|
|
64
74
|
// TODO: Depending, on mode, below continue or break on error
|
|
65
75
|
//console.error('Error: Failed to parse number value: ' + txt)
|
|
76
|
+
if (!(0, number_1.isValidJSNumber)(txt)) {
|
|
77
|
+
(0, print_1.debugPrint)('* Identified as invalid number');
|
|
78
|
+
return { tag: 'From invalid number/value', value: undefined };
|
|
79
|
+
}
|
|
66
80
|
(0, print_1.debugPrint)('* Identified as a int number');
|
|
67
|
-
return {
|
|
81
|
+
return { tag: 'From int number, Number-Integer', value: parseInt(txt) };
|
|
68
82
|
};
|
|
69
83
|
exports.default = parseNumberLiteral;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ErrorDataHandler } from '../core/ErrorDataHandler';
|
|
2
2
|
import { TSectionHeaderType } from '../core/types';
|
|
3
|
-
import {
|
|
3
|
+
import { StmtContext } from '../grammar/YiniParser';
|
|
4
4
|
/**
|
|
5
5
|
* Extract ...
|
|
6
6
|
* @param rawLine Raw line with the section header.
|
|
7
|
+
* @note Implemented without regexp to keep it less cryptic, etc.
|
|
7
8
|
*/
|
|
8
|
-
declare const parseSectionHeader: (rawLine: string, errorHandler: ErrorDataHandler, ctx: null |
|
|
9
|
+
declare const parseSectionHeader: (rawLine: string, errorHandler: ErrorDataHandler, ctx: null | StmtContext) => {
|
|
9
10
|
markerType: TSectionHeaderType;
|
|
10
11
|
sectionName: string;
|
|
11
12
|
sectionLevel: number;
|
|
@@ -11,6 +11,7 @@ const yiniHelpers_1 = require("../yiniHelpers");
|
|
|
11
11
|
/**
|
|
12
12
|
* Extract ...
|
|
13
13
|
* @param rawLine Raw line with the section header.
|
|
14
|
+
* @note Implemented without regexp to keep it less cryptic, etc.
|
|
14
15
|
*/
|
|
15
16
|
const parseSectionHeader = (rawLine, errorHandler, ctx) => {
|
|
16
17
|
(0, print_1.debugPrint)('-> Entered parseSectionHeader(..)');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isValidJSNumber = exports.isInfinityValue = exports.isNaNValue = void 0;
|
|
4
|
+
const isNaNValue = (n) => {
|
|
5
|
+
return Number.isNaN(n);
|
|
6
|
+
};
|
|
7
|
+
exports.isNaNValue = isNaNValue;
|
|
8
|
+
const isInfinityValue = (n) => {
|
|
9
|
+
return n === Infinity || n === -Infinity;
|
|
10
|
+
};
|
|
11
|
+
exports.isInfinityValue = isInfinityValue;
|
|
12
|
+
const isValidJSNumber = (str) => {
|
|
13
|
+
if (str.trim() === '')
|
|
14
|
+
return false; // Reject empty or whitespace-only.
|
|
15
|
+
const n = Number(str);
|
|
16
|
+
return !Number.isNaN(n); // True only if parse succeeded.
|
|
17
|
+
};
|
|
18
|
+
exports.isValidJSNumber = isValidJSNumber;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Removes top-level properties with value `undefined`.
|
|
3
|
+
* Does not recurse into nested objects or arrays.
|
|
4
|
+
*
|
|
5
|
+
* @param obj Any JS object
|
|
6
|
+
* @returns A shallow copy with undefined properties removed,
|
|
7
|
+
* except in nested objects or arrays.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* Input:
|
|
11
|
+
* const input = {
|
|
12
|
+
* a: 1,
|
|
13
|
+
* b: undefined,
|
|
14
|
+
* c: { d: undefined, e: 2 },
|
|
15
|
+
* f: [1, undefined, 2]
|
|
16
|
+
* };
|
|
17
|
+
*
|
|
18
|
+
* Output:
|
|
19
|
+
* {
|
|
20
|
+
* a: 1,
|
|
21
|
+
* c: { d: undefined, e: 2 },
|
|
22
|
+
* f: [1, undefined, 2]
|
|
23
|
+
* }
|
|
24
|
+
*/
|
|
25
|
+
export declare const removeUndefinedShallow: <T extends object>(obj: T) => Partial<T>;
|
|
26
|
+
/**
|
|
27
|
+
* Recursively removes properties with value `undefined` from objects
|
|
28
|
+
* and arrays.
|
|
29
|
+
*
|
|
30
|
+
* @param obj Any JS value (object, array, primitive)
|
|
31
|
+
* @returns A deep-cloned copy with all `undefined` removed, including in
|
|
32
|
+
* nested objects and arrays.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* Input:
|
|
36
|
+
* const input = {
|
|
37
|
+
* a: 1,
|
|
38
|
+
* b: undefined,
|
|
39
|
+
* c: {
|
|
40
|
+
* d: undefined,
|
|
41
|
+
* e: 2,
|
|
42
|
+
* f: [1, undefined, { g: undefined, h: 42 }]
|
|
43
|
+
* }
|
|
44
|
+
* };
|
|
45
|
+
*
|
|
46
|
+
* Output:
|
|
47
|
+
* {
|
|
48
|
+
* a: 1,
|
|
49
|
+
* c: {
|
|
50
|
+
* e: 2,
|
|
51
|
+
* f: [1, { h: 42 }]
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
*/
|
|
55
|
+
export declare const removeUndefinedDeep: <T>(obj: T) => T;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.removeUndefinedDeep = exports.removeUndefinedShallow = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Removes top-level properties with value `undefined`.
|
|
6
|
+
* Does not recurse into nested objects or arrays.
|
|
7
|
+
*
|
|
8
|
+
* @param obj Any JS object
|
|
9
|
+
* @returns A shallow copy with undefined properties removed,
|
|
10
|
+
* except in nested objects or arrays.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* Input:
|
|
14
|
+
* const input = {
|
|
15
|
+
* a: 1,
|
|
16
|
+
* b: undefined,
|
|
17
|
+
* c: { d: undefined, e: 2 },
|
|
18
|
+
* f: [1, undefined, 2]
|
|
19
|
+
* };
|
|
20
|
+
*
|
|
21
|
+
* Output:
|
|
22
|
+
* {
|
|
23
|
+
* a: 1,
|
|
24
|
+
* c: { d: undefined, e: 2 },
|
|
25
|
+
* f: [1, undefined, 2]
|
|
26
|
+
* }
|
|
27
|
+
*/
|
|
28
|
+
const removeUndefinedShallow = (obj) => {
|
|
29
|
+
const cleaned = {};
|
|
30
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
31
|
+
if (value !== undefined) {
|
|
32
|
+
cleaned[key] = value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return cleaned;
|
|
36
|
+
};
|
|
37
|
+
exports.removeUndefinedShallow = removeUndefinedShallow;
|
|
38
|
+
/**
|
|
39
|
+
* Recursively removes properties with value `undefined` from objects
|
|
40
|
+
* and arrays.
|
|
41
|
+
*
|
|
42
|
+
* @param obj Any JS value (object, array, primitive)
|
|
43
|
+
* @returns A deep-cloned copy with all `undefined` removed, including in
|
|
44
|
+
* nested objects and arrays.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* Input:
|
|
48
|
+
* const input = {
|
|
49
|
+
* a: 1,
|
|
50
|
+
* b: undefined,
|
|
51
|
+
* c: {
|
|
52
|
+
* d: undefined,
|
|
53
|
+
* e: 2,
|
|
54
|
+
* f: [1, undefined, { g: undefined, h: 42 }]
|
|
55
|
+
* }
|
|
56
|
+
* };
|
|
57
|
+
*
|
|
58
|
+
* Output:
|
|
59
|
+
* {
|
|
60
|
+
* a: 1,
|
|
61
|
+
* c: {
|
|
62
|
+
* e: 2,
|
|
63
|
+
* f: [1, { h: 42 }]
|
|
64
|
+
* }
|
|
65
|
+
* }
|
|
66
|
+
*/
|
|
67
|
+
const removeUndefinedDeep = (obj) => {
|
|
68
|
+
if (obj === null || typeof obj !== 'object') {
|
|
69
|
+
return obj; // primitive value
|
|
70
|
+
}
|
|
71
|
+
if (Array.isArray(obj)) {
|
|
72
|
+
// Clean each element, and filter out undefined entries
|
|
73
|
+
return obj
|
|
74
|
+
.map((item) => (0, exports.removeUndefinedDeep)(item))
|
|
75
|
+
.filter((item) => item !== undefined);
|
|
76
|
+
}
|
|
77
|
+
const cleaned = {};
|
|
78
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
79
|
+
if (value !== undefined) {
|
|
80
|
+
cleaned[key] = (0, exports.removeUndefinedDeep)(value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return cleaned;
|
|
84
|
+
};
|
|
85
|
+
exports.removeUndefinedDeep = removeUndefinedDeep;
|
package/dist/utils/string.d.ts
CHANGED
|
@@ -2,12 +2,27 @@
|
|
|
2
2
|
* This file contains general string helper functions (utils).
|
|
3
3
|
* @note More specific YINI helper functions should go into yiniHelpers.ts-file.
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Capitalizes the first character of a string.
|
|
7
|
+
*
|
|
8
|
+
* @param str The input string.
|
|
9
|
+
* @returns A new string with the first character uppercased.
|
|
10
|
+
*/
|
|
11
|
+
export declare const capitalizeFirst: (str: string) => string;
|
|
12
|
+
export declare const computeSha256: (content: string) => string;
|
|
5
13
|
/**
|
|
6
14
|
* Splits a string into an array of lines, handling both LF and CRLF newlines.
|
|
7
15
|
* @param content The input string.
|
|
8
16
|
* @returns Array of lines (strings).
|
|
9
17
|
*/
|
|
10
|
-
export declare
|
|
18
|
+
export declare const splitLines: (content: string) => string[];
|
|
19
|
+
/**
|
|
20
|
+
* Trims trailing non-letter characters (A–Z, a–z) from the end of a string.
|
|
21
|
+
*
|
|
22
|
+
* @param str Input string
|
|
23
|
+
* @returns String with trailing non-letters removed
|
|
24
|
+
*/
|
|
25
|
+
export declare const trimTrailingNonLetters: (str: string) => string;
|
|
11
26
|
/**
|
|
12
27
|
* If a string starts and ends with a backtick `, if so trims the
|
|
13
28
|
* first and last character (the backticks).
|
|
@@ -40,3 +55,8 @@ export declare const isDigit: (character: string) => boolean;
|
|
|
40
55
|
* @deprecated This seems not useful anymore, use stripCommentsAndAfter(..) instead.
|
|
41
56
|
*/
|
|
42
57
|
export declare const stripNLAndAfter: (line: string) => string;
|
|
58
|
+
/**
|
|
59
|
+
* Transforms strings such as 'Id-Name' to 'id_name'.
|
|
60
|
+
* Replaces all '-' to '_', and returns rusult in lower case.
|
|
61
|
+
*/
|
|
62
|
+
export declare const toLowerSnakeCase: (txt: string) => string;
|
package/dist/utils/string.js
CHANGED
|
@@ -4,18 +4,45 @@
|
|
|
4
4
|
* @note More specific YINI helper functions should go into yiniHelpers.ts-file.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.stripNLAndAfter = exports.isDigit = exports.isAlpha = exports.isEnclosedInBackticks = exports.trimBackticks = void 0;
|
|
8
|
-
|
|
7
|
+
exports.toLowerSnakeCase = exports.stripNLAndAfter = exports.isDigit = exports.isAlpha = exports.isEnclosedInBackticks = exports.trimBackticks = exports.trimTrailingNonLetters = exports.splitLines = exports.computeSha256 = exports.capitalizeFirst = void 0;
|
|
8
|
+
const crypto_1 = require("crypto");
|
|
9
9
|
const print_1 = require("./print");
|
|
10
|
+
/**
|
|
11
|
+
* Capitalizes the first character of a string.
|
|
12
|
+
*
|
|
13
|
+
* @param str The input string.
|
|
14
|
+
* @returns A new string with the first character uppercased.
|
|
15
|
+
*/
|
|
16
|
+
const capitalizeFirst = (str) => {
|
|
17
|
+
if (!str)
|
|
18
|
+
return str;
|
|
19
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
20
|
+
};
|
|
21
|
+
exports.capitalizeFirst = capitalizeFirst;
|
|
22
|
+
const computeSha256 = (content) => {
|
|
23
|
+
return (0, crypto_1.createHash)('sha256').update(content, 'utf8').digest('hex');
|
|
24
|
+
};
|
|
25
|
+
exports.computeSha256 = computeSha256;
|
|
10
26
|
/**
|
|
11
27
|
* Splits a string into an array of lines, handling both LF and CRLF newlines.
|
|
12
28
|
* @param content The input string.
|
|
13
29
|
* @returns Array of lines (strings).
|
|
14
30
|
*/
|
|
15
|
-
|
|
31
|
+
const splitLines = (content) => {
|
|
16
32
|
// Chould handle \n (LF), \r\n (CRLF), and even just \r (old Mac style).
|
|
17
33
|
return content.split(/\r\n|\r|\n/);
|
|
18
|
-
}
|
|
34
|
+
};
|
|
35
|
+
exports.splitLines = splitLines;
|
|
36
|
+
/**
|
|
37
|
+
* Trims trailing non-letter characters (A–Z, a–z) from the end of a string.
|
|
38
|
+
*
|
|
39
|
+
* @param str Input string
|
|
40
|
+
* @returns String with trailing non-letters removed
|
|
41
|
+
*/
|
|
42
|
+
const trimTrailingNonLetters = (str) => {
|
|
43
|
+
return str.replace(/[^a-zA-Z]+$/g, '');
|
|
44
|
+
};
|
|
45
|
+
exports.trimTrailingNonLetters = trimTrailingNonLetters;
|
|
19
46
|
/**
|
|
20
47
|
* If a string starts and ends with a backtick `, if so trims the
|
|
21
48
|
* first and last character (the backticks).
|
|
@@ -95,3 +122,11 @@ const stripNLAndAfter = (line) => {
|
|
|
95
122
|
return resultLine;
|
|
96
123
|
};
|
|
97
124
|
exports.stripNLAndAfter = stripNLAndAfter;
|
|
125
|
+
/**
|
|
126
|
+
* Transforms strings such as 'Id-Name' to 'id_name'.
|
|
127
|
+
* Replaces all '-' to '_', and returns rusult in lower case.
|
|
128
|
+
*/
|
|
129
|
+
const toLowerSnakeCase = (txt) => {
|
|
130
|
+
return txt.trim().toLowerCase().replace(/[-]/g, '_');
|
|
131
|
+
};
|
|
132
|
+
exports.toLowerSnakeCase = toLowerSnakeCase;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error instance helper.
|
|
3
|
+
* @example
|
|
4
|
+
* ...
|
|
5
|
+
* } catch (err: unknown) {
|
|
6
|
+
* if (err instanceof Error) {
|
|
7
|
+
* console.error("Message:", err.message)
|
|
8
|
+
* console.error("Stack:", err.stack)
|
|
9
|
+
* } else {
|
|
10
|
+
* console.error("Unknown error:", err)
|
|
11
|
+
* console.error("Thrown value:", JSON.stringify(err))
|
|
12
|
+
* }
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
export declare const isError: (e: unknown) => e is Error;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isError = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Error instance helper.
|
|
6
|
+
* @example
|
|
7
|
+
* ...
|
|
8
|
+
* } catch (err: unknown) {
|
|
9
|
+
* if (err instanceof Error) {
|
|
10
|
+
* console.error("Message:", err.message)
|
|
11
|
+
* console.error("Stack:", err.stack)
|
|
12
|
+
* } else {
|
|
13
|
+
* console.error("Unknown error:", err)
|
|
14
|
+
* console.error("Thrown value:", JSON.stringify(err))
|
|
15
|
+
* }
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
const isError = (e) => {
|
|
19
|
+
return e instanceof Error;
|
|
20
|
+
};
|
|
21
|
+
exports.isError = isError;
|
package/dist/yiniHelpers.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* This file contains specific YINI helper functions (utils).
|
|
3
3
|
* @note More general helper functions should go into the dir "src/utils/".
|
|
4
4
|
*/
|
|
5
|
+
import { TScalarValue, TValueLiteral } from './core/types';
|
|
5
6
|
/**
|
|
6
7
|
* Check if the character is a section marker character.
|
|
7
8
|
* @param character A character in a string.
|
|
@@ -42,3 +43,5 @@ export declare const isValidSimpleIdent: (str: string) => boolean;
|
|
|
42
43
|
* @link https://github.com/YINI-lang/YINI-spec/blob/develop/YINI-Specification.md#34-identifiers
|
|
43
44
|
*/
|
|
44
45
|
export declare const isValidBacktickedIdent: (str: string) => boolean;
|
|
46
|
+
export declare const printLiteral: (value: TValueLiteral) => void;
|
|
47
|
+
export declare const isScalar: (v: TValueLiteral) => v is TScalarValue;
|
package/dist/yiniHelpers.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @note More general helper functions should go into the dir "src/utils/".
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.isValidBacktickedIdent = exports.isValidSimpleIdent = exports.stripCommentsAndAfter = exports.isMarkerCharacter = void 0;
|
|
7
|
+
exports.isScalar = exports.printLiteral = exports.isValidBacktickedIdent = exports.isValidSimpleIdent = exports.stripCommentsAndAfter = exports.isMarkerCharacter = void 0;
|
|
8
8
|
const print_1 = require("./utils/print");
|
|
9
9
|
const string_1 = require("./utils/string");
|
|
10
10
|
const SECTION_MARKER1 = '^';
|
|
@@ -37,11 +37,14 @@ exports.isMarkerCharacter = isMarkerCharacter;
|
|
|
37
37
|
* @throws Will throw if consisting more than 1 lines.
|
|
38
38
|
*/
|
|
39
39
|
const stripCommentsAndAfter = (line) => {
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
// if (splitLines(line).length > 1) {
|
|
41
|
+
// throw new Error(
|
|
42
|
+
// 'Internal error: Detected several row lines in line: >>>' +
|
|
43
|
+
// line +
|
|
44
|
+
// '<<<',
|
|
45
|
+
// )
|
|
46
|
+
// }
|
|
47
|
+
line = line.split('\n', 1)[0];
|
|
45
48
|
let idx1 = line.indexOf('//');
|
|
46
49
|
let idx2 = line.indexOf('# '); // NOTE: (!) Hash comments requires a WS after the hash!
|
|
47
50
|
let idx3 = line.indexOf('#\t'); // NOTE: (!) Hash comments requires a WS after the hash!
|
|
@@ -66,7 +69,7 @@ const stripCommentsAndAfter = (line) => {
|
|
|
66
69
|
const resultLine = idx === Number.MAX_SAFE_INTEGER ? line : line.substring(0, idx);
|
|
67
70
|
(0, print_1.debugPrint)('stripCommentsAndAfter(..), line: >>>' + line + '<<<');
|
|
68
71
|
(0, print_1.debugPrint)('stripCommentsAndAfter(..), resultLine: >>>' + resultLine + '<<<');
|
|
69
|
-
return resultLine;
|
|
72
|
+
return resultLine.trim();
|
|
70
73
|
};
|
|
71
74
|
exports.stripCommentsAndAfter = stripCommentsAndAfter;
|
|
72
75
|
/**
|
|
@@ -139,3 +142,36 @@ const isValidBacktickedIdent = (str) => {
|
|
|
139
142
|
return true;
|
|
140
143
|
};
|
|
141
144
|
exports.isValidBacktickedIdent = isValidBacktickedIdent;
|
|
145
|
+
const assertNever = (x) => {
|
|
146
|
+
throw new Error(`Unhandled: ${JSON.stringify(x)}`);
|
|
147
|
+
};
|
|
148
|
+
const printLiteral = (value) => {
|
|
149
|
+
switch (value.type) {
|
|
150
|
+
case 'String':
|
|
151
|
+
case 'Number':
|
|
152
|
+
case 'Boolean':
|
|
153
|
+
case 'Null':
|
|
154
|
+
console.log('' + value.value);
|
|
155
|
+
break;
|
|
156
|
+
case 'Undefined':
|
|
157
|
+
console.log('' + value.value);
|
|
158
|
+
break;
|
|
159
|
+
case 'List':
|
|
160
|
+
(0, print_1.printObject)(value.elems);
|
|
161
|
+
break;
|
|
162
|
+
case 'Object':
|
|
163
|
+
(0, print_1.printObject)(value.entries);
|
|
164
|
+
break;
|
|
165
|
+
default:
|
|
166
|
+
return assertNever(value); // ensures exhaustiveness
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
exports.printLiteral = printLiteral;
|
|
170
|
+
const isScalar = (v) => v.type === 'String' ||
|
|
171
|
+
v.type === 'Number' ||
|
|
172
|
+
v.type === 'Boolean' ||
|
|
173
|
+
v.type === 'Null';
|
|
174
|
+
exports.isScalar = isScalar;
|
|
175
|
+
// export const isList = (v: TValueLiteral): v is TListValue => v.type === 'List'
|
|
176
|
+
// export const isObject = (v: TValueLiteral): v is TObjectValue =>
|
|
177
|
+
// v.type === 'Object'
|
package/package.json
CHANGED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { Bad_memberContext, Boolean_literalContext, ElementContext, ElementsContext, List_in_bracketsContext, ListContext, Member_colon_listContext, MemberContext, Null_literalContext, Number_literalContext, Object_literalContext, ObjectMemberContext, ObjectMemberListContext, Section_membersContext, SectionContext, String_concatContext, String_literalContext, Terminal_lineContext, ValueContext, YiniContext } from '../grammar/YiniParser.js';
|
|
2
|
-
import YiniParserVisitor from '../grammar/YiniParserVisitor';
|
|
3
|
-
import { ErrorDataHandler } from './ErrorDataHandler';
|
|
4
|
-
export type TDataType = undefined | 'String' | 'Number-Integer' | 'Number-Float' | 'Boolean' | 'Null' | 'Object' | 'List';
|
|
5
|
-
/**
|
|
6
|
-
* This interface defines a complete generic visitor for a parse tree produced
|
|
7
|
-
* by `YiniParser`.
|
|
8
|
-
*
|
|
9
|
-
* @param <IResult> The return type of the visit operation. Use `void` for
|
|
10
|
-
* operations with no return type.
|
|
11
|
-
*/
|
|
12
|
-
export default class YINIVisitor<IResult> extends YiniParserVisitor<IResult> {
|
|
13
|
-
private reversedTree;
|
|
14
|
-
private errorHandler;
|
|
15
|
-
private isStrict;
|
|
16
|
-
private lastActiveSectionAtLevels;
|
|
17
|
-
private lastActiveSectionNameAtLevels;
|
|
18
|
-
private numOfLevelOnes;
|
|
19
|
-
private level;
|
|
20
|
-
private prevLevel;
|
|
21
|
-
private prevSectionName;
|
|
22
|
-
private meta_numOfSections;
|
|
23
|
-
private meta_numOfMembers;
|
|
24
|
-
private meta_numOfChains;
|
|
25
|
-
private meta_maxLevelSection;
|
|
26
|
-
private existingSectionTitlesAtLevels;
|
|
27
|
-
private hasDefinedSectionTitle;
|
|
28
|
-
private setDefineSectionTitle;
|
|
29
|
-
constructor(errorHandler: ErrorDataHandler, isStrict: boolean);
|
|
30
|
-
private pushOnTree;
|
|
31
|
-
private getDepthOfLevels;
|
|
32
|
-
private setLastActiveSection;
|
|
33
|
-
/**
|
|
34
|
-
* Visit a parse tree produced by `YiniParser.yini`.
|
|
35
|
-
* @param ctx the parse tree
|
|
36
|
-
* @return the visitor result
|
|
37
|
-
*/
|
|
38
|
-
visitYini: (ctx: YiniContext, isStrict?: boolean) => any;
|
|
39
|
-
/**
|
|
40
|
-
* Will visit here on EVERY section.
|
|
41
|
-
* @param ctx the parse tree
|
|
42
|
-
* @returns { [sectionName]: sectionObj }
|
|
43
|
-
*/
|
|
44
|
-
visitSection: (ctx: SectionContext) => any;
|
|
45
|
-
/**
|
|
46
|
-
* Visit a parse tree produced by `YiniParser.bad_member`.
|
|
47
|
-
* @param ctx the parse tree
|
|
48
|
-
* @return the visitor result
|
|
49
|
-
*/
|
|
50
|
-
visitBad_member: (ctx: Bad_memberContext) => any;
|
|
51
|
-
/**
|
|
52
|
-
* Visit a parse tree produced by `YiniParser.terminal_line`.
|
|
53
|
-
* @param ctx the parse tree
|
|
54
|
-
* @return the visitor result
|
|
55
|
-
*/
|
|
56
|
-
visitTerminal_line?: (ctx: Terminal_lineContext) => IResult;
|
|
57
|
-
/**
|
|
58
|
-
* Visit a parse tree produced by `YiniParser.section_members`.
|
|
59
|
-
* In here will mount object onto members object.
|
|
60
|
-
* @param ctx the parse tree
|
|
61
|
-
* @returns { key: value, ... }
|
|
62
|
-
*/
|
|
63
|
-
visitSection_members: (ctx: Section_membersContext) => any;
|
|
64
|
-
/**
|
|
65
|
-
* Visit every single section or member (any key-value pair such as
|
|
66
|
-
* key=value or key=[...] etc.).
|
|
67
|
-
* @returns {
|
|
68
|
-
type: resultType,
|
|
69
|
-
key: resultKey,
|
|
70
|
-
value: resultValue,
|
|
71
|
-
}: IResult
|
|
72
|
-
*/
|
|
73
|
-
visitMember: (ctx: MemberContext) => IResult;
|
|
74
|
-
/**
|
|
75
|
-
* Visit a parse tree produced by `YiniParser.member_colon_list`.
|
|
76
|
-
* @param ctx the parse tree
|
|
77
|
-
* @return the visitor result
|
|
78
|
-
*/
|
|
79
|
-
visitMember_colon_list: (ctx: Member_colon_listContext) => IResult;
|
|
80
|
-
/**
|
|
81
|
-
* Visit a parse tree produced by `YiniParser.value`.
|
|
82
|
-
* @param ctx the parse tree
|
|
83
|
-
* @return the visitor result
|
|
84
|
-
*/
|
|
85
|
-
visitValue: (ctx: ValueContext) => any;
|
|
86
|
-
/**
|
|
87
|
-
* Visit a parse tree produced by `YiniParser.string_literal`.
|
|
88
|
-
* @param ctx the parse tree
|
|
89
|
-
* @return the visitor result
|
|
90
|
-
*/
|
|
91
|
-
visitString_literal: (ctx: String_literalContext) => IResult;
|
|
92
|
-
/**
|
|
93
|
-
* Visit a parse tree produced by `YiniParser.number_literal`.
|
|
94
|
-
* @param ctx the parse tree
|
|
95
|
-
* @return the visitor result
|
|
96
|
-
*/
|
|
97
|
-
visitNumber_literal: (ctx: Number_literalContext) => IResult;
|
|
98
|
-
/**
|
|
99
|
-
* Visit a parse tree produced by `YiniParser.boolean_literal`.
|
|
100
|
-
* @param ctx the parse tree
|
|
101
|
-
* @return the visitor result
|
|
102
|
-
*/
|
|
103
|
-
visitBoolean_literal: (ctx: Boolean_literalContext) => IResult;
|
|
104
|
-
/**
|
|
105
|
-
* Visit a parse tree produced by `YiniParser.null_literal`.
|
|
106
|
-
* @param ctx the parse tree
|
|
107
|
-
* @return the visitor result
|
|
108
|
-
*/
|
|
109
|
-
visitNull_literal: (ctx: Null_literalContext) => IResult;
|
|
110
|
-
/**
|
|
111
|
-
* Visit a parse tree produced by `YiniParser.object_literal`.
|
|
112
|
-
* @param ctx the parse tree
|
|
113
|
-
* @return the visitor result
|
|
114
|
-
*/
|
|
115
|
-
visitObject_literal: (ctx: Object_literalContext) => IResult;
|
|
116
|
-
/**
|
|
117
|
-
* Visit a parse tree produced by `YiniParser.objectMemberList`.
|
|
118
|
-
* @param ctx the parse tree
|
|
119
|
-
* @return the visitor result
|
|
120
|
-
*/
|
|
121
|
-
visitObjectMemberList: (ctx: ObjectMemberListContext) => IResult;
|
|
122
|
-
/**
|
|
123
|
-
* Visit a parse tree produced by `YiniParser.objectMember`.
|
|
124
|
-
* @param ctx the parse tree
|
|
125
|
-
* @return the visitor result
|
|
126
|
-
*/
|
|
127
|
-
visitObjectMember: (ctx: ObjectMemberContext) => IResult;
|
|
128
|
-
/**
|
|
129
|
-
* Visit a parse tree produced by `YiniParser.list`.
|
|
130
|
-
* @param ctx the parse tree
|
|
131
|
-
* @return the visitor result
|
|
132
|
-
*/
|
|
133
|
-
visitList: (ctx: ListContext) => IResult;
|
|
134
|
-
/**
|
|
135
|
-
* Visit a parse tree produced by `YiniParser.list_in_brackets`.
|
|
136
|
-
* @param ctx the parse tree
|
|
137
|
-
* @return the visitor result
|
|
138
|
-
*/
|
|
139
|
-
visitList_in_brackets: (ctx: List_in_bracketsContext) => IResult;
|
|
140
|
-
/**
|
|
141
|
-
* Visit a parse tree produced by `YiniParser.elements`.
|
|
142
|
-
* @param ctx the parse tree
|
|
143
|
-
* @return the visitor result
|
|
144
|
-
*/
|
|
145
|
-
visitElements: (ctx: ElementsContext) => IResult;
|
|
146
|
-
/**
|
|
147
|
-
* Visit a parse tree produced by `YiniParser.element`.
|
|
148
|
-
* @param ctx the parse tree
|
|
149
|
-
* @return the visitor result
|
|
150
|
-
*/
|
|
151
|
-
visitElement: (ctx: ElementContext) => any;
|
|
152
|
-
/**
|
|
153
|
-
* Visit a parse tree produced by `YiniParser.string_concat`.
|
|
154
|
-
* @param ctx the parse tree
|
|
155
|
-
* @return the visitor result
|
|
156
|
-
*/
|
|
157
|
-
visitString_concat?: (ctx: String_concatContext) => IResult;
|
|
158
|
-
}
|