shell-dsl 0.0.1 → 0.0.3

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 (133) hide show
  1. package/README.md +572 -28
  2. package/dist/cjs/index.cjs +72 -0
  3. package/dist/cjs/index.cjs.map +10 -0
  4. package/dist/cjs/package.json +5 -0
  5. package/dist/cjs/src/errors.cjs +73 -0
  6. package/dist/cjs/src/errors.cjs.map +10 -0
  7. package/dist/cjs/src/fs/index.cjs +37 -0
  8. package/dist/cjs/src/fs/index.cjs.map +10 -0
  9. package/dist/cjs/src/fs/memfs-adapter.cjs +221 -0
  10. package/dist/cjs/src/fs/memfs-adapter.cjs.map +10 -0
  11. package/dist/cjs/src/index.cjs +80 -0
  12. package/dist/cjs/src/index.cjs.map +10 -0
  13. package/dist/cjs/src/interpreter/context.cjs +47 -0
  14. package/dist/cjs/src/interpreter/context.cjs.map +10 -0
  15. package/dist/cjs/src/interpreter/index.cjs +39 -0
  16. package/dist/cjs/src/interpreter/index.cjs.map +10 -0
  17. package/dist/cjs/src/interpreter/interpreter.cjs +381 -0
  18. package/dist/cjs/src/interpreter/interpreter.cjs.map +10 -0
  19. package/dist/cjs/src/io/index.cjs +44 -0
  20. package/dist/cjs/src/io/index.cjs.map +10 -0
  21. package/dist/cjs/src/io/stdin.cjs +99 -0
  22. package/dist/cjs/src/io/stdin.cjs.map +10 -0
  23. package/dist/cjs/src/io/stdout.cjs +203 -0
  24. package/dist/cjs/src/io/stdout.cjs.map +10 -0
  25. package/dist/cjs/src/lexer/index.cjs +40 -0
  26. package/dist/cjs/src/lexer/index.cjs.map +10 -0
  27. package/dist/cjs/src/lexer/lexer.cjs +335 -0
  28. package/dist/cjs/src/lexer/lexer.cjs.map +10 -0
  29. package/dist/cjs/src/lexer/tokens.cjs +66 -0
  30. package/dist/cjs/src/lexer/tokens.cjs.map +10 -0
  31. package/dist/cjs/src/parser/ast.cjs +75 -0
  32. package/dist/cjs/src/parser/ast.cjs.map +10 -0
  33. package/dist/cjs/src/parser/index.cjs +49 -0
  34. package/dist/cjs/src/parser/index.cjs.map +10 -0
  35. package/dist/cjs/src/parser/parser.cjs +216 -0
  36. package/dist/cjs/src/parser/parser.cjs.map +10 -0
  37. package/dist/cjs/src/shell-dsl.cjs +187 -0
  38. package/dist/cjs/src/shell-dsl.cjs.map +10 -0
  39. package/dist/cjs/src/shell-promise.cjs +159 -0
  40. package/dist/cjs/src/shell-promise.cjs.map +10 -0
  41. package/dist/cjs/src/types.cjs +43 -0
  42. package/dist/cjs/src/types.cjs.map +10 -0
  43. package/dist/cjs/src/utils/escape.cjs +53 -0
  44. package/dist/cjs/src/utils/escape.cjs.map +10 -0
  45. package/dist/cjs/src/utils/index.cjs +38 -0
  46. package/dist/cjs/src/utils/index.cjs.map +10 -0
  47. package/dist/mjs/index.mjs +42 -0
  48. package/dist/mjs/index.mjs.map +10 -0
  49. package/dist/mjs/package.json +5 -0
  50. package/dist/mjs/src/errors.mjs +42 -0
  51. package/dist/mjs/src/errors.mjs.map +10 -0
  52. package/dist/mjs/src/fs/index.mjs +7 -0
  53. package/dist/mjs/src/fs/index.mjs.map +10 -0
  54. package/dist/mjs/src/fs/memfs-adapter.mjs +178 -0
  55. package/dist/mjs/src/fs/memfs-adapter.mjs.map +10 -0
  56. package/dist/mjs/src/index.mjs +61 -0
  57. package/dist/mjs/src/index.mjs.map +10 -0
  58. package/dist/mjs/src/interpreter/context.mjs +17 -0
  59. package/dist/mjs/src/interpreter/context.mjs.map +10 -0
  60. package/dist/mjs/src/interpreter/index.mjs +9 -0
  61. package/dist/mjs/src/interpreter/index.mjs.map +10 -0
  62. package/dist/mjs/src/interpreter/interpreter.mjs +351 -0
  63. package/dist/mjs/src/interpreter/interpreter.mjs.map +10 -0
  64. package/dist/mjs/src/io/index.mjs +14 -0
  65. package/dist/mjs/src/io/index.mjs.map +10 -0
  66. package/dist/mjs/src/io/stdin.mjs +68 -0
  67. package/dist/mjs/src/io/stdin.mjs.map +10 -0
  68. package/dist/mjs/src/io/stdout.mjs +172 -0
  69. package/dist/mjs/src/io/stdout.mjs.map +10 -0
  70. package/dist/mjs/src/lexer/index.mjs +10 -0
  71. package/dist/mjs/src/lexer/index.mjs.map +10 -0
  72. package/dist/mjs/src/lexer/lexer.mjs +305 -0
  73. package/dist/mjs/src/lexer/lexer.mjs.map +10 -0
  74. package/dist/mjs/src/lexer/tokens.mjs +36 -0
  75. package/dist/mjs/src/lexer/tokens.mjs.map +10 -0
  76. package/dist/mjs/src/parser/ast.mjs +45 -0
  77. package/dist/mjs/src/parser/ast.mjs.map +10 -0
  78. package/dist/mjs/src/parser/index.mjs +30 -0
  79. package/dist/mjs/src/parser/index.mjs.map +10 -0
  80. package/dist/mjs/src/parser/parser.mjs +189 -0
  81. package/dist/mjs/src/parser/parser.mjs.map +10 -0
  82. package/dist/mjs/src/shell-dsl.mjs +157 -0
  83. package/dist/mjs/src/shell-dsl.mjs.map +10 -0
  84. package/dist/mjs/src/shell-promise.mjs +129 -0
  85. package/dist/mjs/src/shell-promise.mjs.map +10 -0
  86. package/dist/mjs/src/types.mjs +13 -0
  87. package/dist/mjs/src/types.mjs.map +10 -0
  88. package/dist/mjs/src/utils/escape.mjs +23 -0
  89. package/dist/mjs/src/utils/escape.mjs.map +10 -0
  90. package/dist/mjs/src/utils/index.mjs +8 -0
  91. package/dist/mjs/src/utils/index.mjs.map +10 -0
  92. package/dist/types/commands/cat.d.ts +2 -0
  93. package/dist/types/commands/cp.d.ts +2 -0
  94. package/dist/types/commands/echo.d.ts +2 -0
  95. package/dist/types/commands/grep.d.ts +2 -0
  96. package/dist/types/commands/head.d.ts +2 -0
  97. package/dist/types/commands/index.d.ts +20 -0
  98. package/dist/types/commands/ls.d.ts +2 -0
  99. package/dist/types/commands/mkdir.d.ts +2 -0
  100. package/dist/types/commands/mv.d.ts +2 -0
  101. package/dist/types/commands/pwd.d.ts +2 -0
  102. package/dist/types/commands/rm.d.ts +2 -0
  103. package/dist/types/commands/sort.d.ts +2 -0
  104. package/dist/types/commands/tail.d.ts +2 -0
  105. package/dist/types/commands/tee.d.ts +2 -0
  106. package/dist/types/commands/test.d.ts +3 -0
  107. package/dist/types/commands/touch.d.ts +2 -0
  108. package/dist/types/commands/true-false.d.ts +3 -0
  109. package/dist/types/commands/uniq.d.ts +2 -0
  110. package/dist/types/commands/wc.d.ts +2 -0
  111. package/dist/types/index.d.ts +3 -0
  112. package/dist/types/src/errors.d.ts +16 -0
  113. package/dist/types/src/fs/index.d.ts +1 -0
  114. package/dist/types/src/fs/memfs-adapter.d.ts +3 -0
  115. package/dist/types/src/index.d.ts +15 -0
  116. package/dist/types/src/interpreter/context.d.ts +11 -0
  117. package/dist/types/src/interpreter/index.d.ts +2 -0
  118. package/dist/types/src/interpreter/interpreter.d.ts +32 -0
  119. package/dist/types/src/io/index.d.ts +2 -0
  120. package/dist/types/src/io/stdin.d.ts +11 -0
  121. package/dist/types/src/io/stdout.d.ts +40 -0
  122. package/dist/types/src/lexer/index.d.ts +3 -0
  123. package/dist/types/src/lexer/lexer.d.ts +24 -0
  124. package/dist/types/src/lexer/tokens.d.ts +38 -0
  125. package/dist/types/src/parser/ast.d.ts +64 -0
  126. package/dist/types/src/parser/index.d.ts +3 -0
  127. package/dist/types/src/parser/parser.d.ts +23 -0
  128. package/dist/types/src/shell-dsl.d.ts +32 -0
  129. package/dist/types/src/shell-promise.d.ts +39 -0
  130. package/dist/types/src/types.d.ts +76 -0
  131. package/dist/types/src/utils/escape.d.ts +2 -0
  132. package/dist/types/src/utils/index.d.ts +1 -0
  133. package/package.json +46 -6
