@sciexpr/parser 0.1.0 → 0.1.2
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/index.cjs +40 -11
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +40 -11
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -139,8 +139,6 @@ var LatexTokenizer = class {
|
|
|
139
139
|
this.pos++;
|
|
140
140
|
return { type: "ampersand" /* Ampersand */, value: "&", position: start, length: 1 };
|
|
141
141
|
}
|
|
142
|
-
if (ch === "\\" && this.input[this.pos + 1] === "\\") {
|
|
143
|
-
}
|
|
144
142
|
if (/[0-9]/.test(ch)) {
|
|
145
143
|
this.pos++;
|
|
146
144
|
while (this.pos < this.input.length && /[0-9.]/.test(this.input[this.pos])) {
|
|
@@ -182,9 +180,17 @@ var LatexParser = class {
|
|
|
182
180
|
// ==========================================================================
|
|
183
181
|
// Parse Expressions
|
|
184
182
|
// ==========================================================================
|
|
185
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Parse a sequence of expressions.
|
|
185
|
+
* @param stopType Optional token type to stop at (e.g. CloseBrace inside a group).
|
|
186
|
+
* When set, the loop breaks BEFORE consuming the stop token.
|
|
187
|
+
*/
|
|
188
|
+
parseExpressions(stopType) {
|
|
186
189
|
const exprs = [];
|
|
187
190
|
while (!this.isEOF()) {
|
|
191
|
+
if (stopType !== void 0 && this.peek()?.type === stopType) {
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
188
194
|
const expr = this.parseExpression();
|
|
189
195
|
if (expr) exprs.push(expr);
|
|
190
196
|
}
|
|
@@ -220,6 +226,10 @@ var LatexParser = class {
|
|
|
220
226
|
this.advance();
|
|
221
227
|
expr = (0, import_core2.createSymbol)(token.value, this.classifySymbol(token.value));
|
|
222
228
|
break;
|
|
229
|
+
case "ampersand" /* Ampersand */:
|
|
230
|
+
this.advance();
|
|
231
|
+
expr = (0, import_core2.createSymbol)("&", import_core.SymbolType.Ordinary);
|
|
232
|
+
break;
|
|
223
233
|
case "number" /* Number */:
|
|
224
234
|
this.advance();
|
|
225
235
|
expr = (0, import_core2.createSymbol)(token.value, import_core.SymbolType.Number);
|
|
@@ -230,13 +240,13 @@ var LatexParser = class {
|
|
|
230
240
|
// Skip whitespace
|
|
231
241
|
case "openParen" /* OpenParen */:
|
|
232
242
|
this.advance();
|
|
233
|
-
const body = this.parseExpressions();
|
|
243
|
+
const body = this.parseExpressions("closeParen" /* CloseParen */);
|
|
234
244
|
this.skipType("closeParen" /* CloseParen */);
|
|
235
245
|
expr = (0, import_core2.createDelimiter)("(", ")", body.length === 1 ? body[0] : (0, import_core2.createGroup)(body));
|
|
236
246
|
break;
|
|
237
247
|
case "openBracket" /* OpenBracket */:
|
|
238
248
|
this.advance();
|
|
239
|
-
const bracketBody = this.parseExpressions();
|
|
249
|
+
const bracketBody = this.parseExpressions("closeBracket" /* CloseBracket */);
|
|
240
250
|
this.skipType("closeBracket" /* CloseBracket */);
|
|
241
251
|
expr = (0, import_core2.createDelimiter)("[", "]", bracketBody.length === 1 ? bracketBody[0] : (0, import_core2.createGroup)(bracketBody));
|
|
242
252
|
break;
|
|
@@ -346,7 +356,7 @@ var LatexParser = class {
|
|
|
346
356
|
/** 解析 { expressions } 分组 */
|
|
347
357
|
parseGroup() {
|
|
348
358
|
this.skipType("openBrace" /* OpenBrace */);
|
|
349
|
-
const children = this.parseExpressions();
|
|
359
|
+
const children = this.parseExpressions("closeBrace" /* CloseBrace */);
|
|
350
360
|
this.skipType("closeBrace" /* CloseBrace */);
|
|
351
361
|
return (0, import_core2.createGroup)(children);
|
|
352
362
|
}
|
|
@@ -453,9 +463,17 @@ var ChemicalParser = class {
|
|
|
453
463
|
}
|
|
454
464
|
groupCount = parseInt(numStr, 10);
|
|
455
465
|
if (groupCount && groupCount > 1) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
466
|
+
const multiplier = groupCount;
|
|
467
|
+
const scaledAtoms = groupAtoms.map(
|
|
468
|
+
(atom) => (0, import_core4.createChemElement)(atom.symbol, {
|
|
469
|
+
count: (atom.count ?? 1) * multiplier,
|
|
470
|
+
isotope: atom.isotope,
|
|
471
|
+
charge: atom.charge,
|
|
472
|
+
chargeSign: atom.chargeSign
|
|
473
|
+
})
|
|
474
|
+
);
|
|
475
|
+
nodes.push((0, import_core4.createChemGroup)(scaledAtoms));
|
|
476
|
+
continue;
|
|
459
477
|
}
|
|
460
478
|
}
|
|
461
479
|
nodes.push((0, import_core4.createChemGroup)(groupAtoms));
|
|
@@ -473,8 +491,12 @@ var ChemicalParser = class {
|
|
|
473
491
|
const chargeMatch = chargeStr.match(/^(\d*)([+\-])$/);
|
|
474
492
|
if (chargeMatch) {
|
|
475
493
|
const el = lastNode;
|
|
476
|
-
|
|
477
|
-
|
|
494
|
+
nodes[nodes.length - 1] = (0, import_core4.createChemElement)(el.symbol, {
|
|
495
|
+
count: el.count,
|
|
496
|
+
isotope: el.isotope,
|
|
497
|
+
charge: parseInt(chargeMatch[1] || "1", 10),
|
|
498
|
+
chargeSign: chargeMatch[2]
|
|
499
|
+
});
|
|
478
500
|
}
|
|
479
501
|
}
|
|
480
502
|
continue;
|
|
@@ -495,6 +517,7 @@ var ChemicalParser = class {
|
|
|
495
517
|
};
|
|
496
518
|
|
|
497
519
|
// src/registry.ts
|
|
520
|
+
var import_core5 = require("@sciexpr/core");
|
|
498
521
|
var ParserRegistry = class {
|
|
499
522
|
parsers = /* @__PURE__ */ new Map();
|
|
500
523
|
defaultParsers;
|
|
@@ -535,6 +558,9 @@ var ParserRegistry = class {
|
|
|
535
558
|
* @returns 解析后的 AST
|
|
536
559
|
*/
|
|
537
560
|
parse(input, options) {
|
|
561
|
+
if (!input || input.trim().length === 0) {
|
|
562
|
+
return (0, import_core5.createRoot)(import_core5.ExpressionKind.Text, []);
|
|
563
|
+
}
|
|
538
564
|
if (options?.hint && options.hint !== "auto") {
|
|
539
565
|
const parser2 = this.parsers.get(options.hint);
|
|
540
566
|
if (parser2) {
|
|
@@ -545,6 +571,9 @@ var ParserRegistry = class {
|
|
|
545
571
|
if (parser) {
|
|
546
572
|
return parser.parse(input, options);
|
|
547
573
|
}
|
|
574
|
+
if (options?.hint === "physics") {
|
|
575
|
+
return this.defaultParsers[0].parse(input, options);
|
|
576
|
+
}
|
|
548
577
|
return this.defaultParsers[0].parse(input, options);
|
|
549
578
|
}
|
|
550
579
|
/** 列出所有已注册的解析器 ID */
|
package/dist/index.d.cts
CHANGED
|
@@ -14,7 +14,7 @@ interface IParser {
|
|
|
14
14
|
/** 解析选项 */
|
|
15
15
|
interface ParseOptions {
|
|
16
16
|
/** 输入格式提示 */
|
|
17
|
-
hint?: 'latex' | 'chemical' | 'unicode' | 'auto';
|
|
17
|
+
hint?: 'latex' | 'chemical' | 'physics' | 'unicode' | 'auto';
|
|
18
18
|
/** 是否为 display 模式 */
|
|
19
19
|
displayMode?: boolean;
|
|
20
20
|
/** 自定义宏 */
|
|
@@ -83,6 +83,11 @@ declare class LatexParser implements IParser {
|
|
|
83
83
|
private displayMode;
|
|
84
84
|
canParse(input: string): boolean;
|
|
85
85
|
parse(input: string, options?: ParseOptions): ExpressionRoot;
|
|
86
|
+
/**
|
|
87
|
+
* Parse a sequence of expressions.
|
|
88
|
+
* @param stopType Optional token type to stop at (e.g. CloseBrace inside a group).
|
|
89
|
+
* When set, the loop breaks BEFORE consuming the stop token.
|
|
90
|
+
*/
|
|
86
91
|
private parseExpressions;
|
|
87
92
|
private parseExpression;
|
|
88
93
|
/** 处理上/下标:检查 ^ 和 _ 后附加到 base 节点 */
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ interface IParser {
|
|
|
14
14
|
/** 解析选项 */
|
|
15
15
|
interface ParseOptions {
|
|
16
16
|
/** 输入格式提示 */
|
|
17
|
-
hint?: 'latex' | 'chemical' | 'unicode' | 'auto';
|
|
17
|
+
hint?: 'latex' | 'chemical' | 'physics' | 'unicode' | 'auto';
|
|
18
18
|
/** 是否为 display 模式 */
|
|
19
19
|
displayMode?: boolean;
|
|
20
20
|
/** 自定义宏 */
|
|
@@ -83,6 +83,11 @@ declare class LatexParser implements IParser {
|
|
|
83
83
|
private displayMode;
|
|
84
84
|
canParse(input: string): boolean;
|
|
85
85
|
parse(input: string, options?: ParseOptions): ExpressionRoot;
|
|
86
|
+
/**
|
|
87
|
+
* Parse a sequence of expressions.
|
|
88
|
+
* @param stopType Optional token type to stop at (e.g. CloseBrace inside a group).
|
|
89
|
+
* When set, the loop breaks BEFORE consuming the stop token.
|
|
90
|
+
*/
|
|
86
91
|
private parseExpressions;
|
|
87
92
|
private parseExpression;
|
|
88
93
|
/** 处理上/下标:检查 ^ 和 _ 后附加到 base 节点 */
|
package/dist/index.js
CHANGED
|
@@ -109,8 +109,6 @@ var LatexTokenizer = class {
|
|
|
109
109
|
this.pos++;
|
|
110
110
|
return { type: "ampersand" /* Ampersand */, value: "&", position: start, length: 1 };
|
|
111
111
|
}
|
|
112
|
-
if (ch === "\\" && this.input[this.pos + 1] === "\\") {
|
|
113
|
-
}
|
|
114
112
|
if (/[0-9]/.test(ch)) {
|
|
115
113
|
this.pos++;
|
|
116
114
|
while (this.pos < this.input.length && /[0-9.]/.test(this.input[this.pos])) {
|
|
@@ -161,9 +159,17 @@ var LatexParser = class {
|
|
|
161
159
|
// ==========================================================================
|
|
162
160
|
// Parse Expressions
|
|
163
161
|
// ==========================================================================
|
|
164
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Parse a sequence of expressions.
|
|
164
|
+
* @param stopType Optional token type to stop at (e.g. CloseBrace inside a group).
|
|
165
|
+
* When set, the loop breaks BEFORE consuming the stop token.
|
|
166
|
+
*/
|
|
167
|
+
parseExpressions(stopType) {
|
|
165
168
|
const exprs = [];
|
|
166
169
|
while (!this.isEOF()) {
|
|
170
|
+
if (stopType !== void 0 && this.peek()?.type === stopType) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
167
173
|
const expr = this.parseExpression();
|
|
168
174
|
if (expr) exprs.push(expr);
|
|
169
175
|
}
|
|
@@ -199,6 +205,10 @@ var LatexParser = class {
|
|
|
199
205
|
this.advance();
|
|
200
206
|
expr = createSymbol(token.value, this.classifySymbol(token.value));
|
|
201
207
|
break;
|
|
208
|
+
case "ampersand" /* Ampersand */:
|
|
209
|
+
this.advance();
|
|
210
|
+
expr = createSymbol("&", SymbolType.Ordinary);
|
|
211
|
+
break;
|
|
202
212
|
case "number" /* Number */:
|
|
203
213
|
this.advance();
|
|
204
214
|
expr = createSymbol(token.value, SymbolType.Number);
|
|
@@ -209,13 +219,13 @@ var LatexParser = class {
|
|
|
209
219
|
// Skip whitespace
|
|
210
220
|
case "openParen" /* OpenParen */:
|
|
211
221
|
this.advance();
|
|
212
|
-
const body = this.parseExpressions();
|
|
222
|
+
const body = this.parseExpressions("closeParen" /* CloseParen */);
|
|
213
223
|
this.skipType("closeParen" /* CloseParen */);
|
|
214
224
|
expr = createDelimiter("(", ")", body.length === 1 ? body[0] : createGroup(body));
|
|
215
225
|
break;
|
|
216
226
|
case "openBracket" /* OpenBracket */:
|
|
217
227
|
this.advance();
|
|
218
|
-
const bracketBody = this.parseExpressions();
|
|
228
|
+
const bracketBody = this.parseExpressions("closeBracket" /* CloseBracket */);
|
|
219
229
|
this.skipType("closeBracket" /* CloseBracket */);
|
|
220
230
|
expr = createDelimiter("[", "]", bracketBody.length === 1 ? bracketBody[0] : createGroup(bracketBody));
|
|
221
231
|
break;
|
|
@@ -325,7 +335,7 @@ var LatexParser = class {
|
|
|
325
335
|
/** 解析 { expressions } 分组 */
|
|
326
336
|
parseGroup() {
|
|
327
337
|
this.skipType("openBrace" /* OpenBrace */);
|
|
328
|
-
const children = this.parseExpressions();
|
|
338
|
+
const children = this.parseExpressions("closeBrace" /* CloseBrace */);
|
|
329
339
|
this.skipType("closeBrace" /* CloseBrace */);
|
|
330
340
|
return createGroup(children);
|
|
331
341
|
}
|
|
@@ -432,9 +442,17 @@ var ChemicalParser = class {
|
|
|
432
442
|
}
|
|
433
443
|
groupCount = parseInt(numStr, 10);
|
|
434
444
|
if (groupCount && groupCount > 1) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
445
|
+
const multiplier = groupCount;
|
|
446
|
+
const scaledAtoms = groupAtoms.map(
|
|
447
|
+
(atom) => createChemElement(atom.symbol, {
|
|
448
|
+
count: (atom.count ?? 1) * multiplier,
|
|
449
|
+
isotope: atom.isotope,
|
|
450
|
+
charge: atom.charge,
|
|
451
|
+
chargeSign: atom.chargeSign
|
|
452
|
+
})
|
|
453
|
+
);
|
|
454
|
+
nodes.push(createChemGroup(scaledAtoms));
|
|
455
|
+
continue;
|
|
438
456
|
}
|
|
439
457
|
}
|
|
440
458
|
nodes.push(createChemGroup(groupAtoms));
|
|
@@ -452,8 +470,12 @@ var ChemicalParser = class {
|
|
|
452
470
|
const chargeMatch = chargeStr.match(/^(\d*)([+\-])$/);
|
|
453
471
|
if (chargeMatch) {
|
|
454
472
|
const el = lastNode;
|
|
455
|
-
|
|
456
|
-
|
|
473
|
+
nodes[nodes.length - 1] = createChemElement(el.symbol, {
|
|
474
|
+
count: el.count,
|
|
475
|
+
isotope: el.isotope,
|
|
476
|
+
charge: parseInt(chargeMatch[1] || "1", 10),
|
|
477
|
+
chargeSign: chargeMatch[2]
|
|
478
|
+
});
|
|
457
479
|
}
|
|
458
480
|
}
|
|
459
481
|
continue;
|
|
@@ -474,6 +496,7 @@ var ChemicalParser = class {
|
|
|
474
496
|
};
|
|
475
497
|
|
|
476
498
|
// src/registry.ts
|
|
499
|
+
import { createRoot as createRoot3, ExpressionKind as ExpressionKind3 } from "@sciexpr/core";
|
|
477
500
|
var ParserRegistry = class {
|
|
478
501
|
parsers = /* @__PURE__ */ new Map();
|
|
479
502
|
defaultParsers;
|
|
@@ -514,6 +537,9 @@ var ParserRegistry = class {
|
|
|
514
537
|
* @returns 解析后的 AST
|
|
515
538
|
*/
|
|
516
539
|
parse(input, options) {
|
|
540
|
+
if (!input || input.trim().length === 0) {
|
|
541
|
+
return createRoot3(ExpressionKind3.Text, []);
|
|
542
|
+
}
|
|
517
543
|
if (options?.hint && options.hint !== "auto") {
|
|
518
544
|
const parser2 = this.parsers.get(options.hint);
|
|
519
545
|
if (parser2) {
|
|
@@ -524,6 +550,9 @@ var ParserRegistry = class {
|
|
|
524
550
|
if (parser) {
|
|
525
551
|
return parser.parse(input, options);
|
|
526
552
|
}
|
|
553
|
+
if (options?.hint === "physics") {
|
|
554
|
+
return this.defaultParsers[0].parse(input, options);
|
|
555
|
+
}
|
|
527
556
|
return this.defaultParsers[0].parse(input, options);
|
|
528
557
|
}
|
|
529
558
|
/** 列出所有已注册的解析器 ID */
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sciexpr/parser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Scientific Expression Engine - LaTeX & Chemical formula parser",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
|
-
"module": "./dist/index.
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
|
-
"import": "./dist/index.
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
13
|
"require": "./dist/index.cjs"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@sciexpr/core": "0.1.
|
|
46
|
+
"@sciexpr/core": "0.1.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"tsup": "^8.0.0",
|