yini-parser 1.0.0-beta.1 → 1.0.2-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 +15 -2
- package/README.md +52 -230
- package/dist/YINI.js +6 -36
- package/dist/core/YINIVisitor.d.ts +7 -1
- package/dist/core/YINIVisitor.js +9 -2
- package/dist/grammar/YiniLexer.d.ts +1 -0
- package/dist/grammar/YiniLexer.js +238 -228
- package/dist/grammar/YiniParser.d.ts +17 -0
- package/dist/grammar/YiniParser.js +477 -302
- package/dist/grammar/YiniParserVisitor.d.ts +7 -0
- package/dist/grammar/YiniParserVisitor.js +1 -1
- package/dist/index.js +32 -110
- package/dist/parseEntry.js +27 -7
- package/dist/parsers/parseNumber.js +30 -10
- package/package.json +7 -3
|
@@ -20,6 +20,7 @@ import { String_concatContext } from "./YiniParser.js";
|
|
|
20
20
|
import { Boolean_literalContext } from "./YiniParser.js";
|
|
21
21
|
import { Empty_objectContext } from "./YiniParser.js";
|
|
22
22
|
import { Empty_listContext } from "./YiniParser.js";
|
|
23
|
+
import { Bad_memberContext } from "./YiniParser.js";
|
|
23
24
|
/**
|
|
24
25
|
* This interface defines a complete generic visitor for a parse tree produced
|
|
25
26
|
* by `YiniParser`.
|
|
@@ -154,4 +155,10 @@ export default class YiniParserVisitor<Result> extends ParseTreeVisitor<Result>
|
|
|
154
155
|
* @return the visitor result
|
|
155
156
|
*/
|
|
156
157
|
visitEmpty_list?: (ctx: Empty_listContext) => Result;
|
|
158
|
+
/**
|
|
159
|
+
* Visit a parse tree produced by `YiniParser.bad_member`.
|
|
160
|
+
* @param ctx the parse tree
|
|
161
|
+
* @return the visitor result
|
|
162
|
+
*/
|
|
163
|
+
visitBad_member?: (ctx: Bad_memberContext) => Result;
|
|
157
164
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// import { isDebug&&console.log } from './utils/general'
|
|
3
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
-
};
|
|
6
|
-
var _a, _b, _c;
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.parseFile = exports.parse = void 0;
|
|
9
2
|
/*
|
|
10
|
-
https://
|
|
3
|
+
https://github.com/YINI-lang/yini-parser-typescript/blob/main/docs/Project-Setup.md
|
|
11
4
|
|
|
12
5
|
Run the code with the following command:
|
|
13
|
-
npx ts-node index
|
|
14
|
-
or
|
|
15
6
|
npm start
|
|
7
|
+
or
|
|
8
|
+
npm run start:dev
|
|
9
|
+
or
|
|
10
|
+
npm run start:dev:debug
|
|
16
11
|
|
|
17
12
|
/END
|
|
18
13
|
*/
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
var _a, _b, _c;
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.parseFile = exports.parse = void 0;
|
|
19
20
|
const env_1 = require("./config/env");
|
|
20
21
|
const print_1 = require("./utils/print");
|
|
21
22
|
const YINI_1 = __importDefault(require("./YINI"));
|
|
22
|
-
// export { default } from './YINI'
|
|
23
23
|
exports.parse = YINI_1.default.parse;
|
|
24
24
|
exports.parseFile = YINI_1.default.parseFile;
|
|
25
25
|
exports.default = YINI_1.default;
|
|
@@ -52,100 +52,8 @@ if ((0, env_1.isProdEnv)()) {
|
|
|
52
52
|
// Do nothing, and exit.
|
|
53
53
|
}
|
|
54
54
|
else {
|
|
55
|
-
const invalidInput1 = `
|
|
56
|
-
^ Settings
|
|
57
|
-
fruit = "Pear"
|
|
58
|
-
number = 5
|
|
59
|
-
value q= "something"
|
|
60
|
-
`;
|
|
61
|
-
const invalidInput2 = `
|
|
62
|
-
^ Config
|
|
63
|
-
varAge = 30
|
|
64
|
-
varName = abcd
|
|
65
|
-
varNull = NULL
|
|
66
|
-
`;
|
|
67
|
-
const input1 = `
|
|
68
|
-
^ SectionName
|
|
69
|
-
varBool = true
|
|
70
|
-
varBool2 = off
|
|
71
|
-
varInt = 30
|
|
72
|
-
varFloat = 12.34
|
|
73
|
-
varStr = "Alice"
|
|
74
|
-
listItems = ["a", "b", "c"]
|
|
75
|
-
varE1 = 1e4
|
|
76
|
-
varE2 = 1.23e4
|
|
77
|
-
varE3 = 6.5E23
|
|
78
|
-
/END
|
|
79
|
-
`;
|
|
80
|
-
const input2 = `
|
|
81
|
-
^ Config
|
|
82
|
-
varAge = 30
|
|
83
|
-
varName = "Alice"
|
|
84
|
-
varNull = NULL
|
|
85
|
-
listItems = ["a", "b", "c"]
|
|
86
|
-
^^Extra
|
|
87
|
-
isExtra = true
|
|
88
|
-
/END
|
|
89
|
-
`;
|
|
90
|
-
// const input = `
|
|
91
|
-
// # Config`;
|
|
92
|
-
// debugPrint('input2:')
|
|
93
|
-
// if (isDebug()) {
|
|
94
|
-
// console.debug(input2)
|
|
95
|
-
// }
|
|
96
|
-
// YINI.parse(input2)
|
|
97
|
-
// debugPrint('invalidInput1:')
|
|
98
|
-
// if (isDebug()) {
|
|
99
|
-
// console.debug(invalidInput1)
|
|
100
|
-
// }
|
|
101
|
-
// YINI.parse(invalidInput1)
|
|
102
55
|
if (env_1.localAppEnv === 'local' && env_1.localNodeEnv !== 'test') {
|
|
103
|
-
|
|
104
|
-
YINI.parse(`
|
|
105
|
-
--^ Section0
|
|
106
|
-
--value = 0
|
|
107
|
-
^ Section1
|
|
108
|
-
value = 1
|
|
109
|
-
|
|
110
|
-
^^ Section11
|
|
111
|
-
value = 11
|
|
112
|
-
|
|
113
|
-
^^^ Section111
|
|
114
|
-
value = 111
|
|
115
|
-
//^^^^ Section2104
|
|
116
|
-
value = 24
|
|
117
|
-
|
|
118
|
-
^ Section2
|
|
119
|
-
value = 2
|
|
120
|
-
`)
|
|
121
|
-
}
|
|
122
|
-
*/
|
|
123
|
-
// YINI.parse(`number = 42`)
|
|
124
|
-
/*
|
|
125
|
-
Expected JS output:
|
|
126
|
-
{
|
|
127
|
-
Section1: { value: 1, Section2: { value: 11 }},
|
|
128
|
-
Section2: { value: 2 }
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
*/
|
|
132
|
-
/*
|
|
133
|
-
YINI.parse(
|
|
134
|
-
`
|
|
135
|
-
// Using numeric shorthand section markers.
|
|
136
|
-
|
|
137
|
-
@yini
|
|
138
|
-
|
|
139
|
-
// This whole line is a comment.
|
|
140
|
-
^SectionName# This part is a comment.
|
|
141
|
-
// This whole line is a comment.
|
|
142
|
-
--x=1
|
|
143
|
-
`,
|
|
144
|
-
false,
|
|
145
|
-
2,
|
|
146
|
-
)
|
|
147
|
-
*/
|
|
148
|
-
// YINI.parse(`^1 SectionName`, false, 2)
|
|
56
|
+
// parseUntilError(`^1 SectionName`, false, 2)
|
|
149
57
|
// const validYini = `
|
|
150
58
|
// < user
|
|
151
59
|
// username = 'tester two'
|
|
@@ -169,18 +77,32 @@ Expected JS output:
|
|
|
169
77
|
// notifications = ON
|
|
170
78
|
// `
|
|
171
79
|
// // Act.
|
|
172
|
-
// const result =
|
|
80
|
+
// const result = parseUntilError(validYini)
|
|
173
81
|
// debugPrint(result)
|
|
174
82
|
// const validYini = `^ App
|
|
175
83
|
// id = 32403 # The correct app id.
|
|
176
84
|
// title = "My Program"
|
|
177
85
|
// `
|
|
178
86
|
const yini = `
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
87
|
+
^ DozNumbers
|
|
88
|
+
^^ WithXE
|
|
89
|
+
doz1 = 0z00
|
|
90
|
+
doz2 = 0z01 // One with leading zeros
|
|
91
|
+
doz3 = 0z100 // Decimal 144 (X/A is digit for 10 in base-12)
|
|
92
|
+
doz4 = 0z7EE // Decimal 1151
|
|
93
|
+
doz5 = 0zX00 // Decimal 1440 (E/B is digit for 11 in base-12)
|
|
94
|
+
|
|
95
|
+
^^ WithAB
|
|
96
|
+
doz6 = 0z7BB // Decimal 1151
|
|
97
|
+
doz7 = 0zA00 // Decimal 1440 (E/B is digit for 11 in base-12)
|
|
98
|
+
`;
|
|
99
|
+
console.log((0, print_1.toPrettyJSON)(YINI_1.default.parse(yini, false)));
|
|
100
|
+
// console.log(
|
|
101
|
+
// toPrettyJSON(YINI.parseFile('comprehensive-example.yini', true)),
|
|
102
|
+
// )
|
|
103
|
+
// const fileName = './tests/fixtures/valid/common/common-config-2.yini'
|
|
104
|
+
// YINI.parseFile(fileName, false)
|
|
105
|
+
// parseUntilError(`
|
|
184
106
|
// ^ Section1
|
|
185
107
|
// ^^ Section2
|
|
186
108
|
// ^^^ Section3
|
package/dist/parseEntry.js
CHANGED
|
@@ -12,13 +12,13 @@ const YINIVisitor_1 = __importDefault(require("./core/YINIVisitor"));
|
|
|
12
12
|
const YiniLexer_1 = __importDefault(require("./grammar/YiniLexer"));
|
|
13
13
|
const YiniParser_1 = __importDefault(require("./grammar/YiniParser"));
|
|
14
14
|
const print_1 = require("./utils/print");
|
|
15
|
-
class
|
|
15
|
+
class MyParserErrorListener {
|
|
16
16
|
constructor(errorHandler) {
|
|
17
17
|
this.errors = [];
|
|
18
18
|
this.errorHandler = errorHandler;
|
|
19
19
|
}
|
|
20
20
|
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) {
|
|
21
|
-
(0, print_1.debugPrint)('ANTLR
|
|
21
|
+
(0, print_1.debugPrint)('ANTLR parser cached an error');
|
|
22
22
|
this.errors.push(`Line ${line}:${charPositionInLine} ${msg}`);
|
|
23
23
|
const msgWhat = `Syntax error, at line: ${line}`;
|
|
24
24
|
const msgWhy = `At about column ${1 + charPositionInLine} ${msg}`;
|
|
@@ -29,6 +29,20 @@ class MyErrorListener {
|
|
|
29
29
|
reportAttemptingFullContext(...args) { }
|
|
30
30
|
reportContextSensitivity(...args) { }
|
|
31
31
|
}
|
|
32
|
+
class MyLexerErrorListener {
|
|
33
|
+
constructor(errorHandler) {
|
|
34
|
+
this.errors = [];
|
|
35
|
+
this.errorHandler = errorHandler;
|
|
36
|
+
}
|
|
37
|
+
syntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e) {
|
|
38
|
+
// Handle the error as you want:
|
|
39
|
+
(0, print_1.debugPrint)('ANTLR parser cached an error');
|
|
40
|
+
this.errors.push(`Line ${line}:${charPositionInLine} ${msg}`);
|
|
41
|
+
const msgWhat = `Syntax error, at line: ${line}`;
|
|
42
|
+
const msgWhy = `At about column ${1 + charPositionInLine} ${msg}`;
|
|
43
|
+
this.errorHandler.pushOrBail(null, 'Syntax-Error', msgWhat, msgWhy);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
32
46
|
const parseMain = (yiniContent, options = {
|
|
33
47
|
isStrict: false,
|
|
34
48
|
bailSensitivityLevel: 0,
|
|
@@ -58,17 +72,23 @@ const parseMain = (yiniContent, options = {
|
|
|
58
72
|
const tokenStream = new antlr4_1.CommonTokenStream(lexer);
|
|
59
73
|
const parser = new YiniParser_1.default(tokenStream);
|
|
60
74
|
const errorHandler = new ErrorDataHandler_1.ErrorDataHandler(persistThreshold);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
// Remove the default ConsoleErrorListener
|
|
76
|
+
lexer.removeErrorListeners(); // Removes the default lexer console error output.
|
|
77
|
+
const lexerErrorListener = new MyLexerErrorListener(errorHandler);
|
|
78
|
+
lexer.addErrorListener(lexerErrorListener);
|
|
79
|
+
// const errorListener = new MyParserErrorListener(errorHandler)
|
|
80
|
+
parser.removeErrorListeners(); // Removes the default parser console error output.
|
|
81
|
+
const parserErrorListener = new MyParserErrorListener(errorHandler);
|
|
82
|
+
parser.addErrorListener(parserErrorListener);
|
|
64
83
|
(0, print_1.debugPrint)();
|
|
65
84
|
(0, print_1.debugPrint)('--- Starting parsing... ---');
|
|
66
85
|
const parseTree = parser.yini(); // The function yini() is the start rule.
|
|
67
|
-
if (
|
|
86
|
+
if (parserErrorListener.errors.length > 0 ||
|
|
87
|
+
lexerErrorListener.errors.length > 0) {
|
|
68
88
|
(0, print_1.debugPrint)('*** ERROR detected ***');
|
|
69
89
|
if ((0, env_1.isDebug)()) {
|
|
70
90
|
// Handle or display syntax errors
|
|
71
|
-
console.error('Syntax errors detected:',
|
|
91
|
+
console.error('Syntax errors detected:', parserErrorListener.errors, lexerErrorListener.errors);
|
|
72
92
|
//process.exit(1)
|
|
73
93
|
}
|
|
74
94
|
}
|
|
@@ -3,37 +3,57 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const print_1 = require("../utils/print");
|
|
4
4
|
const parseNumberLiteral = (txt) => {
|
|
5
5
|
(0, print_1.debugPrint)('-> Entered parseNumberLiteral(..), txt: ' + txt);
|
|
6
|
-
if (/^
|
|
6
|
+
if (/^[+-]?(?:\d+\.\d*|\d*\.?\d+)e[+-]?\d+$/i.test(txt)) {
|
|
7
|
+
// Exp. numbers
|
|
8
|
+
(0, print_1.debugPrint)('* Identified as an exp number');
|
|
9
|
+
return {
|
|
10
|
+
type: 'Number-Float',
|
|
11
|
+
// value: parseInt(txt.replace('#', '0x'), 16),
|
|
12
|
+
value: parseFloat(txt),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
// --- Hexadecimal ---------
|
|
16
|
+
if (/^[+-]?(0[xX]|#)/.test(txt)) {
|
|
7
17
|
// Prefix: 0x, 0X, #
|
|
8
18
|
(0, print_1.debugPrint)('* Identified as a hex number');
|
|
19
|
+
(0, print_1.debugPrint)('parsed out HEX: ' + txt.replace(/0[xX]|#/, ''));
|
|
9
20
|
return {
|
|
10
21
|
type: 'Number-Integer',
|
|
11
22
|
// value: parseInt(txt.replace('#', '0x'), 16),
|
|
12
|
-
value: parseInt(txt.replace(
|
|
23
|
+
value: parseInt(txt.replace(/0[xX]|#/, ''), 16),
|
|
13
24
|
};
|
|
14
25
|
}
|
|
15
|
-
|
|
26
|
+
// --- Binary ---------
|
|
27
|
+
if (/^[+-]?(0[bB]|%)/.test(txt)) {
|
|
16
28
|
// Prefix: 0b, 0B, %
|
|
17
29
|
(0, print_1.debugPrint)('* Identified as a bin number');
|
|
30
|
+
(0, print_1.debugPrint)('parsed out BIN: ' + txt.replace(/0[bB]|%/, ''));
|
|
18
31
|
return {
|
|
19
32
|
type: 'Number-Integer',
|
|
20
|
-
value: parseInt(txt.replace(
|
|
33
|
+
value: parseInt(txt.replace(/0[bB]|%/, ''), 2),
|
|
21
34
|
};
|
|
22
35
|
}
|
|
23
|
-
|
|
36
|
+
// --- Octal ---------
|
|
37
|
+
if (/^[+-]?0[oO]/.test(txt)) {
|
|
24
38
|
// Prefix: 0o, 0O
|
|
25
|
-
(0, print_1.debugPrint)('* Identified as a
|
|
39
|
+
(0, print_1.debugPrint)('* Identified as a oct number');
|
|
40
|
+
(0, print_1.debugPrint)('parsed out OCT: ' + txt.replace(/0[oO]/, ''));
|
|
26
41
|
return {
|
|
27
42
|
type: 'Number-Integer',
|
|
28
|
-
value: parseInt(txt.replace(
|
|
43
|
+
value: parseInt(txt.replace(/0[oO]/, ''), 8),
|
|
29
44
|
};
|
|
30
45
|
}
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
// --- Duodecimal ---------
|
|
47
|
+
if (/^[+-]?0[zZ]/.test(txt)) {
|
|
48
|
+
// Prefix: 0z, 0Z, x = A = 10, e = B = 11.
|
|
33
49
|
(0, print_1.debugPrint)('* Identified as a duodecimal number');
|
|
50
|
+
(0, print_1.debugPrint)('parsed out DOZ: ' + txt.replace(/0[zZ]/, ''));
|
|
51
|
+
txt = txt.replace(/[xX]/g, 'A');
|
|
52
|
+
txt = txt.replace(/[eE]/g, 'B');
|
|
53
|
+
(0, print_1.debugPrint)('Converter to AB form: ' + txt.replace(/0[zZ]/, ''));
|
|
34
54
|
return {
|
|
35
55
|
type: 'Number-Integer',
|
|
36
|
-
value: parseInt(txt.replace(
|
|
56
|
+
value: parseInt(txt.replace(/0[zZ]/, ''), 12),
|
|
37
57
|
};
|
|
38
58
|
}
|
|
39
59
|
// In a regex literal the dot must be escaped (\.) to match a literal '.'
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yini-parser",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.2-beta",
|
|
4
|
+
"description": "Node.js parser for YINI — a clean, structured INI alternative with types, simple section nesting, comments, and strict mode.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"yini",
|
|
7
7
|
"yini-parser",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"nodejs",
|
|
20
20
|
"javascript"
|
|
21
21
|
],
|
|
22
|
-
"homepage": "https://
|
|
22
|
+
"homepage": "https://github.com/YINI-lang/yini-parser-typescript",
|
|
23
23
|
"license": "Apache-2.0",
|
|
24
24
|
"files": [
|
|
25
25
|
"dist/",
|
|
@@ -54,9 +54,13 @@
|
|
|
54
54
|
"test:smoke": "cross-env NODE_ENV=test APP_ENV=local jest tests/smoke --bail --verbose --runInBand",
|
|
55
55
|
"test:unit": "cross-env NODE_ENV=test APP_ENV=local jest tests/unit --bail --verbose --runInBand",
|
|
56
56
|
"test:integr": "cross-env NODE_ENV=test APP_ENV=local jest tests/integration --bail --verbose --runInBand",
|
|
57
|
+
"test:issues": "cross-env NODE_ENV=test APP_ENV=local jest tests/fixed-issues --bail --verbose --runInBand",
|
|
58
|
+
"test:gold": "cross-env NODE_ENV=test APP_ENV=local jest tests/golden --bail --verbose --runInBand",
|
|
57
59
|
"test:smoke:debug": "cross-env npm run test:smoke -- --isDebug=1",
|
|
58
60
|
"test:unit:debug": "cross-env npm run test:unit -- --isDebug=1",
|
|
59
61
|
"test:integr:debug": "cross-env npm run test:integr -- --isDebug=1",
|
|
62
|
+
"test:issues:debug": "cross-env npm run test:issues -- --isDebug=1",
|
|
63
|
+
"test:gold:debug": "cross-env npm run test:gold -- --isDebug=1",
|
|
60
64
|
"test:esm": "node ./tests/fixtures/test-src-files/esm-smoke.js",
|
|
61
65
|
"ci:test": "cross-env NODE_ENV=test APP_ENV=ci jest --verbose --runInBand",
|
|
62
66
|
"ci:test:smoke": "cross-env NODE_ENV=test APP_ENV=ci jest tests/smoke --verbose --runInBand",
|