@@ -0,0 +1,305 @@
1
+ // src/lexer/lexer.ts
2
+ import { LexError } from "../errors.mjs";
3
+ var GLOB_CHARS = new Set(["*", "?", "[", "{", "}"]);
4
+ var WORD_BREAK_CHARS = new Set([
5
+ " ",
6
+ "\t",
7
+ `
8
+ `,
9
+ "\r",
10
+ "|",
11
+ "&",
12
+ ";",
13
+ ">",
14
+ "<",
15
+ "(",
16
+ ")",
17
+ "$",
18
+ "'",
19
+ '"',
20
+ "`"
21
+ ]);
22
+
23
+ class Lexer {
24
+ source;
25
+ pos = 0;
26
+ line = 1;
27
+ column = 1;
28
+ constructor(source) {
29
+ this.source = source;
30
+ }
31
+ tokenize() {
32
+ const tokens = [];
33
+ while (!this.isAtEnd()) {
34
+ this.skipWhitespace();
35
+ if (this.isAtEnd())
36
+ break;
37
+ const token = this.nextToken();
38
+ if (token) {
39
+ tokens.push(token);
40
+ }
41
+ }
42
+ tokens.push({ type: "eof" });
43
+ return tokens;
44
+ }
45
+ nextToken() {
46
+ const char = this.peek();
47
+ if (char === "#") {
48
+ this.skipComment();
49
+ return null;
50
+ }
51
+ if (char === "|") {
52
+ this.advance();
53
+ if (this.peek() === "|") {
54
+ this.advance();
55
+ return { type: "or" };
56
+ }
57
+ return { type: "pipe" };
58
+ }
59
+ if (char === "&") {
60
+ this.advance();
61
+ if (this.peek() === "&") {
62
+ this.advance();
63
+ return { type: "and" };
64
+ }
65
+ if (this.peek() === ">") {
66
+ this.advance();
67
+ if (this.peek() === ">") {
68
+ this.advance();
69
+ return { type: "redirect", mode: "&>>" };
70
+ }
71
+ return { type: "redirect", mode: "&>" };
72
+ }
73
+ return { type: "word", value: "&" };
74
+ }
75
+ if (char === ";") {
76
+ this.advance();
77
+ return { type: "semicolon" };
78
+ }
79
+ if (char === ">") {
80
+ this.advance();
81
+ if (this.peek() === ">") {
82
+ this.advance();
83
+ return { type: "redirect", mode: ">>" };
84
+ }
85
+ return { type: "redirect", mode: ">" };
86
+ }
87
+ if (char === "<") {
88
+ this.advance();
89
+ return { type: "redirect", mode: "<" };
90
+ }
91
+ if (char === "1" || char === "2") {
92
+ const fd = char;
93
+ const nextChar = this.peekAhead(1);
94
+ if (nextChar === ">") {
95
+ this.advance();
96
+ this.advance();
97
+ if (fd === "2") {
98
+ if (this.peek() === "&" && this.peekAhead(1) === "1") {
99
+ this.advance();
100
+ this.advance();
101
+ return { type: "redirect", mode: "2>&1" };
102
+ }
103
+ if (this.peek() === ">") {
104
+ this.advance();
105
+ return { type: "redirect", mode: "2>>" };
106
+ }
107
+ return { type: "redirect", mode: "2>" };
108
+ } else {
109
+ if (this.peek() === "&" && this.peekAhead(1) === "2") {
110
+ this.advance();
111
+ this.advance();
112
+ return { type: "redirect", mode: "1>&2" };
113
+ }
114
+ if (this.peek() === ">") {
115
+ this.advance();
116
+ return { type: "redirect", mode: ">>" };
117
+ }
118
+ return { type: "redirect", mode: ">" };
119
+ }
120
+ }
121
+ }
122
+ if (char === "$") {
123
+ return this.readVariable();
124
+ }
125
+ if (char === "'") {
126
+ return this.readSingleQuote();
127
+ }
128
+ if (char === '"') {
129
+ return this.readDoubleQuote();
130
+ }
131
+ return this.readWord();
132
+ }
133
+ readVariable() {
134
+ this.advance();
135
+ if (this.peek() === "(") {
136
+ this.advance();
137
+ const command = this.readUntilMatchingParen();
138
+ return { type: "substitution", command };
139
+ }
140
+ if (this.peek() === "{") {
141
+ this.advance();
142
+ let name2 = "";
143
+ while (!this.isAtEnd() && this.peek() !== "}") {
144
+ name2 += this.advance();
145
+ }
146
+ if (this.peek() === "}") {
147
+ this.advance();
148
+ }
149
+ return { type: "variable", name: name2 };
150
+ }
151
+ let name = "";
152
+ while (!this.isAtEnd() && this.isVarChar(this.peek())) {
153
+ name += this.advance();
154
+ }
155
+ if (name === "") {
156
+ return { type: "word", value: "$" };
157
+ }
158
+ return { type: "variable", name };
159
+ }
160
+ readUntilMatchingParen() {
161
+ let depth = 1;
162
+ let result = "";
163
+ while (!this.isAtEnd() && depth > 0) {
164
+ const char = this.peek();
165
+ if (char === "(") {
166
+ depth++;
167
+ } else if (char === ")") {
168
+ depth--;
169
+ if (depth === 0) {
170
+ this.advance();
171
+ break;
172
+ }
173
+ }
174
+ result += this.advance();
175
+ }
176
+ return result;
177
+ }
178
+ readSingleQuote() {
179
+ this.advance();
180
+ let value = "";
181
+ while (!this.isAtEnd() && this.peek() !== "'") {
182
+ value += this.advance();
183
+ }
184
+ if (this.peek() === "'") {
185
+ this.advance();
186
+ } else {
187
+ throw new LexError("Unterminated single quote", this.pos, this.line, this.column);
188
+ }
189
+ return { type: "singleQuote", value };
190
+ }
191
+ readDoubleQuote() {
192
+ this.advance();
193
+ const parts = [];
194
+ let currentString = "";
195
+ while (!this.isAtEnd() && this.peek() !== '"') {
196
+ const char = this.peek();
197
+ if (char === "\\") {
198
+ this.advance();
199
+ if (!this.isAtEnd()) {
200
+ const escaped = this.advance();
201
+ if (["$", '"', "\\", "`", `
202
+ `].includes(escaped)) {
203
+ currentString += escaped;
204
+ } else {
205
+ currentString += "\\" + escaped;
206
+ }
207
+ }
208
+ } else if (char === "$") {
209
+ if (currentString) {
210
+ parts.push(currentString);
211
+ currentString = "";
212
+ }
213
+ parts.push(this.readVariable());
214
+ } else {
215
+ currentString += this.advance();
216
+ }
217
+ }
218
+ if (currentString) {
219
+ parts.push(currentString);
220
+ }
221
+ if (this.peek() === '"') {
222
+ this.advance();
223
+ } else {
224
+ throw new LexError("Unterminated double quote", this.pos, this.line, this.column);
225
+ }
226
+ return { type: "doubleQuote", parts };
227
+ }
228
+ readWord() {
229
+ let value = "";
230
+ let hasGlobChars = false;
231
+ while (!this.isAtEnd() && !this.isWordBreak(this.peek())) {
232
+ const char = this.peek();
233
+ if (char === "\\") {
234
+ this.advance();
235
+ if (!this.isAtEnd()) {
236
+ value += this.advance();
237
+ }
238
+ } else {
239
+ if (GLOB_CHARS.has(char)) {
240
+ hasGlobChars = true;
241
+ }
242
+ value += this.advance();
243
+ }
244
+ }
245
+ const assignmentMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/);
246
+ if (assignmentMatch) {
247
+ return {
248
+ type: "assignment",
249
+ name: assignmentMatch[1],
250
+ value: assignmentMatch[2]
251
+ };
252
+ }
253
+ if (hasGlobChars) {
254
+ return { type: "glob", pattern: value };
255
+ }
256
+ return { type: "word", value };
257
+ }
258
+ isWordBreak(char) {
259
+ return WORD_BREAK_CHARS.has(char);
260
+ }
261
+ isVarChar(char) {
262
+ return /[a-zA-Z0-9_]/.test(char);
263
+ }
264
+ skipWhitespace() {
265
+ while (!this.isAtEnd() && /\s/.test(this.peek())) {
266
+ this.advance();
267
+ }
268
+ }
269
+ skipComment() {
270
+ while (!this.isAtEnd() && this.peek() !== `
271
+ `) {
272
+ this.advance();
273
+ }
274
+ }
275
+ peek() {
276
+ return this.source[this.pos] ?? "";
277
+ }
278
+ peekAhead(n) {
279
+ return this.source[this.pos + n] ?? "";
280
+ }
281
+ advance() {
282
+ const char = this.source[this.pos];
283
+ this.pos++;
284
+ if (char === `
285
+ `) {
286
+ this.line++;
287
+ this.column = 1;
288
+ } else {
289
+ this.column++;
290
+ }
291
+ return char;
292
+ }
293
+ isAtEnd() {
294
+ return this.pos >= this.source.length;
295
+ }
296
+ }
297
+ function lex(source) {
298
+ return new Lexer(source).tokenize();
299
+ }
300
+ export {
301
+ lex,
302
+ Lexer
303
+ };
304
+
305
+ //# debugId=819722A2CE193AAF64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/lexer/lexer.ts"],
4
+ "sourcesContent": [
5
+ "import { LexError } from \"../errors.mjs\";\nimport type { Token, RedirectMode } from \"./tokens.mjs\";\n\nconst GLOB_CHARS = new Set([\"*\", \"?\", \"[\", \"{\", \"}\"]);\nconst WORD_BREAK_CHARS = new Set([\n \" \",\n \"\\t\",\n \"\\n\",\n \"\\r\",\n \"|\",\n \"&\",\n \";\",\n \">\",\n \"<\",\n \"(\",\n \")\",\n \"$\",\n \"'\",\n '\"',\n \"`\",\n]);\n\nexport class Lexer {\n private source: string;\n private pos: number = 0;\n private line: number = 1;\n private column: number = 1;\n\n constructor(source: string) {\n this.source = source;\n }\n\n tokenize(): Token[] {\n const tokens: Token[] = [];\n\n while (!this.isAtEnd()) {\n this.skipWhitespace();\n if (this.isAtEnd()) break;\n\n const token = this.nextToken();\n if (token) {\n tokens.push(token);\n }\n }\n\n tokens.push({ type: \"eof\" });\n return tokens;\n }\n\n private nextToken(): Token | null {\n const char = this.peek();\n\n // Comments\n if (char === \"#\") {\n this.skipComment();\n return null;\n }\n\n // Operators and redirects\n if (char === \"|\") {\n this.advance();\n if (this.peek() === \"|\") {\n this.advance();\n return { type: \"or\" };\n }\n return { type: \"pipe\" };\n }\n\n if (char === \"&\") {\n this.advance();\n if (this.peek() === \"&\") {\n this.advance();\n return { type: \"and\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \"&>>\" };\n }\n return { type: \"redirect\", mode: \"&>\" };\n }\n // Background execution (&) - treat as word for now\n return { type: \"word\", value: \"&\" };\n }\n\n if (char === \";\") {\n this.advance();\n return { type: \"semicolon\" };\n }\n\n // Redirects\n if (char === \">\") {\n this.advance();\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \">>\" };\n }\n return { type: \"redirect\", mode: \">\" };\n }\n\n if (char === \"<\") {\n this.advance();\n return { type: \"redirect\", mode: \"<\" };\n }\n\n // File descriptor redirects (2>, 2>>, 2>&1, 1>&2)\n if (char === \"1\" || char === \"2\") {\n const fd = char;\n const nextChar = this.peekAhead(1);\n if (nextChar === \">\") {\n this.advance(); // consume fd\n this.advance(); // consume >\n if (fd === \"2\") {\n if (this.peek() === \"&\" && this.peekAhead(1) === \"1\") {\n this.advance(); // consume &\n this.advance(); // consume 1\n return { type: \"redirect\", mode: \"2>&1\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \"2>>\" };\n }\n return { type: \"redirect\", mode: \"2>\" };\n } else {\n // 1>&2\n if (this.peek() === \"&\" && this.peekAhead(1) === \"2\") {\n this.advance(); // consume &\n this.advance(); // consume 2\n return { type: \"redirect\", mode: \"1>&2\" };\n }\n if (this.peek() === \">\") {\n this.advance();\n return { type: \"redirect\", mode: \">>\" };\n }\n return { type: \"redirect\", mode: \">\" };\n }\n }\n }\n\n // Variables and substitutions\n if (char === \"$\") {\n return this.readVariable();\n }\n\n // Single quotes\n if (char === \"'\") {\n return this.readSingleQuote();\n }\n\n // Double quotes\n if (char === '\"') {\n return this.readDoubleQuote();\n }\n\n // Word (including potential globs and assignments)\n return this.readWord();\n }\n\n private readVariable(): Token {\n this.advance(); // consume $\n\n // Command substitution $(...)\n if (this.peek() === \"(\") {\n this.advance(); // consume (\n const command = this.readUntilMatchingParen();\n return { type: \"substitution\", command };\n }\n\n // ${VAR} syntax\n if (this.peek() === \"{\") {\n this.advance(); // consume {\n let name = \"\";\n while (!this.isAtEnd() && this.peek() !== \"}\") {\n name += this.advance();\n }\n if (this.peek() === \"}\") {\n this.advance(); // consume }\n }\n return { type: \"variable\", name };\n }\n\n // $VAR syntax\n let name = \"\";\n while (!this.isAtEnd() && this.isVarChar(this.peek())) {\n name += this.advance();\n }\n\n if (name === \"\") {\n return { type: \"word\", value: \"$\" };\n }\n\n return { type: \"variable\", name };\n }\n\n private readUntilMatchingParen(): string {\n let depth = 1;\n let result = \"\";\n\n while (!this.isAtEnd() && depth > 0) {\n const char = this.peek();\n if (char === \"(\") {\n depth++;\n } else if (char === \")\") {\n depth--;\n if (depth === 0) {\n this.advance(); // consume closing )\n break;\n }\n }\n result += this.advance();\n }\n\n return result;\n }\n\n private readSingleQuote(): Token {\n this.advance(); // consume opening '\n let value = \"\";\n\n while (!this.isAtEnd() && this.peek() !== \"'\") {\n value += this.advance();\n }\n\n if (this.peek() === \"'\") {\n this.advance(); // consume closing '\n } else {\n throw new LexError(\"Unterminated single quote\", this.pos, this.line, this.column);\n }\n\n return { type: \"singleQuote\", value };\n }\n\n private readDoubleQuote(): Token {\n this.advance(); // consume opening \"\n const parts: Array<string | Token> = [];\n let currentString = \"\";\n\n while (!this.isAtEnd() && this.peek() !== '\"') {\n const char = this.peek();\n\n if (char === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n const escaped = this.advance();\n // In double quotes, only certain chars are special\n if ([\"$\", '\"', \"\\\\\", \"`\", \"\\n\"].includes(escaped)) {\n currentString += escaped;\n } else {\n currentString += \"\\\\\" + escaped;\n }\n }\n } else if (char === \"$\") {\n if (currentString) {\n parts.push(currentString);\n currentString = \"\";\n }\n parts.push(this.readVariable());\n } else {\n currentString += this.advance();\n }\n }\n\n if (currentString) {\n parts.push(currentString);\n }\n\n if (this.peek() === '\"') {\n this.advance(); // consume closing \"\n } else {\n throw new LexError(\"Unterminated double quote\", this.pos, this.line, this.column);\n }\n\n return { type: \"doubleQuote\", parts };\n }\n\n private readWord(): Token {\n let value = \"\";\n let hasGlobChars = false;\n\n while (!this.isAtEnd() && !this.isWordBreak(this.peek())) {\n const char = this.peek();\n\n if (char === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n value += this.advance();\n }\n } else {\n if (GLOB_CHARS.has(char)) {\n hasGlobChars = true;\n }\n value += this.advance();\n }\n }\n\n // Check if this is an assignment (VAR=value)\n const assignmentMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/);\n if (assignmentMatch) {\n return {\n type: \"assignment\",\n name: assignmentMatch[1]!,\n value: assignmentMatch[2]!,\n };\n }\n\n if (hasGlobChars) {\n return { type: \"glob\", pattern: value };\n }\n\n return { type: \"word\", value };\n }\n\n private isWordBreak(char: string): boolean {\n return WORD_BREAK_CHARS.has(char);\n }\n\n private isVarChar(char: string): boolean {\n return /[a-zA-Z0-9_]/.test(char);\n }\n\n private skipWhitespace(): void {\n while (!this.isAtEnd() && /\\s/.test(this.peek())) {\n this.advance();\n }\n }\n\n private skipComment(): void {\n while (!this.isAtEnd() && this.peek() !== \"\\n\") {\n this.advance();\n }\n }\n\n private peek(): string {\n return this.source[this.pos] ?? \"\";\n }\n\n private peekAhead(n: number): string {\n return this.source[this.pos + n] ?? \"\";\n }\n\n private advance(): string {\n const char = this.source[this.pos]!;\n this.pos++;\n if (char === \"\\n\") {\n this.line++;\n this.column = 1;\n } else {\n this.column++;\n }\n return char;\n }\n\n private isAtEnd(): boolean {\n return this.pos >= this.source.length;\n }\n}\n\nexport function lex(source: string): Token[] {\n return new Lexer(source).tokenize();\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "819722A2CE193AAF64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,36 @@
1
+ // src/lexer/tokens.ts
2
+ function tokenToString(token) {
3
+ switch (token.type) {
4
+ case "word":
5
+ return token.value;
6
+ case "pipe":
7
+ return "|";
8
+ case "and":
9
+ return "&&";
10
+ case "or":
11
+ return "||";
12
+ case "semicolon":
13
+ return ";";
14
+ case "redirect":
15
+ return token.mode;
16
+ case "variable":
17
+ return `$${token.name}`;
18
+ case "substitution":
19
+ return `$(${token.command})`;
20
+ case "glob":
21
+ return token.pattern;
22
+ case "singleQuote":
23
+ return `'${token.value}'`;
24
+ case "doubleQuote":
25
+ return `"${token.parts.map((p) => typeof p === "string" ? p : tokenToString(p)).join("")}"`;
26
+ case "assignment":
27
+ return `${token.name}=${typeof token.value === "string" ? token.value : token.value.map(tokenToString).join("")}`;
28
+ case "eof":
29
+ return "<EOF>";
30
+ }
31
+ }
32
+ export {
33
+ tokenToString
34
+ };
35
+
36
+ //# debugId=D103DC901FB8A54E64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/lexer/tokens.ts"],
4
+ "sourcesContent": [
5
+ "export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport type Token =\n | { type: \"word\"; value: string }\n | { type: \"pipe\" }\n | { type: \"and\" }\n | { type: \"or\" }\n | { type: \"semicolon\" }\n | { type: \"redirect\"; mode: RedirectMode }\n | { type: \"variable\"; name: string }\n | { type: \"substitution\"; command: string }\n | { type: \"glob\"; pattern: string }\n | { type: \"singleQuote\"; value: string }\n | { type: \"doubleQuote\"; parts: Array<string | Token> }\n | { type: \"assignment\"; name: string; value: string | Token[] }\n | { type: \"eof\" };\n\nexport function tokenToString(token: Token): string {\n switch (token.type) {\n case \"word\":\n return token.value;\n case \"pipe\":\n return \"|\";\n case \"and\":\n return \"&&\";\n case \"or\":\n return \"||\";\n case \"semicolon\":\n return \";\";\n case \"redirect\":\n return token.mode;\n case \"variable\":\n return `$${token.name}`;\n case \"substitution\":\n return `$(${token.command})`;\n case \"glob\":\n return token.pattern;\n case \"singleQuote\":\n return `'${token.value}'`;\n case \"doubleQuote\":\n return `\"${token.parts.map((p) => (typeof p === \"string\" ? p : tokenToString(p))).join(\"\")}\"`;\n case \"assignment\":\n return `${token.name}=${typeof token.value === \"string\" ? token.value : token.value.map(tokenToString).join(\"\")}`;\n case \"eof\":\n return \"<EOF>\";\n }\n}\n"
6
+ ],
7
+ "mappings": ";AA0BO,SAAS,aAAa,CAAC,OAAsB;AAAA,EAClD,QAAQ,MAAM;AAAA,SACP;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO,IAAI,MAAM;AAAA,SACd;AAAA,MACH,OAAO,KAAK,MAAM;AAAA,SACf;AAAA,MACH,OAAO,MAAM;AAAA,SACV;AAAA,MACH,OAAO,IAAI,MAAM;AAAA,SACd;AAAA,MACH,OAAO,IAAI,MAAM,MAAM,IAAI,CAAC,MAAO,OAAO,MAAM,WAAW,IAAI,cAAc,CAAC,CAAE,EAAE,KAAK,EAAE;AAAA,SACtF;AAAA,MACH,OAAO,GAAG,MAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ,MAAM,MAAM,IAAI,aAAa,EAAE,KAAK,EAAE;AAAA,SAC3G;AAAA,MACH,OAAO;AAAA;AAAA;",
8
+ "debugId": "D103DC901FB8A54E64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,45 @@
1
+ // src/parser/ast.ts
2
+ function isCommandNode(node) {
3
+ return node.type === "command";
4
+ }
5
+ function isPipelineNode(node) {
6
+ return node.type === "pipeline";
7
+ }
8
+ function isAndNode(node) {
9
+ return node.type === "and";
10
+ }
11
+ function isOrNode(node) {
12
+ return node.type === "or";
13
+ }
14
+ function isSequenceNode(node) {
15
+ return node.type === "sequence";
16
+ }
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
+ export {
33
+ isVariableNode,
34
+ isSubstitutionNode,
35
+ isSequenceNode,
36
+ isPipelineNode,
37
+ isOrNode,
38
+ isLiteralNode,
39
+ isGlobNode,
40
+ isConcatNode,
41
+ isCommandNode,
42
+ isAndNode
43
+ };
44
+
45
+ //# debugId=A4A8963D49D6651C64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/parser/ast.ts"],
4
+ "sourcesContent": [
5
+ "export type RedirectMode =\n | \">\"\n | \">>\"\n | \"<\"\n | \"2>\"\n | \"2>>\"\n | \"&>\"\n | \"&>>\"\n | \"2>&1\"\n | \"1>&2\";\n\nexport interface Redirect {\n mode: RedirectMode;\n target: ASTNode;\n}\n\nexport type ASTNode =\n | CommandNode\n | PipelineNode\n | AndNode\n | OrNode\n | SequenceNode\n | LiteralNode\n | VariableNode\n | SubstitutionNode\n | GlobNode\n | ConcatNode;\n\nexport interface CommandNode {\n type: \"command\";\n name: ASTNode;\n args: ASTNode[];\n redirects: Redirect[];\n assignments: Array<{ name: string; value: ASTNode }>;\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 LiteralNode {\n type: \"literal\";\n value: string;\n}\n\nexport interface VariableNode {\n type: \"variable\";\n name: string;\n}\n\nexport interface SubstitutionNode {\n type: \"substitution\";\n command: ASTNode;\n}\n\nexport interface GlobNode {\n type: \"glob\";\n pattern: string;\n}\n\nexport interface ConcatNode {\n type: \"concat\";\n parts: ASTNode[];\n}\n\n// Type guards\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 isLiteralNode(node: ASTNode): node is LiteralNode {\n return node.type === \"literal\";\n}\n\nexport function isVariableNode(node: ASTNode): node is VariableNode {\n return node.type === \"variable\";\n}\n\nexport function isSubstitutionNode(node: ASTNode): node is SubstitutionNode {\n return node.type === \"substitution\";\n}\n\nexport function isGlobNode(node: ASTNode): node is GlobNode {\n return node.type === \"glob\";\n}\n\nexport function isConcatNode(node: ASTNode): node is ConcatNode {\n return node.type === \"concat\";\n}\n"
6
+ ],
7
+ "mappings": ";AAoFO,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,aAAa,CAAC,MAAoC;AAAA,EAChE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,cAAc,CAAC,MAAqC;AAAA,EAClE,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,kBAAkB,CAAC,MAAyC;AAAA,EAC1E,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,UAAU,CAAC,MAAiC;AAAA,EAC1D,OAAO,KAAK,SAAS;AAAA;AAGhB,SAAS,YAAY,CAAC,MAAmC;AAAA,EAC9D,OAAO,KAAK,SAAS;AAAA;",
8
+ "debugId": "A4A8963D49D6651C64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,30 @@
1
+ // src/parser/index.ts
2
+ import { Parser, parse } from "./parser.mjs";
3
+ import {
4
+ isCommandNode,
5
+ isPipelineNode,
6
+ isAndNode,
7
+ isOrNode,
8
+ isSequenceNode,
9
+ isLiteralNode,
10
+ isVariableNode,
11
+ isSubstitutionNode,
12
+ isGlobNode,
13
+ isConcatNode
14
+ } from "./ast.mjs";
15
+ export {
16
+ parse,
17
+ isVariableNode,
18
+ isSubstitutionNode,
19
+ isSequenceNode,
20
+ isPipelineNode,
21
+ isOrNode,
22
+ isLiteralNode,
23
+ isGlobNode,
24
+ isConcatNode,
25
+ isCommandNode,
26
+ isAndNode,
27
+ Parser
28
+ };
29
+
30
+ //# debugId=FE914D4DC4891D7B64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/parser/index.ts"],
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 LiteralNode,\n VariableNode,\n SubstitutionNode,\n GlobNode,\n ConcatNode,\n} from \"./ast.mjs\";\nexport {\n isCommandNode,\n isPipelineNode,\n isAndNode,\n isOrNode,\n isSequenceNode,\n isLiteralNode,\n isVariableNode,\n isSubstitutionNode,\n isGlobNode,\n isConcatNode,\n} from \"./ast.mjs\";\n"
6
+ ],
7
+ "mappings": ";AAAA;AAgBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;",
8
+ "debugId": "FE914D4DC4891D7B64756E2164756E21",
9
+ "names": []
10
+ }