jsonh-ts 1.0.0

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.
Files changed (56) hide show
  1. package/build/index.d.ts +22 -0
  2. package/build/index.d.ts.map +1 -0
  3. package/build/index.js +22 -0
  4. package/build/index.js.map +1 -0
  5. package/build/json-token-type.d.ts +77 -0
  6. package/build/json-token-type.d.ts.map +1 -0
  7. package/build/json-token-type.js +79 -0
  8. package/build/json-token-type.js.map +1 -0
  9. package/build/jsonh-number-parser.d.ts +21 -0
  10. package/build/jsonh-number-parser.d.ts.map +1 -0
  11. package/build/jsonh-number-parser.js +174 -0
  12. package/build/jsonh-number-parser.js.map +1 -0
  13. package/build/jsonh-reader-options.d.ts +25 -0
  14. package/build/jsonh-reader-options.d.ts.map +1 -0
  15. package/build/jsonh-reader-options.js +26 -0
  16. package/build/jsonh-reader-options.js.map +1 -0
  17. package/build/jsonh-reader.d.ts +68 -0
  18. package/build/jsonh-reader.d.ts.map +1 -0
  19. package/build/jsonh-reader.js +1218 -0
  20. package/build/jsonh-reader.js.map +1 -0
  21. package/build/jsonh-token.d.ts +21 -0
  22. package/build/jsonh-token.d.ts.map +1 -0
  23. package/build/jsonh-token.js +36 -0
  24. package/build/jsonh-token.js.map +1 -0
  25. package/build/jsonh-version.d.ts +15 -0
  26. package/build/jsonh-version.d.ts.map +1 -0
  27. package/build/jsonh-version.js +17 -0
  28. package/build/jsonh-version.js.map +1 -0
  29. package/build/result-helpers.d.ts +6 -0
  30. package/build/result-helpers.d.ts.map +1 -0
  31. package/build/result-helpers.js +11 -0
  32. package/build/result-helpers.js.map +1 -0
  33. package/build/result.d.ts +48 -0
  34. package/build/result.d.ts.map +1 -0
  35. package/build/result.js +95 -0
  36. package/build/result.js.map +1 -0
  37. package/build/string-text-reader.d.ts +11 -0
  38. package/build/string-text-reader.d.ts.map +1 -0
  39. package/build/string-text-reader.js +33 -0
  40. package/build/string-text-reader.js.map +1 -0
  41. package/build/text-reader.d.ts +20 -0
  42. package/build/text-reader.d.ts.map +1 -0
  43. package/build/text-reader.js +19 -0
  44. package/build/text-reader.js.map +1 -0
  45. package/index.ts +21 -0
  46. package/json-token-type.ts +77 -0
  47. package/jsonh-number-parser.ts +191 -0
  48. package/jsonh-reader-options.ts +26 -0
  49. package/jsonh-reader.ts +1317 -0
  50. package/jsonh-token.ts +37 -0
  51. package/jsonh-version.ts +15 -0
  52. package/package.json +30 -0
  53. package/result.ts +97 -0
  54. package/string-text-reader.ts +35 -0
  55. package/text-reader.ts +30 -0
  56. package/tsconfig.json +38 -0
