shell-dsl 0.0.34 → 0.0.36
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/README.md +41 -5
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/fs/memfs-adapter.cjs +56 -2
- package/dist/cjs/src/fs/memfs-adapter.cjs.map +3 -3
- package/dist/cjs/src/fs/real-fs.cjs +134 -3
- package/dist/cjs/src/fs/real-fs.cjs.map +3 -3
- package/dist/cjs/src/fs/special-files.cjs +3 -2
- package/dist/cjs/src/fs/special-files.cjs.map +3 -3
- package/dist/cjs/src/fs/web-fs.cjs +72 -3
- package/dist/cjs/src/fs/web-fs.cjs.map +3 -3
- package/dist/cjs/src/index.cjs +2 -7
- package/dist/cjs/src/index.cjs.map +3 -3
- package/dist/cjs/src/interpreter/interpreter.cjs +186 -68
- package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
- package/dist/cjs/src/parser/ast.cjs +5 -25
- package/dist/cjs/src/parser/ast.cjs.map +3 -3
- package/dist/cjs/src/parser/index.cjs +2 -7
- package/dist/cjs/src/parser/index.cjs.map +3 -3
- package/dist/cjs/src/parser/parser.cjs +132 -82
- package/dist/cjs/src/parser/parser.cjs.map +3 -3
- package/dist/cjs/src/types.cjs.map +2 -2
- package/dist/cjs/src/vcs/content.cjs +106 -0
- package/dist/cjs/src/vcs/content.cjs.map +10 -0
- package/dist/cjs/src/vcs/diff.cjs +72 -28
- package/dist/cjs/src/vcs/diff.cjs.map +3 -3
- package/dist/cjs/src/vcs/index.cjs.map +1 -1
- package/dist/cjs/src/vcs/objects.cjs +141 -0
- package/dist/cjs/src/vcs/objects.cjs.map +10 -0
- package/dist/cjs/src/vcs/rules.cjs +6 -3
- package/dist/cjs/src/vcs/rules.cjs.map +3 -3
- package/dist/cjs/src/vcs/snapshot.cjs +89 -39
- package/dist/cjs/src/vcs/snapshot.cjs.map +3 -3
- package/dist/cjs/src/vcs/storage.cjs +44 -3
- package/dist/cjs/src/vcs/storage.cjs.map +3 -3
- package/dist/cjs/src/vcs/text-diff.cjs +219 -0
- package/dist/cjs/src/vcs/text-diff.cjs.map +10 -0
- package/dist/cjs/src/vcs/vcs.cjs +108 -61
- package/dist/cjs/src/vcs/vcs.cjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/src/fs/memfs-adapter.mjs +57 -2
- package/dist/mjs/src/fs/memfs-adapter.mjs.map +3 -3
- package/dist/mjs/src/fs/real-fs.mjs +135 -3
- package/dist/mjs/src/fs/real-fs.mjs.map +3 -3
- package/dist/mjs/src/fs/special-files.mjs +3 -2
- package/dist/mjs/src/fs/special-files.mjs.map +3 -3
- package/dist/mjs/src/fs/web-fs.mjs +72 -3
- package/dist/mjs/src/fs/web-fs.mjs.map +3 -3
- package/dist/mjs/src/index.mjs +4 -14
- package/dist/mjs/src/index.mjs.map +3 -3
- package/dist/mjs/src/interpreter/interpreter.mjs +186 -68
- package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
- package/dist/mjs/src/parser/ast.mjs +5 -25
- package/dist/mjs/src/parser/ast.mjs.map +3 -3
- package/dist/mjs/src/parser/index.mjs +4 -14
- package/dist/mjs/src/parser/index.mjs.map +3 -3
- package/dist/mjs/src/parser/parser.mjs +132 -82
- package/dist/mjs/src/parser/parser.mjs.map +3 -3
- package/dist/mjs/src/types.mjs.map +2 -2
- package/dist/mjs/src/vcs/content.mjs +66 -0
- package/dist/mjs/src/vcs/content.mjs.map +10 -0
- package/dist/mjs/src/vcs/diff.mjs +72 -28
- package/dist/mjs/src/vcs/diff.mjs.map +3 -3
- package/dist/mjs/src/vcs/index.mjs.map +1 -1
- package/dist/mjs/src/vcs/objects.mjs +106 -0
- package/dist/mjs/src/vcs/objects.mjs.map +10 -0
- package/dist/mjs/src/vcs/rules.mjs +6 -3
- package/dist/mjs/src/vcs/rules.mjs.map +3 -3
- package/dist/mjs/src/vcs/snapshot.mjs +89 -39
- package/dist/mjs/src/vcs/snapshot.mjs.map +3 -3
- package/dist/mjs/src/vcs/storage.mjs +45 -3
- package/dist/mjs/src/vcs/storage.mjs.map +3 -3
- package/dist/mjs/src/vcs/text-diff.mjs +179 -0
- package/dist/mjs/src/vcs/text-diff.mjs.map +10 -0
- package/dist/mjs/src/vcs/vcs.mjs +115 -63
- package/dist/mjs/src/vcs/vcs.mjs.map +3 -3
- package/dist/types/src/fs/real-fs.d.ts +12 -1
- package/dist/types/src/index.d.ts +4 -4
- package/dist/types/src/interpreter/interpreter.d.ts +15 -1
- package/dist/types/src/parser/ast.d.ts +34 -38
- package/dist/types/src/parser/index.d.ts +2 -2
- package/dist/types/src/parser/parser.d.ts +4 -1
- package/dist/types/src/types.d.ts +10 -0
- package/dist/types/src/vcs/content.d.ts +6 -0
- package/dist/types/src/vcs/diff.d.ts +10 -7
- package/dist/types/src/vcs/index.d.ts +1 -1
- package/dist/types/src/vcs/objects.d.ts +22 -0
- package/dist/types/src/vcs/snapshot.d.ts +13 -8
- package/dist/types/src/vcs/storage.d.ts +7 -1
- package/dist/types/src/vcs/text-diff.d.ts +1 -0
- package/dist/types/src/vcs/types.d.ts +20 -5
- package/dist/types/src/vcs/vcs.d.ts +6 -0
- package/package.json +7 -2
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// src/parser/ast.ts
|
|
2
|
+
function isWordNode(node) {
|
|
3
|
+
return node.type === "word";
|
|
4
|
+
}
|
|
2
5
|
function isCommandNode(node) {
|
|
3
6
|
return node.type === "command";
|
|
4
7
|
}
|
|
@@ -14,21 +17,6 @@ function isOrNode(node) {
|
|
|
14
17
|
function isSequenceNode(node) {
|
|
15
18
|
return node.type === "sequence";
|
|
16
19
|
}
|
|
17
|
-
function isLiteralNode(node) {
|
|
18
|
-
return node.type === "literal";
|
|
19
|
-
}
|
|
20
|
-
function isVariableNode(node) {
|
|
21
|
-
return node.type === "variable";
|
|
22
|
-
}
|
|
23
|
-
function isSubstitutionNode(node) {
|
|
24
|
-
return node.type === "substitution";
|
|
25
|
-
}
|
|
26
|
-
function isGlobNode(node) {
|
|
27
|
-
return node.type === "glob";
|
|
28
|
-
}
|
|
29
|
-
function isConcatNode(node) {
|
|
30
|
-
return node.type === "concat";
|
|
31
|
-
}
|
|
32
20
|
function isIfNode(node) {
|
|
33
21
|
return node.type === "if";
|
|
34
22
|
}
|
|
@@ -44,26 +32,18 @@ function isUntilNode(node) {
|
|
|
44
32
|
function isCaseNode(node) {
|
|
45
33
|
return node.type === "case";
|
|
46
34
|
}
|
|
47
|
-
function isArithmeticNode(node) {
|
|
48
|
-
return node.type === "arithmetic";
|
|
49
|
-
}
|
|
50
35
|
export {
|
|
36
|
+
isWordNode,
|
|
51
37
|
isWhileNode,
|
|
52
|
-
isVariableNode,
|
|
53
38
|
isUntilNode,
|
|
54
|
-
isSubstitutionNode,
|
|
55
39
|
isSequenceNode,
|
|
56
40
|
isPipelineNode,
|
|
57
41
|
isOrNode,
|
|
58
|
-
isLiteralNode,
|
|
59
42
|
isIfNode,
|
|
60
|
-
isGlobNode,
|
|
61
43
|
isForNode,
|
|
62
|
-
isConcatNode,
|
|
63
44
|
isCommandNode,
|
|
64
45
|
isCaseNode,
|
|
65
|
-
isArithmeticNode,
|
|
66
46
|
isAndNode
|
|
67
47
|
};
|
|
68
48
|
|
|
69
|
-
//# debugId=
|
|
49
|
+
//# debugId=A94B2B641FD2258A64756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parser/ast.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport interface
|
|
5
|
+
"export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport interface TextPart {\n type: \"text\";\n value: string;\n quoted: boolean;\n}\n\nexport interface VariablePart {\n type: \"variable\";\n name: string;\n quoted: boolean;\n}\n\nexport interface SubstitutionPart {\n type: \"substitution\";\n command: ASTNode;\n quoted: boolean;\n}\n\nexport interface ArithmeticPart {\n type: \"arithmetic\";\n expression: string;\n quoted: boolean;\n}\n\nexport type WordPart = TextPart | VariablePart | SubstitutionPart | ArithmeticPart;\n\nexport interface WordNode {\n type: \"word\";\n parts: WordPart[];\n}\n\nexport interface Redirect {\n mode: RedirectMode;\n target: WordNode;\n heredocContent?: boolean;\n}\n\nexport type ASTNode =\n | CommandNode\n | PipelineNode\n | AndNode\n | OrNode\n | SequenceNode\n | IfNode\n | ForNode\n | WhileNode\n | UntilNode\n | CaseNode;\n\nexport interface CommandNode {\n type: \"command\";\n name: WordNode;\n args: WordNode[];\n redirects: Redirect[];\n assignments: Array<{ name: string; value: WordNode }>;\n}\n\nexport interface PipelineNode {\n type: \"pipeline\";\n commands: ASTNode[];\n}\n\nexport interface AndNode {\n type: \"and\";\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface OrNode {\n type: \"or\";\n left: ASTNode;\n right: ASTNode;\n}\n\nexport interface SequenceNode {\n type: \"sequence\";\n commands: ASTNode[];\n}\n\nexport interface IfNode {\n type: \"if\";\n condition: ASTNode;\n thenBranch: ASTNode;\n elifBranches: Array<{ condition: ASTNode; body: ASTNode }>;\n elseBranch?: ASTNode;\n}\n\nexport interface ForNode {\n type: \"for\";\n variable: string;\n items: WordNode[];\n body: ASTNode;\n}\n\nexport interface WhileNode {\n type: \"while\";\n condition: ASTNode;\n body: ASTNode;\n}\n\nexport interface UntilNode {\n type: \"until\";\n condition: ASTNode;\n body: ASTNode;\n}\n\nexport interface CaseClause {\n patterns: WordNode[];\n body: ASTNode;\n}\n\nexport interface CaseNode {\n type: \"case\";\n word: WordNode;\n clauses: CaseClause[];\n}\n\n// Type guards\nexport function isWordNode(node: ASTNode | WordNode): node is WordNode {\n return node.type === \"word\";\n}\n\nexport function isCommandNode(node: ASTNode): node is CommandNode {\n return node.type === \"command\";\n}\n\nexport function isPipelineNode(node: ASTNode): node is PipelineNode {\n return node.type === \"pipeline\";\n}\n\nexport function isAndNode(node: ASTNode): node is AndNode {\n return node.type === \"and\";\n}\n\nexport function isOrNode(node: ASTNode): node is OrNode {\n return node.type === \"or\";\n}\n\nexport function isSequenceNode(node: ASTNode): node is SequenceNode {\n return node.type === \"sequence\";\n}\n\nexport function isIfNode(node: ASTNode): node is IfNode {\n return node.type === \"if\";\n}\n\nexport function isForNode(node: ASTNode): node is ForNode {\n return node.type === \"for\";\n}\n\nexport function isWhileNode(node: ASTNode): node is WhileNode {\n return node.type === \"while\";\n}\n\nexport function isUntilNode(node: ASTNode): node is UntilNode {\n return node.type === \"until\";\n}\n\nexport function isCaseNode(node: ASTNode): node is CaseNode {\n return node.type === \"case\";\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAiIO,SAAS,UAAU,CAAC,MAA4C;AAAA,EACrE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,aAAa,CAAC,MAAoC;AAAA,EAChE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,SAAS,CAAC,MAAgC;AAAA,EACxD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,QAAQ,CAAC,MAA+B;AAAA,EACtD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,QAAQ,CAAC,MAA+B;AAAA,EACtD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,SAAS,CAAC,MAAgC;AAAA,EACxD,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,WAAW,CAAC,MAAkC;AAAA,EAC5D,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,WAAW,CAAC,MAAkC;AAAA,EAC5D,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,UAAU,CAAC,MAAiC;AAAA,EAC1D,OAAO,KAAK,SAAS;AAAA;",
|
|
8
|
+
"debugId": "A94B2B641FD2258A64756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -1,42 +1,32 @@
|
|
|
1
1
|
// src/parser/index.ts
|
|
2
2
|
import { Parser, parse } from "./parser.mjs";
|
|
3
3
|
import {
|
|
4
|
+
isWordNode,
|
|
4
5
|
isCommandNode,
|
|
5
6
|
isPipelineNode,
|
|
6
7
|
isAndNode,
|
|
7
8
|
isOrNode,
|
|
8
9
|
isSequenceNode,
|
|
9
|
-
isLiteralNode,
|
|
10
|
-
isVariableNode,
|
|
11
|
-
isSubstitutionNode,
|
|
12
|
-
isGlobNode,
|
|
13
|
-
isConcatNode,
|
|
14
10
|
isIfNode,
|
|
15
11
|
isForNode,
|
|
16
12
|
isWhileNode,
|
|
17
13
|
isUntilNode,
|
|
18
|
-
isCaseNode
|
|
19
|
-
isArithmeticNode
|
|
14
|
+
isCaseNode
|
|
20
15
|
} from "./ast.mjs";
|
|
21
16
|
export {
|
|
22
17
|
parse,
|
|
18
|
+
isWordNode,
|
|
23
19
|
isWhileNode,
|
|
24
|
-
isVariableNode,
|
|
25
20
|
isUntilNode,
|
|
26
|
-
isSubstitutionNode,
|
|
27
21
|
isSequenceNode,
|
|
28
22
|
isPipelineNode,
|
|
29
23
|
isOrNode,
|
|
30
|
-
isLiteralNode,
|
|
31
24
|
isIfNode,
|
|
32
|
-
isGlobNode,
|
|
33
25
|
isForNode,
|
|
34
|
-
isConcatNode,
|
|
35
26
|
isCommandNode,
|
|
36
27
|
isCaseNode,
|
|
37
|
-
isArithmeticNode,
|
|
38
28
|
isAndNode,
|
|
39
29
|
Parser
|
|
40
30
|
};
|
|
41
31
|
|
|
42
|
-
//# debugId=
|
|
32
|
+
//# debugId=BC1B31107743967964756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parser/index.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export { Parser, parse } from \"./parser.mjs\";\nexport type {\n ASTNode,\n Redirect,\n RedirectMode,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n
|
|
5
|
+
"export { Parser, parse } from \"./parser.mjs\";\nexport type {\n ASTNode,\n Redirect,\n RedirectMode,\n CommandNode,\n PipelineNode,\n AndNode,\n OrNode,\n SequenceNode,\n WordNode,\n WordPart,\n TextPart,\n VariablePart,\n SubstitutionPart,\n ArithmeticPart,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n} from \"./ast.mjs\";\nexport {\n isWordNode,\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isIfNode,\n isForNode,\n isWhileNode,\n isUntilNode,\n isCaseNode,\n} from \"./ast.mjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAAA;AAuBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAAA;AAuBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
|
|
8
|
+
"debugId": "BC1B31107743967964756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -212,7 +212,7 @@ class Parser {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
if (commands.length === 0) {
|
|
215
|
-
return
|
|
215
|
+
return this.createNoopCommand();
|
|
216
216
|
}
|
|
217
217
|
if (commands.length === 1) {
|
|
218
218
|
return commands[0];
|
|
@@ -223,7 +223,7 @@ class Parser {
|
|
|
223
223
|
this.skipNewlines();
|
|
224
224
|
const commands = [];
|
|
225
225
|
if (this.isCompoundListTerminator(terminators)) {
|
|
226
|
-
return
|
|
226
|
+
return this.createNoopCommand();
|
|
227
227
|
}
|
|
228
228
|
commands.push(this.parseAndOr());
|
|
229
229
|
while ((this.match("semicolon") || this.match("newline")) && !this.isAtEnd()) {
|
|
@@ -238,6 +238,21 @@ class Parser {
|
|
|
238
238
|
}
|
|
239
239
|
return { type: "sequence", commands };
|
|
240
240
|
}
|
|
241
|
+
createNoopCommand() {
|
|
242
|
+
return {
|
|
243
|
+
type: "command",
|
|
244
|
+
name: this.createTextWord("true"),
|
|
245
|
+
args: [],
|
|
246
|
+
redirects: [],
|
|
247
|
+
assignments: []
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
createTextWord(value, quoted = false) {
|
|
251
|
+
return {
|
|
252
|
+
type: "word",
|
|
253
|
+
parts: value === "" && !quoted ? [] : [{ type: "text", value, quoted }]
|
|
254
|
+
};
|
|
255
|
+
}
|
|
241
256
|
isCompoundListTerminator(terminators) {
|
|
242
257
|
const token = this.peek();
|
|
243
258
|
if (token.type !== "keyword")
|
|
@@ -262,7 +277,7 @@ class Parser {
|
|
|
262
277
|
const token = this.advance();
|
|
263
278
|
assignments.push({
|
|
264
279
|
name: token.name,
|
|
265
|
-
value: this.
|
|
280
|
+
value: this.tokenToWord(token.value)
|
|
266
281
|
});
|
|
267
282
|
}
|
|
268
283
|
while (this.isWordToken()) {
|
|
@@ -270,7 +285,7 @@ class Parser {
|
|
|
270
285
|
const heredocToken = this.advance();
|
|
271
286
|
redirects.push({
|
|
272
287
|
mode: "<",
|
|
273
|
-
target: this.
|
|
288
|
+
target: this.tokenToWord(heredocToken),
|
|
274
289
|
heredocContent: true
|
|
275
290
|
});
|
|
276
291
|
} else {
|
|
@@ -285,7 +300,7 @@ class Parser {
|
|
|
285
300
|
const heredocToken = this.advance();
|
|
286
301
|
redirects.push({
|
|
287
302
|
mode: "<",
|
|
288
|
-
target: this.
|
|
303
|
+
target: this.tokenToWord(heredocToken),
|
|
289
304
|
heredocContent: true
|
|
290
305
|
});
|
|
291
306
|
} else {
|
|
@@ -296,7 +311,7 @@ class Parser {
|
|
|
296
311
|
if (args.length === 0 && assignments.length === 0 && redirects.length === 0) {
|
|
297
312
|
throw new ParseError("Expected command");
|
|
298
313
|
}
|
|
299
|
-
const name = args.shift() ??
|
|
314
|
+
const name = args.shift() ?? this.createTextWord(redirects.length > 0 ? ":" : "");
|
|
300
315
|
return {
|
|
301
316
|
type: "command",
|
|
302
317
|
name,
|
|
@@ -307,123 +322,158 @@ class Parser {
|
|
|
307
322
|
}
|
|
308
323
|
parseWordArg() {
|
|
309
324
|
const token = this.advance();
|
|
310
|
-
return this.
|
|
325
|
+
return this.tokenToWord(token);
|
|
326
|
+
}
|
|
327
|
+
tokenToWord(token) {
|
|
328
|
+
const parts = this.tokenToWordParts(token);
|
|
329
|
+
return {
|
|
330
|
+
type: "word",
|
|
331
|
+
parts
|
|
332
|
+
};
|
|
311
333
|
}
|
|
312
|
-
|
|
334
|
+
tokenToWordParts(token, quoted = false) {
|
|
313
335
|
if (typeof token === "string") {
|
|
314
|
-
return { type: "
|
|
336
|
+
return [{ type: "text", value: token, quoted }];
|
|
315
337
|
}
|
|
316
338
|
if (Array.isArray(token)) {
|
|
317
|
-
|
|
318
|
-
if (parts.length === 1)
|
|
319
|
-
return parts[0];
|
|
320
|
-
return { type: "concat", parts };
|
|
339
|
+
return token.flatMap((part) => this.tokenToWordParts(part, quoted));
|
|
321
340
|
}
|
|
322
341
|
switch (token.type) {
|
|
323
342
|
case "word":
|
|
324
|
-
return { type: "
|
|
343
|
+
return [{ type: "text", value: token.value, quoted }];
|
|
325
344
|
case "singleQuote":
|
|
326
|
-
return { type: "
|
|
345
|
+
return [{ type: "text", value: token.value, quoted: true }];
|
|
327
346
|
case "doubleQuote":
|
|
328
347
|
return this.parseDoubleQuoteParts(token.parts);
|
|
329
348
|
case "variable":
|
|
330
|
-
return { type: "variable", name: token.name };
|
|
331
|
-
case "substitution":
|
|
349
|
+
return [{ type: "variable", name: token.name, quoted }];
|
|
350
|
+
case "substitution": {
|
|
332
351
|
const innerParser = new Parser(new Lexer(token.command, { preserveNewlines: true }).tokenize());
|
|
333
|
-
return { type: "substitution", command: innerParser.parse() };
|
|
352
|
+
return [{ type: "substitution", command: innerParser.parse(), quoted }];
|
|
353
|
+
}
|
|
334
354
|
case "arithmetic":
|
|
335
|
-
return { type: "arithmetic", expression: token.expression };
|
|
355
|
+
return [{ type: "arithmetic", expression: token.expression, quoted }];
|
|
336
356
|
case "glob":
|
|
337
|
-
return { type: "
|
|
357
|
+
return [{ type: "text", value: token.pattern, quoted }];
|
|
338
358
|
case "assignment":
|
|
339
|
-
return this.
|
|
359
|
+
return this.tokenToWordParts(token.value, quoted);
|
|
340
360
|
case "heredoc":
|
|
341
|
-
|
|
342
|
-
return this.parseHeredocContent(token.content);
|
|
343
|
-
}
|
|
344
|
-
return { type: "literal", value: token.content };
|
|
361
|
+
return token.expand ? this.parseHeredocContent(token.content).parts : [{ type: "text", value: token.content, quoted: true }];
|
|
345
362
|
default:
|
|
346
363
|
throw new ParseError(`Unexpected token type: ${token.type}`);
|
|
347
364
|
}
|
|
348
365
|
}
|
|
349
366
|
parseDoubleQuoteParts(parts) {
|
|
350
367
|
if (parts.length === 0) {
|
|
351
|
-
return { type: "
|
|
368
|
+
return [{ type: "text", value: "", quoted: true }];
|
|
352
369
|
}
|
|
353
|
-
|
|
354
|
-
const part = parts[0];
|
|
355
|
-
if (typeof part === "string") {
|
|
356
|
-
return { type: "literal", value: part };
|
|
357
|
-
}
|
|
358
|
-
return this.tokenToNode(part);
|
|
359
|
-
}
|
|
360
|
-
const nodes = parts.map((part) => {
|
|
361
|
-
if (typeof part === "string") {
|
|
362
|
-
return { type: "literal", value: part };
|
|
363
|
-
}
|
|
364
|
-
return this.tokenToNode(part);
|
|
365
|
-
});
|
|
366
|
-
return { type: "concat", parts: nodes };
|
|
370
|
+
return parts.flatMap((part) => this.tokenToWordParts(part, true));
|
|
367
371
|
}
|
|
368
372
|
parseHeredocContent(content) {
|
|
369
373
|
const parts = [];
|
|
370
|
-
let
|
|
374
|
+
let currentText = "";
|
|
371
375
|
let i = 0;
|
|
376
|
+
const pushText = () => {
|
|
377
|
+
if (currentText.length > 0) {
|
|
378
|
+
parts.push({ type: "text", value: currentText, quoted: false });
|
|
379
|
+
currentText = "";
|
|
380
|
+
}
|
|
381
|
+
};
|
|
372
382
|
while (i < content.length) {
|
|
373
|
-
if (content[i]
|
|
374
|
-
|
|
375
|
-
parts.push({ type: "literal", value: currentLiteral });
|
|
376
|
-
currentLiteral = "";
|
|
377
|
-
}
|
|
383
|
+
if (content[i] !== "$") {
|
|
384
|
+
currentText += content[i];
|
|
378
385
|
i++;
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
386
|
+
continue;
|
|
387
|
+
}
|
|
388
|
+
pushText();
|
|
389
|
+
i++;
|
|
390
|
+
if (i >= content.length) {
|
|
391
|
+
currentText += "$";
|
|
392
|
+
break;
|
|
393
|
+
}
|
|
394
|
+
if (content[i] === "{") {
|
|
395
|
+
i++;
|
|
396
|
+
let name = "";
|
|
397
|
+
while (i < content.length && content[i] !== "}") {
|
|
398
|
+
name += content[i];
|
|
399
|
+
i++;
|
|
382
400
|
}
|
|
383
|
-
if (content[i] === "
|
|
401
|
+
if (i < content.length && content[i] === "}") {
|
|
384
402
|
i++;
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
403
|
+
}
|
|
404
|
+
parts.push({ type: "variable", name, quoted: false });
|
|
405
|
+
continue;
|
|
406
|
+
}
|
|
407
|
+
if (content[i] === "(" && content[i + 1] === "(") {
|
|
408
|
+
i += 2;
|
|
409
|
+
let depth = 1;
|
|
410
|
+
let expression = "";
|
|
411
|
+
while (i < content.length && depth > 0) {
|
|
412
|
+
if (content[i] === "(" && content[i + 1] === "(") {
|
|
413
|
+
depth++;
|
|
414
|
+
expression += content[i] + content[i + 1];
|
|
415
|
+
i += 2;
|
|
416
|
+
continue;
|
|
395
417
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
418
|
+
if (content[i] === ")" && content[i + 1] === ")") {
|
|
419
|
+
depth--;
|
|
420
|
+
if (depth === 0) {
|
|
421
|
+
i += 2;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
expression += content[i] + content[i + 1];
|
|
425
|
+
i += 2;
|
|
426
|
+
continue;
|
|
401
427
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
currentLiteral += "$";
|
|
428
|
+
expression += content[i];
|
|
429
|
+
i++;
|
|
405
430
|
}
|
|
406
|
-
|
|
407
|
-
|
|
431
|
+
parts.push({ type: "arithmetic", expression, quoted: false });
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
if (content[i] === "(") {
|
|
408
435
|
i++;
|
|
436
|
+
let depth = 1;
|
|
437
|
+
let command = "";
|
|
438
|
+
while (i < content.length && depth > 0) {
|
|
439
|
+
if (content[i] === "(") {
|
|
440
|
+
depth++;
|
|
441
|
+
} else if (content[i] === ")") {
|
|
442
|
+
depth--;
|
|
443
|
+
if (depth === 0) {
|
|
444
|
+
i++;
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
command += content[i];
|
|
449
|
+
i++;
|
|
450
|
+
}
|
|
451
|
+
const innerParser = new Parser(new Lexer(command, { preserveNewlines: true }).tokenize());
|
|
452
|
+
parts.push({ type: "substitution", command: innerParser.parse(), quoted: false });
|
|
453
|
+
continue;
|
|
409
454
|
}
|
|
455
|
+
if (/[a-zA-Z_]/.test(content[i] ?? "")) {
|
|
456
|
+
let name = "";
|
|
457
|
+
while (i < content.length && /[a-zA-Z0-9_]/.test(content[i] ?? "")) {
|
|
458
|
+
name += content[i];
|
|
459
|
+
i++;
|
|
460
|
+
}
|
|
461
|
+
parts.push({ type: "variable", name, quoted: false });
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
currentText += "$";
|
|
410
465
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
}
|
|
417
|
-
if (parts.length === 1) {
|
|
418
|
-
return parts[0];
|
|
419
|
-
}
|
|
420
|
-
return { type: "concat", parts };
|
|
466
|
+
pushText();
|
|
467
|
+
return {
|
|
468
|
+
type: "word",
|
|
469
|
+
parts
|
|
470
|
+
};
|
|
421
471
|
}
|
|
422
472
|
parseRedirect() {
|
|
423
473
|
const token = this.advance();
|
|
424
474
|
const mode = token.mode;
|
|
425
475
|
if (mode === "2>&1" || mode === "1>&2") {
|
|
426
|
-
return { mode, target:
|
|
476
|
+
return { mode, target: this.createTextWord("") };
|
|
427
477
|
}
|
|
428
478
|
if (!this.isWordToken()) {
|
|
429
479
|
throw new ParseError(`Expected redirect target after ${mode}`);
|
|
@@ -465,4 +515,4 @@ export {
|
|
|
465
515
|
Parser
|
|
466
516
|
};
|
|
467
517
|
|
|
468
|
-
//# debugId=
|
|
518
|
+
//# debugId=87B78A0C1939D94564756E2164756E21
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/parser/parser.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { ParseError } from \"../errors.mjs\";\nimport { Lexer } from \"../lexer/lexer.mjs\";\nimport type { Token, KeywordValue } from \"../lexer/tokens.mjs\";\nimport type { ASTNode, Redirect, RedirectMode, CommandNode, IfNode, ForNode, WhileNode, UntilNode, CaseNode, CaseClause } from \"./ast.mjs\";\n\nexport class Parser {\n private tokens: Token[];\n private pos: number = 0;\n\n constructor(tokens: Token[]) {\n this.tokens = tokens;\n }\n\n parse(): ASTNode {\n const result = this.parseSequence();\n if (!this.isAtEnd()) {\n throw new ParseError(`Unexpected token: ${JSON.stringify(this.peek())}`);\n }\n return result;\n }\n\n // sequence := and_or ((';'|'\\n') and_or)*\n private parseSequence(): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n commands.push(this.parseAndOr());\n\n while (this.match(\"semicolon\") || this.match(\"newline\")) {\n this.skipNewlines();\n // Skip empty commands after separator, or stop at terminating keywords\n if (this.isAtEnd() || this.check(\"semicolon\") || this.check(\"newline\") || this.isTerminatingKeyword()) continue;\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private skipNewlines(): void {\n while (this.match(\"newline\")) {\n // keep consuming newlines\n }\n }\n\n private isTerminatingKeyword(): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return [\"then\", \"elif\", \"else\", \"fi\", \"do\", \"done\", \"esac\"].includes(token.value);\n }\n\n // and_or := pipeline (('&&'|'||') pipeline)*\n private parseAndOr(): ASTNode {\n let left = this.parsePipeline();\n\n while (this.check(\"and\") || this.check(\"or\")) {\n if (this.match(\"and\")) {\n const right = this.parsePipeline();\n left = { type: \"and\", left, right };\n } else if (this.match(\"or\")) {\n const right = this.parsePipeline();\n left = { type: \"or\", left, right };\n }\n }\n\n return left;\n }\n\n // pipeline := command ('|' command)*\n private parsePipeline(): ASTNode {\n const commands: ASTNode[] = [];\n commands.push(this.parseCompoundOrCommand());\n\n while (this.match(\"pipe\")) {\n this.skipNewlines();\n commands.push(this.parseCompoundOrCommand());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"pipeline\", commands };\n }\n\n // compound_or_command := compound_command | simple_command\n private parseCompoundOrCommand(): ASTNode {\n this.skipNewlines();\n const token = this.peek();\n\n if (token.type === \"keyword\") {\n switch (token.value) {\n case \"if\":\n return this.parseIf();\n case \"for\":\n return this.parseFor();\n case \"while\":\n return this.parseWhile();\n case \"until\":\n return this.parseUntil();\n case \"case\":\n return this.parseCase();\n }\n }\n\n return this.parseCommand();\n }\n\n // if := 'if' compound_list 'then' compound_list ('elif' compound_list 'then' compound_list)* ['else' compound_list] 'fi'\n private parseIf(): IfNode {\n this.expectKeyword(\"if\");\n const condition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const thenBranch = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n\n const elifBranches: Array<{ condition: ASTNode; body: ASTNode }> = [];\n while (this.checkKeyword(\"elif\")) {\n this.expectKeyword(\"elif\");\n const elifCondition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const elifBody = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n elifBranches.push({ condition: elifCondition, body: elifBody });\n }\n\n let elseBranch: ASTNode | undefined;\n if (this.checkKeyword(\"else\")) {\n this.expectKeyword(\"else\");\n elseBranch = this.parseCompoundList([\"fi\"]);\n }\n\n this.expectKeyword(\"fi\");\n\n return {\n type: \"if\",\n condition,\n thenBranch,\n elifBranches,\n elseBranch,\n };\n }\n\n // for := 'for' NAME ['in' word*] (';'|'\\n') 'do' compound_list 'done'\n private parseFor(): ForNode {\n this.expectKeyword(\"for\");\n\n // Get variable name\n const varToken = this.peek();\n if (varToken.type !== \"word\") {\n throw new ParseError(\"Expected variable name after 'for'\");\n }\n this.advance();\n const variable = varToken.value;\n\n // Parse optional 'in' clause\n const items: ASTNode[] = [];\n if (this.checkKeyword(\"in\")) {\n this.expectKeyword(\"in\");\n // Read items until semicolon, newline, or 'do'\n while (!this.isAtEnd() && !this.check(\"semicolon\") && !this.check(\"newline\") && !this.checkKeyword(\"do\")) {\n items.push(this.parseWordArg());\n }\n }\n\n // Consume separator (semicolon or newline)\n if (!this.match(\"semicolon\")) {\n this.match(\"newline\");\n }\n this.skipNewlines();\n\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"for\",\n variable,\n items,\n body,\n };\n }\n\n // while := 'while' compound_list 'do' compound_list 'done'\n private parseWhile(): WhileNode {\n this.expectKeyword(\"while\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"while\",\n condition,\n body,\n };\n }\n\n // until := 'until' compound_list 'do' compound_list 'done'\n private parseUntil(): UntilNode {\n this.expectKeyword(\"until\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"until\",\n condition,\n body,\n };\n }\n\n // case := 'case' word 'in' (pattern ('|' pattern)* ')' compound_list ';;')* 'esac'\n private parseCase(): CaseNode {\n this.expectKeyword(\"case\");\n const word = this.parseWordArg();\n this.expectKeyword(\"in\");\n this.skipNewlines();\n\n const clauses: CaseClause[] = [];\n\n while (!this.isAtEnd() && !this.checkKeyword(\"esac\")) {\n // Parse patterns separated by '|'\n // Skip leading '(' if present\n this.match(\"openParen\");\n\n const patterns: ASTNode[] = [];\n patterns.push(this.parseCasePattern());\n\n while (this.match(\"pipe\")) {\n patterns.push(this.parseCasePattern());\n }\n\n // Expect ')'\n if (!this.match(\"closeParen\")) {\n throw new ParseError(\"Expected ')' after case pattern\");\n }\n\n // Parse body until ';;' or 'esac'\n const body = this.parseCaseBody();\n\n clauses.push({ patterns, body });\n\n // ';;' is optional for the last clause\n this.match(\"doubleSemicolon\");\n this.skipNewlines();\n }\n\n this.expectKeyword(\"esac\");\n\n return {\n type: \"case\",\n word,\n clauses,\n };\n }\n\n private parseCasePattern(): ASTNode {\n const token = this.peek();\n\n // Handle glob patterns and words\n if (token.type === \"word\" || token.type === \"glob\" || token.type === \"singleQuote\" || token.type === \"doubleQuote\") {\n return this.parseWordArg();\n }\n\n throw new ParseError(`Expected pattern in case clause, got ${token.type}`);\n }\n\n private parseCaseBody(): ASTNode {\n const commands: ASTNode[] = [];\n this.skipNewlines();\n\n // Parse until ';;' or 'esac'\n while (!this.isAtEnd() && !this.check(\"doubleSemicolon\") && !this.checkKeyword(\"esac\")) {\n commands.push(this.parseAndOr());\n // Consume separator\n if (!this.match(\"semicolon\") && !this.match(\"newline\")) {\n break;\n }\n this.skipNewlines();\n // Check for terminators after consuming separators\n if (this.check(\"doubleSemicolon\") || this.checkKeyword(\"esac\")) {\n break;\n }\n }\n\n if (commands.length === 0) {\n return { type: \"command\", name: { type: \"literal\", value: \"true\" }, args: [], redirects: [], assignments: [] };\n }\n if (commands.length === 1) {\n return commands[0]!;\n }\n return { type: \"sequence\", commands };\n }\n\n // compound_list := and_or ((';'|'\\n') and_or)* [';'|'\\n']\n private parseCompoundList(terminators: KeywordValue[]): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n\n // Check for empty list\n if (this.isCompoundListTerminator(terminators)) {\n // Return a no-op command for empty list\n return { type: \"command\", name: { type: \"literal\", value: \"true\" }, args: [], redirects: [], assignments: [] };\n }\n\n commands.push(this.parseAndOr());\n\n while ((this.match(\"semicolon\") || this.match(\"newline\")) && !this.isAtEnd()) {\n this.skipNewlines();\n // Check for terminators\n if (this.isCompoundListTerminator(terminators)) {\n break;\n }\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private isCompoundListTerminator(terminators: KeywordValue[]): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return terminators.includes(token.value);\n }\n\n private checkKeyword(value: KeywordValue): boolean {\n const token = this.peek();\n return token.type === \"keyword\" && token.value === value;\n }\n\n private expectKeyword(value: KeywordValue): void {\n if (!this.checkKeyword(value)) {\n throw new ParseError(`Expected '${value}'`);\n }\n this.advance();\n // Don't skip newlines here - let the caller handle them\n // Newlines are significant as command separators in compound lists\n }\n\n // command := assignment* word+ redirect*\n private parseCommand(): CommandNode {\n const assignments: Array<{ name: string; value: ASTNode }> = [];\n const args: ASTNode[] = [];\n const redirects: Redirect[] = [];\n\n // Collect leading assignments\n while (this.check(\"assignment\")) {\n const token = this.advance() as Token & { type: \"assignment\" };\n assignments.push({\n name: token.name,\n value: this.tokenToNode(token.value),\n });\n }\n\n // Collect command name and arguments\n while (this.isWordToken()) {\n // Check if it's a heredoc token - convert to input redirect\n if (this.peek().type === \"heredoc\") {\n const heredocToken = this.advance() as Token & { type: \"heredoc\" };\n redirects.push({\n mode: \"<\",\n target: this.tokenToNode(heredocToken),\n heredocContent: true,\n });\n } else {\n args.push(this.parseWordArg());\n }\n }\n\n // Collect redirects\n while (this.check(\"redirect\")) {\n const redirect = this.parseRedirect();\n redirects.push(redirect);\n // After a redirect, there might be more words\n while (this.isWordToken()) {\n if (this.peek().type === \"heredoc\") {\n const heredocToken = this.advance() as Token & { type: \"heredoc\" };\n redirects.push({\n mode: \"<\",\n target: this.tokenToNode(heredocToken),\n heredocContent: true,\n });\n } else {\n args.push(this.parseWordArg());\n }\n }\n }\n\n if (args.length === 0 && assignments.length === 0 && redirects.length === 0) {\n throw new ParseError(\"Expected command\");\n }\n\n const name = args.shift() ?? { type: \"literal\" as const, value: redirects.length > 0 ? \":\" : \"\" };\n\n return {\n type: \"command\",\n name,\n args,\n redirects,\n assignments,\n };\n }\n\n private parseWordArg(): ASTNode {\n const token = this.advance();\n return this.tokenToNode(token);\n }\n\n private tokenToNode(token: Token | string | Token[]): ASTNode {\n if (typeof token === \"string\") {\n return { type: \"literal\", value: token };\n }\n\n if (Array.isArray(token)) {\n const parts = token.map((t) => this.tokenToNode(t));\n if (parts.length === 1) return parts[0]!;\n return { type: \"concat\", parts };\n }\n\n switch (token.type) {\n case \"word\":\n return { type: \"literal\", value: token.value };\n case \"singleQuote\":\n return { type: \"literal\", value: token.value };\n case \"doubleQuote\":\n return this.parseDoubleQuoteParts(token.parts);\n case \"variable\":\n return { type: \"variable\", name: token.name };\n case \"substitution\":\n // Parse the inner command\n const innerParser = new Parser(\n new Lexer(token.command, { preserveNewlines: true }).tokenize()\n );\n return { type: \"substitution\", command: innerParser.parse() };\n case \"arithmetic\":\n return { type: \"arithmetic\", expression: token.expression };\n case \"glob\":\n return { type: \"glob\", pattern: token.pattern };\n case \"assignment\":\n return this.tokenToNode(token.value);\n case \"heredoc\":\n if (token.expand) {\n return this.parseHeredocContent(token.content);\n }\n return { type: \"literal\", value: token.content };\n default:\n throw new ParseError(`Unexpected token type: ${(token as Token).type}`);\n }\n }\n\n private parseDoubleQuoteParts(parts: Array<string | Token>): ASTNode {\n if (parts.length === 0) {\n return { type: \"literal\", value: \"\" };\n }\n\n if (parts.length === 1) {\n const part = parts[0]!;\n if (typeof part === \"string\") {\n return { type: \"literal\", value: part };\n }\n return this.tokenToNode(part);\n }\n\n const nodes: ASTNode[] = parts.map((part) => {\n if (typeof part === \"string\") {\n return { type: \"literal\" as const, value: part };\n }\n return this.tokenToNode(part);\n });\n\n return { type: \"concat\", parts: nodes };\n }\n\n private parseHeredocContent(content: string): ASTNode {\n // Parse content looking for $VAR and ${VAR} patterns\n const parts: ASTNode[] = [];\n let currentLiteral = \"\";\n let i = 0;\n\n while (i < content.length) {\n if (content[i] === \"$\") {\n // Flush current literal\n if (currentLiteral) {\n parts.push({ type: \"literal\", value: currentLiteral });\n currentLiteral = \"\";\n }\n\n i++; // consume $\n if (i >= content.length) {\n currentLiteral += \"$\";\n break;\n }\n\n if (content[i] === \"{\") {\n // ${VAR} syntax\n i++; // consume {\n let varName = \"\";\n while (i < content.length && content[i] !== \"}\") {\n varName += content[i];\n i++;\n }\n if (i < content.length && content[i] === \"}\") {\n i++; // consume }\n }\n if (varName) {\n parts.push({ type: \"variable\", name: varName });\n }\n } else if (/[a-zA-Z_]/.test(content[i] ?? \"\")) {\n // $VAR syntax\n let varName = \"\";\n while (i < content.length && /[a-zA-Z0-9_]/.test(content[i] ?? \"\")) {\n varName += content[i];\n i++;\n }\n parts.push({ type: \"variable\", name: varName });\n } else {\n // Not a variable, keep the $\n currentLiteral += \"$\";\n }\n } else {\n currentLiteral += content[i];\n i++;\n }\n }\n\n // Flush remaining literal\n if (currentLiteral) {\n parts.push({ type: \"literal\", value: currentLiteral });\n }\n\n if (parts.length === 0) {\n return { type: \"literal\", value: \"\" };\n }\n if (parts.length === 1) {\n return parts[0]!;\n }\n return { type: \"concat\", parts };\n }\n\n private parseRedirect(): Redirect {\n const token = this.advance() as Token & { type: \"redirect\" };\n const mode = token.mode as RedirectMode;\n\n // 2>&1 and 1>&2 don't have a target\n if (mode === \"2>&1\" || mode === \"1>&2\") {\n return { mode, target: { type: \"literal\", value: \"\" } };\n }\n\n if (!this.isWordToken()) {\n throw new ParseError(`Expected redirect target after ${mode}`);\n }\n\n const target = this.parseWordArg();\n return { mode, target };\n }\n\n private isWordToken(): boolean {\n const token = this.peek();\n return (\n Array.isArray(token) ||\n token.type === \"word\" ||\n token.type === \"singleQuote\" ||\n token.type === \"doubleQuote\" ||\n token.type === \"variable\" ||\n token.type === \"substitution\" ||\n token.type === \"arithmetic\" ||\n token.type === \"glob\" ||\n token.type === \"heredoc\"\n );\n }\n\n private check(type: Token[\"type\"]): boolean {\n return this.peek().type === type;\n }\n\n private match(type: Token[\"type\"]): boolean {\n if (this.check(type)) {\n this.advance();\n return true;\n }\n return false;\n }\n\n private peek(): Token {\n return this.tokens[this.pos] ?? { type: \"eof\" };\n }\n\n private advance(): Token {\n const token = this.peek();\n this.pos++;\n return token;\n }\n\n private isAtEnd(): boolean {\n return this.peek().type === \"eof\";\n }\n}\n\nexport function parse(tokens: Token[]): ASTNode {\n return new Parser(tokens).parse();\n}\n"
|
|
5
|
+
"import { ParseError } from \"../errors.mjs\";\nimport { Lexer } from \"../lexer/lexer.mjs\";\nimport type { Token, KeywordValue } from \"../lexer/tokens.mjs\";\nimport type {\n ASTNode,\n Redirect,\n RedirectMode,\n CommandNode,\n IfNode,\n ForNode,\n WhileNode,\n UntilNode,\n CaseNode,\n CaseClause,\n WordNode,\n WordPart,\n} from \"./ast.mjs\";\n\nexport class Parser {\n private tokens: Token[];\n private pos: number = 0;\n\n constructor(tokens: Token[]) {\n this.tokens = tokens;\n }\n\n parse(): ASTNode {\n const result = this.parseSequence();\n if (!this.isAtEnd()) {\n throw new ParseError(`Unexpected token: ${JSON.stringify(this.peek())}`);\n }\n return result;\n }\n\n // sequence := and_or ((';'|'\\n') and_or)*\n private parseSequence(): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n commands.push(this.parseAndOr());\n\n while (this.match(\"semicolon\") || this.match(\"newline\")) {\n this.skipNewlines();\n if (this.isAtEnd() || this.check(\"semicolon\") || this.check(\"newline\") || this.isTerminatingKeyword()) continue;\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private skipNewlines(): void {\n while (this.match(\"newline\")) {\n // keep consuming newlines\n }\n }\n\n private isTerminatingKeyword(): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return [\"then\", \"elif\", \"else\", \"fi\", \"do\", \"done\", \"esac\"].includes(token.value);\n }\n\n // and_or := pipeline (('&&'|'||') pipeline)*\n private parseAndOr(): ASTNode {\n let left = this.parsePipeline();\n\n while (this.check(\"and\") || this.check(\"or\")) {\n if (this.match(\"and\")) {\n const right = this.parsePipeline();\n left = { type: \"and\", left, right };\n } else if (this.match(\"or\")) {\n const right = this.parsePipeline();\n left = { type: \"or\", left, right };\n }\n }\n\n return left;\n }\n\n // pipeline := command ('|' command)*\n private parsePipeline(): ASTNode {\n const commands: ASTNode[] = [];\n commands.push(this.parseCompoundOrCommand());\n\n while (this.match(\"pipe\")) {\n this.skipNewlines();\n commands.push(this.parseCompoundOrCommand());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"pipeline\", commands };\n }\n\n // compound_or_command := compound_command | simple_command\n private parseCompoundOrCommand(): ASTNode {\n this.skipNewlines();\n const token = this.peek();\n\n if (token.type === \"keyword\") {\n switch (token.value) {\n case \"if\":\n return this.parseIf();\n case \"for\":\n return this.parseFor();\n case \"while\":\n return this.parseWhile();\n case \"until\":\n return this.parseUntil();\n case \"case\":\n return this.parseCase();\n }\n }\n\n return this.parseCommand();\n }\n\n // if := 'if' compound_list 'then' compound_list ('elif' compound_list 'then' compound_list)* ['else' compound_list] 'fi'\n private parseIf(): IfNode {\n this.expectKeyword(\"if\");\n const condition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const thenBranch = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n\n const elifBranches: Array<{ condition: ASTNode; body: ASTNode }> = [];\n while (this.checkKeyword(\"elif\")) {\n this.expectKeyword(\"elif\");\n const elifCondition = this.parseCompoundList([\"then\"]);\n this.expectKeyword(\"then\");\n const elifBody = this.parseCompoundList([\"elif\", \"else\", \"fi\"]);\n elifBranches.push({ condition: elifCondition, body: elifBody });\n }\n\n let elseBranch: ASTNode | undefined;\n if (this.checkKeyword(\"else\")) {\n this.expectKeyword(\"else\");\n elseBranch = this.parseCompoundList([\"fi\"]);\n }\n\n this.expectKeyword(\"fi\");\n\n return {\n type: \"if\",\n condition,\n thenBranch,\n elifBranches,\n elseBranch,\n };\n }\n\n // for := 'for' NAME ['in' word*] (';'|'\\n') 'do' compound_list 'done'\n private parseFor(): ForNode {\n this.expectKeyword(\"for\");\n\n const varToken = this.peek();\n if (varToken.type !== \"word\") {\n throw new ParseError(\"Expected variable name after 'for'\");\n }\n this.advance();\n const variable = varToken.value;\n\n const items: WordNode[] = [];\n if (this.checkKeyword(\"in\")) {\n this.expectKeyword(\"in\");\n while (!this.isAtEnd() && !this.check(\"semicolon\") && !this.check(\"newline\") && !this.checkKeyword(\"do\")) {\n items.push(this.parseWordArg());\n }\n }\n\n if (!this.match(\"semicolon\")) {\n this.match(\"newline\");\n }\n this.skipNewlines();\n\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"for\",\n variable,\n items,\n body,\n };\n }\n\n // while := 'while' compound_list 'do' compound_list 'done'\n private parseWhile(): WhileNode {\n this.expectKeyword(\"while\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"while\",\n condition,\n body,\n };\n }\n\n // until := 'until' compound_list 'do' compound_list 'done'\n private parseUntil(): UntilNode {\n this.expectKeyword(\"until\");\n const condition = this.parseCompoundList([\"do\"]);\n this.expectKeyword(\"do\");\n const body = this.parseCompoundList([\"done\"]);\n this.expectKeyword(\"done\");\n\n return {\n type: \"until\",\n condition,\n body,\n };\n }\n\n // case := 'case' word 'in' case_clause* 'esac'\n private parseCase(): CaseNode {\n this.expectKeyword(\"case\");\n const word = this.parseWordArg();\n this.expectKeyword(\"in\");\n this.skipNewlines();\n\n const clauses: CaseClause[] = [];\n\n while (!this.isAtEnd() && !this.checkKeyword(\"esac\")) {\n this.match(\"openParen\");\n\n const patterns: WordNode[] = [];\n patterns.push(this.parseCasePattern());\n\n while (this.match(\"pipe\")) {\n patterns.push(this.parseCasePattern());\n }\n\n if (!this.match(\"closeParen\")) {\n throw new ParseError(\"Expected ')' after case pattern\");\n }\n\n const body = this.parseCaseBody();\n clauses.push({ patterns, body });\n\n this.match(\"doubleSemicolon\");\n this.skipNewlines();\n }\n\n this.expectKeyword(\"esac\");\n\n return {\n type: \"case\",\n word,\n clauses,\n };\n }\n\n private parseCasePattern(): WordNode {\n const token = this.peek();\n\n if (token.type === \"word\" || token.type === \"glob\" || token.type === \"singleQuote\" || token.type === \"doubleQuote\") {\n return this.parseWordArg();\n }\n\n throw new ParseError(`Expected pattern in case clause, got ${token.type}`);\n }\n\n private parseCaseBody(): ASTNode {\n const commands: ASTNode[] = [];\n this.skipNewlines();\n\n while (!this.isAtEnd() && !this.check(\"doubleSemicolon\") && !this.checkKeyword(\"esac\")) {\n commands.push(this.parseAndOr());\n if (!this.match(\"semicolon\") && !this.match(\"newline\")) {\n break;\n }\n this.skipNewlines();\n if (this.check(\"doubleSemicolon\") || this.checkKeyword(\"esac\")) {\n break;\n }\n }\n\n if (commands.length === 0) {\n return this.createNoopCommand();\n }\n if (commands.length === 1) {\n return commands[0]!;\n }\n return { type: \"sequence\", commands };\n }\n\n // compound_list := and_or ((';'|'\\n') and_or)* [';'|'\\n']\n private parseCompoundList(terminators: KeywordValue[]): ASTNode {\n this.skipNewlines();\n const commands: ASTNode[] = [];\n\n if (this.isCompoundListTerminator(terminators)) {\n return this.createNoopCommand();\n }\n\n commands.push(this.parseAndOr());\n\n while ((this.match(\"semicolon\") || this.match(\"newline\")) && !this.isAtEnd()) {\n this.skipNewlines();\n if (this.isCompoundListTerminator(terminators)) {\n break;\n }\n commands.push(this.parseAndOr());\n }\n\n if (commands.length === 1) {\n return commands[0]!;\n }\n\n return { type: \"sequence\", commands };\n }\n\n private createNoopCommand(): CommandNode {\n return {\n type: \"command\",\n name: this.createTextWord(\"true\"),\n args: [],\n redirects: [],\n assignments: [],\n };\n }\n\n private createTextWord(value: string, quoted = false): WordNode {\n return {\n type: \"word\",\n parts: value === \"\" && !quoted ? [] : [{ type: \"text\", value, quoted }],\n };\n }\n\n private isCompoundListTerminator(terminators: KeywordValue[]): boolean {\n const token = this.peek();\n if (token.type !== \"keyword\") return false;\n return terminators.includes(token.value);\n }\n\n private checkKeyword(value: KeywordValue): boolean {\n const token = this.peek();\n return token.type === \"keyword\" && token.value === value;\n }\n\n private expectKeyword(value: KeywordValue): void {\n if (!this.checkKeyword(value)) {\n throw new ParseError(`Expected '${value}'`);\n }\n this.advance();\n }\n\n // command := assignment* word+ redirect*\n private parseCommand(): CommandNode {\n const assignments: Array<{ name: string; value: WordNode }> = [];\n const args: WordNode[] = [];\n const redirects: Redirect[] = [];\n\n while (this.check(\"assignment\")) {\n const token = this.advance() as Token & { type: \"assignment\" };\n assignments.push({\n name: token.name,\n value: this.tokenToWord(token.value),\n });\n }\n\n while (this.isWordToken()) {\n if (this.peek().type === \"heredoc\") {\n const heredocToken = this.advance() as Token & { type: \"heredoc\" };\n redirects.push({\n mode: \"<\",\n target: this.tokenToWord(heredocToken),\n heredocContent: true,\n });\n } else {\n args.push(this.parseWordArg());\n }\n }\n\n while (this.check(\"redirect\")) {\n const redirect = this.parseRedirect();\n redirects.push(redirect);\n while (this.isWordToken()) {\n if (this.peek().type === \"heredoc\") {\n const heredocToken = this.advance() as Token & { type: \"heredoc\" };\n redirects.push({\n mode: \"<\",\n target: this.tokenToWord(heredocToken),\n heredocContent: true,\n });\n } else {\n args.push(this.parseWordArg());\n }\n }\n }\n\n if (args.length === 0 && assignments.length === 0 && redirects.length === 0) {\n throw new ParseError(\"Expected command\");\n }\n\n const name = args.shift() ?? this.createTextWord(redirects.length > 0 ? \":\" : \"\");\n\n return {\n type: \"command\",\n name,\n args,\n redirects,\n assignments,\n };\n }\n\n private parseWordArg(): WordNode {\n const token = this.advance();\n return this.tokenToWord(token);\n }\n\n private tokenToWord(token: Token | string | Token[]): WordNode {\n const parts = this.tokenToWordParts(token);\n return {\n type: \"word\",\n parts,\n };\n }\n\n private tokenToWordParts(token: Token | string | Token[], quoted = false): WordPart[] {\n if (typeof token === \"string\") {\n return [{ type: \"text\", value: token, quoted }];\n }\n\n if (Array.isArray(token)) {\n return token.flatMap((part) => this.tokenToWordParts(part, quoted));\n }\n\n switch (token.type) {\n case \"word\":\n return [{ type: \"text\", value: token.value, quoted }];\n case \"singleQuote\":\n return [{ type: \"text\", value: token.value, quoted: true }];\n case \"doubleQuote\":\n return this.parseDoubleQuoteParts(token.parts);\n case \"variable\":\n return [{ type: \"variable\", name: token.name, quoted }];\n case \"substitution\": {\n const innerParser = new Parser(\n new Lexer(token.command, { preserveNewlines: true }).tokenize()\n );\n return [{ type: \"substitution\", command: innerParser.parse(), quoted }];\n }\n case \"arithmetic\":\n return [{ type: \"arithmetic\", expression: token.expression, quoted }];\n case \"glob\":\n return [{ type: \"text\", value: token.pattern, quoted }];\n case \"assignment\":\n return this.tokenToWordParts(token.value, quoted);\n case \"heredoc\":\n return token.expand\n ? this.parseHeredocContent(token.content).parts\n : [{ type: \"text\", value: token.content, quoted: true }];\n default:\n throw new ParseError(`Unexpected token type: ${(token as Token).type}`);\n }\n }\n\n private parseDoubleQuoteParts(parts: Array<string | Token>): WordPart[] {\n if (parts.length === 0) {\n return [{ type: \"text\", value: \"\", quoted: true }];\n }\n\n return parts.flatMap((part) => this.tokenToWordParts(part, true));\n }\n\n private parseHeredocContent(content: string): WordNode {\n const parts: WordPart[] = [];\n let currentText = \"\";\n let i = 0;\n\n const pushText = () => {\n if (currentText.length > 0) {\n parts.push({ type: \"text\", value: currentText, quoted: false });\n currentText = \"\";\n }\n };\n\n while (i < content.length) {\n if (content[i] !== \"$\") {\n currentText += content[i];\n i++;\n continue;\n }\n\n pushText();\n i++;\n\n if (i >= content.length) {\n currentText += \"$\";\n break;\n }\n\n if (content[i] === \"{\") {\n i++;\n let name = \"\";\n while (i < content.length && content[i] !== \"}\") {\n name += content[i];\n i++;\n }\n if (i < content.length && content[i] === \"}\") {\n i++;\n }\n parts.push({ type: \"variable\", name, quoted: false });\n continue;\n }\n\n if (content[i] === \"(\" && content[i + 1] === \"(\") {\n i += 2;\n let depth = 1;\n let expression = \"\";\n while (i < content.length && depth > 0) {\n if (content[i] === \"(\" && content[i + 1] === \"(\") {\n depth++;\n expression += content[i]! + content[i + 1]!;\n i += 2;\n continue;\n }\n if (content[i] === \")\" && content[i + 1] === \")\") {\n depth--;\n if (depth === 0) {\n i += 2;\n break;\n }\n expression += content[i]! + content[i + 1]!;\n i += 2;\n continue;\n }\n expression += content[i]!;\n i++;\n }\n parts.push({ type: \"arithmetic\", expression, quoted: false });\n continue;\n }\n\n if (content[i] === \"(\") {\n i++;\n let depth = 1;\n let command = \"\";\n while (i < content.length && depth > 0) {\n if (content[i] === \"(\") {\n depth++;\n } else if (content[i] === \")\") {\n depth--;\n if (depth === 0) {\n i++;\n break;\n }\n }\n command += content[i]!;\n i++;\n }\n const innerParser = new Parser(\n new Lexer(command, { preserveNewlines: true }).tokenize()\n );\n parts.push({ type: \"substitution\", command: innerParser.parse(), quoted: false });\n continue;\n }\n\n if (/[a-zA-Z_]/.test(content[i] ?? \"\")) {\n let name = \"\";\n while (i < content.length && /[a-zA-Z0-9_]/.test(content[i] ?? \"\")) {\n name += content[i];\n i++;\n }\n parts.push({ type: \"variable\", name, quoted: false });\n continue;\n }\n\n currentText += \"$\";\n }\n\n pushText();\n\n return {\n type: \"word\",\n parts,\n };\n }\n\n private parseRedirect(): Redirect {\n const token = this.advance() as Token & { type: \"redirect\" };\n const mode = token.mode as RedirectMode;\n\n if (mode === \"2>&1\" || mode === \"1>&2\") {\n return { mode, target: this.createTextWord(\"\") };\n }\n\n if (!this.isWordToken()) {\n throw new ParseError(`Expected redirect target after ${mode}`);\n }\n\n const target = this.parseWordArg();\n return { mode, target };\n }\n\n private isWordToken(): boolean {\n const token = this.peek();\n return (\n Array.isArray(token) ||\n token.type === \"word\" ||\n token.type === \"singleQuote\" ||\n token.type === \"doubleQuote\" ||\n token.type === \"variable\" ||\n token.type === \"substitution\" ||\n token.type === \"arithmetic\" ||\n token.type === \"glob\" ||\n token.type === \"heredoc\"\n );\n }\n\n private check(type: Token[\"type\"]): boolean {\n return this.peek().type === type;\n }\n\n private match(type: Token[\"type\"]): boolean {\n if (this.check(type)) {\n this.advance();\n return true;\n }\n return false;\n }\n\n private peek(): Token {\n return this.tokens[this.pos] ?? { type: \"eof\" };\n }\n\n private advance(): Token {\n const token = this.peek();\n this.pos++;\n return token;\n }\n\n private isAtEnd(): boolean {\n return this.peek().type === \"eof\";\n }\n}\n\nexport function parse(tokens: Token[]): ASTNode {\n return new Parser(tokens).parse();\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "87B78A0C1939D94564756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|