@@ -0,0 +1,191 @@
1
+ import Result = require("./result.js");
2
+
3
+ /**
4
+ * Methods for parsing JSONH numbers.
5
+ *
6
+ * Unlike `JsonhReader.readElement()`, minimal validation is done here. Ensure the input is valid.
7
+ */
8
+ class JsonhNumberParser {
9
+ /**
10
+ * Converts a JSONH number to a base-10 real.
11
+ * For example:
12
+ *
13
+ * ```
14
+ * Input: +5.2e3.0
15
+ * Output: 5200
16
+ * ```
17
+ */
18
+ static parse(jsonhNumber: string): Result<number> {
19
+ // Remove underscores
20
+ jsonhNumber = jsonhNumber.replaceAll("_", "");
21
+ let digits: string = jsonhNumber;
22
+
23
+ // Get sign
24
+ let sign: number = 1;
25
+ if (digits.startsWith('-')) {
26
+ sign = -1;
27
+ digits = digits.slice(1);
28
+ }
29
+ else if (digits.startsWith('+')) {
30
+ sign = 1;
31
+ digits = digits.slice(1);
32
+ }
33
+
34
+ // Decimal
35
+ let baseDigits: string = "0123456789";
36
+ // Hexadecimal
37
+ if (digits.startsWith("0x") || digits.startsWith("0X")) {
38
+ baseDigits = "0123456789abcdef";
39
+ digits = digits.slice(2);
40
+ }
41
+ // Binary
42
+ else if (digits.startsWith("0b") || digits.startsWith("0B")) {
43
+ baseDigits = "01";
44
+ digits = digits.slice(2);
45
+ }
46
+ // Octal
47
+ else if (digits.startsWith("0o") || digits.startsWith("0O")) {
48
+ baseDigits = "01234567";
49
+ digits = digits.slice(2);
50
+ }
51
+
52
+ // Parse number with base digits
53
+ let number: Result<number> = this.#parseFractionalNumberWithExponent(digits, baseDigits);
54
+ if (number.isError) {
55
+ return number;
56
+ }
57
+
58
+ // Apply sign
59
+ if (sign !== 1) {
60
+ number.value *= sign;
61
+ }
62
+ return number;
63
+ }
64
+
65
+ /**
66
+ * Converts a fractional number with an exponent (e.g. `12.3e4.5`) from the given base (e.g. `01234567`) to a base-10 real.
67
+ */
68
+ static #parseFractionalNumberWithExponent(digits: string, baseDigits: string): Result<number> {
69
+ // Find exponent
70
+ let exponentIndex: number = -1;
71
+ // Hexadecimal exponent
72
+ if (baseDigits.includes('e')) {
73
+ for (let index: number = 0; index < digits.length; index++) {
74
+ if (digits.at(index) !== 'e' && digits.at(index) !== 'E') {
75
+ continue;
76
+ }
77
+ if (index + 1 >= digits.length || (digits.at(index + 1) !== '+' && digits.at(index + 1) !== '-')) {
78
+ continue;
79
+ }
80
+ exponentIndex = index;
81
+ break;
82
+ }
83
+ }
84
+ // Exponent
85
+ else {
86
+ exponentIndex = this.#indexOfAny(digits, ['e', 'E']);
87
+ }
88
+
89
+ // If no exponent then parse real
90
+ if (exponentIndex < 0) {
91
+ return this.#parseFractionalNumber(digits, baseDigits);
92
+ }
93
+
94
+ // Get mantissa and exponent
95
+ let mantissaPart: string = digits.slice(0, exponentIndex);
96
+ let exponentPart: string = digits.slice(exponentIndex + 1);
97
+
98
+ // Parse mantissa and exponent
99
+ let mantissa: Result<number> = this.#parseFractionalNumber(mantissaPart, baseDigits);
100
+ if (mantissa.isError) {
101
+ return mantissa;
102
+ }
103
+ let exponent: Result<number> = this.#parseFractionalNumber(exponentPart, baseDigits);
104
+ if (exponent.isError) {
105
+ return exponent;
106
+ }
107
+
108
+ // Multiply mantissa by 10 ^ exponent
109
+ return Result.fromValue(mantissa.value * (10 ** exponent.value));
110
+ }
111
+ /**
112
+ * Converts a fractional number (e.g. `123.45`) from the given base (e.g. `01234567`) to a base-10 real.
113
+ */
114
+ static #parseFractionalNumber(digits: string, baseDigits: string): Result<number> {
115
+ // Find dot
116
+ let dotIndex: number = digits.indexOf('.');
117
+ // If no dot then normalize integer
118
+ if (dotIndex < 0) {
119
+ return this.#parseWholeNumber(digits, baseDigits);
120
+ }
121
+
122
+ // Get parts of number
123
+ let wholePart: string = digits.slice(0, dotIndex);
124
+ let fractionalPart: string = digits.slice(dotIndex + 1);
125
+
126
+ // Parse parts of number
127
+ let whole: Result<number> = this.#parseWholeNumber(wholePart, baseDigits);
128
+ if (whole.isError) {
129
+ return whole;
130
+ }
131
+ let fraction: Result<number> = this.#parseWholeNumber(fractionalPart, baseDigits);
132
+ if (fraction.isError) {
133
+ return fraction;
134
+ }
135
+
136
+ // Combine whole and fraction
137
+ return Result.fromValue(Number.parseFloat(whole.value + '.' + fraction.value));
138
+ }
139
+ /**
140
+ * Converts a whole number (e.g. `12345`) from the given base (e.g. `01234567`) to a base-10 integer.
141
+ */
142
+ static #parseWholeNumber(digits: string, baseDigits: string): Result<number> {
143
+ // Get sign
144
+ let sign: number = 1;
145
+ if (digits.startsWith('-')) {
146
+ sign = -1;
147
+ digits = digits.slice(1);
148
+ }
149
+ else if (digits.startsWith('+')) {
150
+ sign = 1;
151
+ digits = digits.slice(1);
152
+ }
153
+
154
+ // Add each column of digits
155
+ let integer: number = 0;
156
+ for (let index: number = 0; index < digits.length; index++) {
157
+ // Get current digit
158
+ let digitChar: string = digits.at(index)!;
159
+ let digitInt: number = baseDigits.indexOf(digitChar.toLowerCase());
160
+
161
+ // Ensure digit is valid
162
+ if (digitInt < 0) {
163
+ return Result.fromError(new Error(`Invalid digit: '${digitChar}'`));
164
+ }
165
+
166
+ // Get magnitude of current digit column
167
+ let columnNumber: number = digits.length - 1 - index;
168
+ let columnMagnitude: number = baseDigits.length ** columnNumber;
169
+
170
+ // Add value of column
171
+ integer += digitInt * columnMagnitude;
172
+ }
173
+
174
+ // Apply sign
175
+ if (sign !== 1) {
176
+ integer *= sign;
177
+ }
178
+ return Result.fromValue(integer);
179
+ }
180
+ static #indexOfAny(input: string, chars: ReadonlyArray<string>): number {
181
+ for (let i: number = 0; i < input.length; i++) {
182
+ let char: string = input.at(i)!;
183
+ if (chars.includes(char)) {
184
+ return i;
185
+ }
186
+ }
187
+ return -1;
188
+ }
189
+ }
190
+
191
+ export = JsonhNumberParser;
@@ -0,0 +1,26 @@
1
+ import JsonhVersion = require("./jsonh-version.js");
2
+
3
+ /**
4
+ * Options for a JsonhReader.
5
+ */
6
+ class JsonhReaderOptions {
7
+ /**
8
+ * Specifies the major version of the JSONH specification to use.
9
+ */
10
+ version: JsonhVersion = JsonhVersion.Latest;
11
+ /**
12
+ * Enables/disables parsing unclosed inputs.
13
+ *
14
+ * ```
15
+ * {
16
+ "key": "val
17
+ * ```
18
+ *
19
+ * This is potentially useful for large language models that stream responses.
20
+ *
21
+ * Only some tokens can be incomplete in this mode, so it should not be relied upon.
22
+ */
23
+ incompleteInputs: boolean = false;
24
+ }
25
+
26
+ export = JsonhReaderOptions;