shell-dsl 0.0.6 → 0.0.8

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 (197) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/index.cjs +14 -4
  3. package/dist/cjs/index.cjs.map +3 -3
  4. package/dist/cjs/package.json +1 -1
  5. package/dist/cjs/src/commands/awk/awk.cjs +276 -0
  6. package/dist/cjs/src/commands/awk/awk.cjs.map +10 -0
  7. package/dist/cjs/src/commands/break-continue/break-continue.cjs +56 -0
  8. package/dist/cjs/src/commands/break-continue/break-continue.cjs.map +10 -0
  9. package/dist/cjs/src/commands/cat/cat.cjs +57 -0
  10. package/dist/cjs/src/commands/cat/cat.cjs.map +10 -0
  11. package/dist/cjs/src/commands/cp/cp.cjs +126 -0
  12. package/dist/cjs/src/commands/cp/cp.cjs.map +10 -0
  13. package/dist/cjs/src/commands/echo/echo.cjs +50 -0
  14. package/dist/cjs/src/commands/echo/echo.cjs.map +10 -0
  15. package/dist/cjs/src/commands/find/find.cjs +251 -0
  16. package/dist/cjs/src/commands/find/find.cjs.map +10 -0
  17. package/dist/cjs/src/commands/grep/grep.cjs +510 -0
  18. package/dist/cjs/src/commands/grep/grep.cjs.map +10 -0
  19. package/dist/cjs/src/commands/head/head.cjs +95 -0
  20. package/dist/cjs/src/commands/head/head.cjs.map +10 -0
  21. package/dist/cjs/src/commands/index.cjs +136 -0
  22. package/dist/cjs/src/commands/index.cjs.map +10 -0
  23. package/dist/cjs/src/commands/ls/ls.cjs +119 -0
  24. package/dist/cjs/src/commands/ls/ls.cjs.map +10 -0
  25. package/dist/cjs/src/commands/mkdir/mkdir.cjs +64 -0
  26. package/dist/cjs/src/commands/mkdir/mkdir.cjs.map +10 -0
  27. package/dist/cjs/src/commands/mv/mv.cjs +118 -0
  28. package/dist/cjs/src/commands/mv/mv.cjs.map +10 -0
  29. package/dist/cjs/src/commands/pwd/pwd.cjs +41 -0
  30. package/dist/cjs/src/commands/pwd/pwd.cjs.map +10 -0
  31. package/dist/cjs/src/commands/rm/rm.cjs +82 -0
  32. package/dist/cjs/src/commands/rm/rm.cjs.map +10 -0
  33. package/dist/cjs/src/commands/sed/sed.cjs +218 -0
  34. package/dist/cjs/src/commands/sed/sed.cjs.map +10 -0
  35. package/dist/cjs/src/commands/sort/sort.cjs +105 -0
  36. package/dist/cjs/src/commands/sort/sort.cjs.map +10 -0
  37. package/dist/cjs/src/commands/tail/tail.cjs +95 -0
  38. package/dist/cjs/src/commands/tail/tail.cjs.map +10 -0
  39. package/dist/cjs/src/commands/tee/tee.cjs +65 -0
  40. package/dist/cjs/src/commands/tee/tee.cjs.map +10 -0
  41. package/dist/cjs/src/commands/test/test.cjs +148 -0
  42. package/dist/cjs/src/commands/test/test.cjs.map +10 -0
  43. package/dist/cjs/src/commands/touch/touch.cjs +70 -0
  44. package/dist/cjs/src/commands/touch/touch.cjs.map +10 -0
  45. package/dist/cjs/src/commands/tree/tree.cjs +161 -0
  46. package/dist/cjs/src/commands/tree/tree.cjs.map +10 -0
  47. package/dist/cjs/src/commands/true-false/true-false.cjs +43 -0
  48. package/dist/cjs/src/commands/true-false/true-false.cjs.map +10 -0
  49. package/dist/cjs/src/commands/uniq/uniq.cjs +116 -0
  50. package/dist/cjs/src/commands/uniq/uniq.cjs.map +10 -0
  51. package/dist/cjs/src/commands/wc/wc.cjs +116 -0
  52. package/dist/cjs/src/commands/wc/wc.cjs.map +10 -0
  53. package/dist/cjs/src/index.cjs +10 -2
  54. package/dist/cjs/src/index.cjs.map +3 -3
  55. package/dist/cjs/src/interpreter/index.cjs +4 -2
  56. package/dist/cjs/src/interpreter/index.cjs.map +3 -3
  57. package/dist/cjs/src/interpreter/interpreter.cjs +390 -2
  58. package/dist/cjs/src/interpreter/interpreter.cjs.map +3 -3
  59. package/dist/cjs/src/lexer/index.cjs +3 -2
  60. package/dist/cjs/src/lexer/index.cjs.map +3 -3
  61. package/dist/cjs/src/lexer/lexer.cjs +359 -8
  62. package/dist/cjs/src/lexer/lexer.cjs.map +3 -3
  63. package/dist/cjs/src/lexer/tokens.cjs +35 -2
  64. package/dist/cjs/src/lexer/tokens.cjs.map +3 -3
  65. package/dist/cjs/src/parser/ast.cjs +25 -1
  66. package/dist/cjs/src/parser/ast.cjs.map +3 -3
  67. package/dist/cjs/src/parser/index.cjs +7 -1
  68. package/dist/cjs/src/parser/index.cjs.map +3 -3
  69. package/dist/cjs/src/parser/parser.cjs +280 -8
  70. package/dist/cjs/src/parser/parser.cjs.map +3 -3
  71. package/dist/cjs/src/shell-dsl.cjs +2 -2
  72. package/dist/cjs/src/shell-dsl.cjs.map +3 -3
  73. package/dist/mjs/index.mjs +25 -5
  74. package/dist/mjs/index.mjs.map +3 -3
  75. package/dist/mjs/package.json +1 -1
  76. package/dist/mjs/src/commands/awk/awk.mjs +246 -0
  77. package/dist/mjs/src/commands/awk/awk.mjs.map +10 -0
  78. package/dist/mjs/src/commands/break-continue/break-continue.mjs +26 -0
  79. package/dist/mjs/src/commands/break-continue/break-continue.mjs.map +10 -0
  80. package/dist/mjs/src/commands/cat/cat.mjs +27 -0
  81. package/dist/mjs/src/commands/cat/cat.mjs.map +10 -0
  82. package/dist/mjs/src/commands/cp/cp.mjs +96 -0
  83. package/dist/mjs/src/commands/cp/cp.mjs.map +10 -0
  84. package/dist/mjs/src/commands/echo/echo.mjs +20 -0
  85. package/dist/mjs/src/commands/echo/echo.mjs.map +10 -0
  86. package/dist/mjs/src/commands/find/find.mjs +221 -0
  87. package/dist/mjs/src/commands/find/find.mjs.map +10 -0
  88. package/dist/mjs/src/commands/grep/grep.mjs +480 -0
  89. package/dist/mjs/src/commands/grep/grep.mjs.map +10 -0
  90. package/dist/mjs/src/commands/head/head.mjs +65 -0
  91. package/dist/mjs/src/commands/head/head.mjs.map +10 -0
  92. package/dist/mjs/src/commands/index.mjs +106 -0
  93. package/dist/mjs/src/commands/index.mjs.map +10 -0
  94. package/dist/mjs/src/commands/ls/ls.mjs +89 -0
  95. package/dist/mjs/src/commands/ls/ls.mjs.map +10 -0
  96. package/dist/mjs/src/commands/mkdir/mkdir.mjs +34 -0
  97. package/dist/mjs/src/commands/mkdir/mkdir.mjs.map +10 -0
  98. package/dist/mjs/src/commands/mv/mv.mjs +88 -0
  99. package/dist/mjs/src/commands/mv/mv.mjs.map +10 -0
  100. package/dist/mjs/src/commands/pwd/pwd.mjs +11 -0
  101. package/dist/mjs/src/commands/pwd/pwd.mjs.map +10 -0
  102. package/dist/mjs/src/commands/rm/rm.mjs +52 -0
  103. package/dist/mjs/src/commands/rm/rm.mjs.map +10 -0
  104. package/dist/mjs/src/commands/sed/sed.mjs +188 -0
  105. package/dist/mjs/src/commands/sed/sed.mjs.map +10 -0
  106. package/dist/mjs/src/commands/sort/sort.mjs +75 -0
  107. package/dist/mjs/src/commands/sort/sort.mjs.map +10 -0
  108. package/dist/mjs/src/commands/tail/tail.mjs +65 -0
  109. package/dist/mjs/src/commands/tail/tail.mjs.map +10 -0
  110. package/dist/mjs/src/commands/tee/tee.mjs +35 -0
  111. package/dist/mjs/src/commands/tee/tee.mjs.map +10 -0
  112. package/dist/mjs/src/commands/test/test.mjs +118 -0
  113. package/dist/mjs/src/commands/test/test.mjs.map +10 -0
  114. package/dist/mjs/src/commands/touch/touch.mjs +40 -0
  115. package/dist/mjs/src/commands/touch/touch.mjs.map +10 -0
  116. package/dist/mjs/src/commands/tree/tree.mjs +131 -0
  117. package/dist/mjs/src/commands/tree/tree.mjs.map +10 -0
  118. package/dist/mjs/src/commands/true-false/true-false.mjs +13 -0
  119. package/dist/mjs/src/commands/true-false/true-false.mjs.map +10 -0
  120. package/dist/mjs/src/commands/uniq/uniq.mjs +86 -0
  121. package/dist/mjs/src/commands/uniq/uniq.mjs.map +10 -0
  122. package/dist/mjs/src/commands/wc/wc.mjs +86 -0
  123. package/dist/mjs/src/commands/wc/wc.mjs.map +10 -0
  124. package/dist/mjs/src/index.mjs +18 -4
  125. package/dist/mjs/src/index.mjs.map +3 -3
  126. package/dist/mjs/src/interpreter/index.mjs +5 -3
  127. package/dist/mjs/src/interpreter/index.mjs.map +2 -2
  128. package/dist/mjs/src/interpreter/interpreter.mjs +390 -2
  129. package/dist/mjs/src/interpreter/interpreter.mjs.map +3 -3
  130. package/dist/mjs/src/lexer/index.mjs +4 -3
  131. package/dist/mjs/src/lexer/index.mjs.map +2 -2
  132. package/dist/mjs/src/lexer/lexer.mjs +359 -8
  133. package/dist/mjs/src/lexer/lexer.mjs.map +3 -3
  134. package/dist/mjs/src/lexer/tokens.mjs +35 -2
  135. package/dist/mjs/src/lexer/tokens.mjs.map +3 -3
  136. package/dist/mjs/src/parser/ast.mjs +25 -1
  137. package/dist/mjs/src/parser/ast.mjs.map +3 -3
  138. package/dist/mjs/src/parser/index.mjs +14 -2
  139. package/dist/mjs/src/parser/index.mjs.map +3 -3
  140. package/dist/mjs/src/parser/parser.mjs +280 -8
  141. package/dist/mjs/src/parser/parser.mjs.map +3 -3
  142. package/dist/mjs/src/shell-dsl.mjs +2 -2
  143. package/dist/mjs/src/shell-dsl.mjs.map +3 -3
  144. package/dist/types/index.d.ts +2 -2
  145. package/dist/types/src/commands/awk/awk.d.ts +2 -0
  146. package/dist/types/src/commands/break-continue/break-continue.d.ts +3 -0
  147. package/dist/types/src/commands/cat/cat.d.ts +2 -0
  148. package/dist/types/src/commands/cp/cp.d.ts +2 -0
  149. package/dist/types/src/commands/echo/echo.d.ts +2 -0
  150. package/dist/types/src/commands/find/find.d.ts +2 -0
  151. package/dist/types/src/commands/grep/grep.d.ts +2 -0
  152. package/dist/types/src/commands/head/head.d.ts +2 -0
  153. package/dist/types/src/commands/index.d.ts +25 -0
  154. package/dist/types/src/commands/ls/ls.d.ts +2 -0
  155. package/dist/types/src/commands/mkdir/mkdir.d.ts +2 -0
  156. package/dist/types/src/commands/mv/mv.d.ts +2 -0
  157. package/dist/types/src/commands/pwd/pwd.d.ts +2 -0
  158. package/dist/types/src/commands/rm/rm.d.ts +2 -0
  159. package/dist/types/src/commands/sed/sed.d.ts +2 -0
  160. package/dist/types/src/commands/sort/sort.d.ts +2 -0
  161. package/dist/types/src/commands/tail/tail.d.ts +2 -0
  162. package/dist/types/src/commands/tee/tee.d.ts +2 -0
  163. package/dist/types/{commands → src/commands/test}/test.d.ts +1 -1
  164. package/dist/types/src/commands/touch/touch.d.ts +2 -0
  165. package/dist/types/src/commands/tree/tree.d.ts +2 -0
  166. package/dist/types/{commands → src/commands/true-false}/true-false.d.ts +1 -1
  167. package/dist/types/src/commands/uniq/uniq.d.ts +2 -0
  168. package/dist/types/src/commands/wc/wc.d.ts +2 -0
  169. package/dist/types/src/index.d.ts +3 -3
  170. package/dist/types/src/interpreter/index.d.ts +1 -1
  171. package/dist/types/src/interpreter/interpreter.d.ts +18 -0
  172. package/dist/types/src/lexer/index.d.ts +2 -2
  173. package/dist/types/src/lexer/lexer.d.ts +16 -2
  174. package/dist/types/src/lexer/tokens.d.ts +20 -0
  175. package/dist/types/src/parser/ast.d.ts +47 -1
  176. package/dist/types/src/parser/index.d.ts +2 -2
  177. package/dist/types/src/parser/parser.d.ts +15 -0
  178. package/package.json +1 -1
  179. package/dist/types/commands/cat.d.ts +0 -2
  180. package/dist/types/commands/cp.d.ts +0 -2
  181. package/dist/types/commands/echo.d.ts +0 -2
  182. package/dist/types/commands/find.d.ts +0 -2
  183. package/dist/types/commands/grep.d.ts +0 -2
  184. package/dist/types/commands/head.d.ts +0 -2
  185. package/dist/types/commands/index.d.ts +0 -22
  186. package/dist/types/commands/ls.d.ts +0 -2
  187. package/dist/types/commands/mkdir.d.ts +0 -2
  188. package/dist/types/commands/mv.d.ts +0 -2
  189. package/dist/types/commands/pwd.d.ts +0 -2
  190. package/dist/types/commands/rm.d.ts +0 -2
  191. package/dist/types/commands/sort.d.ts +0 -2
  192. package/dist/types/commands/tail.d.ts +0 -2
  193. package/dist/types/commands/tee.d.ts +0 -2
  194. package/dist/types/commands/touch.d.ts +0 -2
  195. package/dist/types/commands/tree.d.ts +0 -2
  196. package/dist/types/commands/uniq.d.ts +0 -2
  197. package/dist/types/commands/wc.d.ts +0 -2
@@ -1,5 +1,6 @@
1
1
  // src/lexer/lexer.ts
2
2
  import { LexError } from "../errors.mjs";
3
+ import { KEYWORDS } from "./tokens.mjs";
3
4
  var GLOB_CHARS = new Set(["*", "?", "[", "{", "}"]);
4
5
  var WORD_BREAK_CHARS = new Set([
5
6
  " ",
@@ -25,13 +26,20 @@ class Lexer {
25
26
  pos = 0;
26
27
  line = 1;
27
28
  column = 1;
28
- constructor(source) {
29
+ tokenQueue = [];
30
+ preserveNewlines;
31
+ constructor(source, options) {
29
32
  this.source = source;
33
+ this.preserveNewlines = options?.preserveNewlines ?? false;
30
34
  }
31
35
  tokenize() {
32
36
  const tokens = [];
33
- while (!this.isAtEnd()) {
34
- this.skipWhitespace();
37
+ while (!this.isAtEnd() || this.tokenQueue.length > 0) {
38
+ if (this.tokenQueue.length > 0) {
39
+ tokens.push(this.tokenQueue.shift());
40
+ continue;
41
+ }
42
+ this.skipWhitespaceExceptNewlines();
35
43
  if (this.isAtEnd())
36
44
  break;
37
45
  const token = this.nextToken();
@@ -43,11 +51,34 @@ class Lexer {
43
51
  return tokens;
44
52
  }
45
53
  nextToken() {
54
+ if (this.tokenQueue.length > 0) {
55
+ return this.tokenQueue.shift();
56
+ }
46
57
  const char = this.peek();
58
+ if (char === `
59
+ `) {
60
+ this.advance();
61
+ while (this.peek() === `
62
+ `) {
63
+ this.advance();
64
+ }
65
+ if (this.preserveNewlines) {
66
+ return { type: "newline" };
67
+ }
68
+ return null;
69
+ }
47
70
  if (char === "#") {
48
71
  this.skipComment();
49
72
  return null;
50
73
  }
74
+ if (char === "(") {
75
+ this.advance();
76
+ return { type: "openParen" };
77
+ }
78
+ if (char === ")") {
79
+ this.advance();
80
+ return { type: "closeParen" };
81
+ }
51
82
  if (char === "|") {
52
83
  this.advance();
53
84
  if (this.peek() === "|") {
@@ -74,6 +105,10 @@ class Lexer {
74
105
  }
75
106
  if (char === ";") {
76
107
  this.advance();
108
+ if (this.peek() === ";") {
109
+ this.advance();
110
+ return { type: "doubleSemicolon" };
111
+ }
77
112
  return { type: "semicolon" };
78
113
  }
79
114
  if (char === ">") {
@@ -86,6 +121,10 @@ class Lexer {
86
121
  }
87
122
  if (char === "<") {
88
123
  this.advance();
124
+ if (this.peek() === "<") {
125
+ this.advance();
126
+ return this.readHeredoc();
127
+ }
89
128
  return { type: "redirect", mode: "<" };
90
129
  }
91
130
  if (char === "1" || char === "2") {
@@ -134,6 +173,11 @@ class Lexer {
134
173
  this.advance();
135
174
  if (this.peek() === "(") {
136
175
  this.advance();
176
+ if (this.peek() === "(") {
177
+ this.advance();
178
+ const expression = this.readUntilDoubleCloseParen();
179
+ return { type: "arithmetic", expression };
180
+ }
137
181
  const command = this.readUntilMatchingParen();
138
182
  return { type: "substitution", command };
139
183
  }
@@ -157,6 +201,30 @@ class Lexer {
157
201
  }
158
202
  return { type: "variable", name };
159
203
  }
204
+ readUntilDoubleCloseParen() {
205
+ let depth = 1;
206
+ let result = "";
207
+ while (!this.isAtEnd() && depth > 0) {
208
+ const char = this.peek();
209
+ if (char === "(" && this.peekAhead(1) === "(") {
210
+ depth++;
211
+ result += this.advance();
212
+ result += this.advance();
213
+ } else if (char === ")" && this.peekAhead(1) === ")") {
214
+ depth--;
215
+ if (depth === 0) {
216
+ this.advance();
217
+ this.advance();
218
+ break;
219
+ }
220
+ result += this.advance();
221
+ result += this.advance();
222
+ } else {
223
+ result += this.advance();
224
+ }
225
+ }
226
+ return result;
227
+ }
160
228
  readUntilMatchingParen() {
161
229
  let depth = 1;
162
230
  let result = "";
@@ -242,19 +310,297 @@ class Lexer {
242
310
  value += this.advance();
243
311
  }
244
312
  }
313
+ const assignmentPrefixMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=$/);
314
+ if (assignmentPrefixMatch && (this.peek() === "$" || this.peek() === "'" || this.peek() === '"')) {
315
+ const name = assignmentPrefixMatch[1];
316
+ const valueTokens = this.readAssignmentValueTokens();
317
+ return {
318
+ type: "assignment",
319
+ name,
320
+ value: valueTokens.length === 1 && valueTokens[0].type === "word" ? valueTokens[0].value : valueTokens
321
+ };
322
+ }
245
323
  const assignmentMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=(.*)$/);
246
324
  if (assignmentMatch) {
325
+ const name = assignmentMatch[1];
326
+ const rawValue = assignmentMatch[2];
327
+ const parsedValue = this.parseAssignmentValue(rawValue);
247
328
  return {
248
329
  type: "assignment",
249
- name: assignmentMatch[1],
250
- value: assignmentMatch[2]
330
+ name,
331
+ value: parsedValue
251
332
  };
252
333
  }
334
+ if (KEYWORDS.has(value)) {
335
+ return { type: "keyword", value };
336
+ }
253
337
  if (hasGlobChars) {
254
338
  return { type: "glob", pattern: value };
255
339
  }
256
340
  return { type: "word", value };
257
341
  }
342
+ readAssignmentValueTokens() {
343
+ const tokens = [];
344
+ while (!this.isAtEnd()) {
345
+ const char = this.peek();
346
+ if (char === " " || char === "\t" || char === `
347
+ ` || char === "\r" || char === ";" || char === "|" || char === "&" || char === ">" || char === "<") {
348
+ break;
349
+ }
350
+ if (char === "$") {
351
+ tokens.push(this.readVariable());
352
+ } else if (char === "'") {
353
+ tokens.push(this.readSingleQuote());
354
+ } else if (char === '"') {
355
+ tokens.push(this.readDoubleQuote());
356
+ } else {
357
+ let word = "";
358
+ while (!this.isAtEnd() && !this.isWordBreak(this.peek())) {
359
+ word += this.advance();
360
+ }
361
+ if (word) {
362
+ tokens.push({ type: "word", value: word });
363
+ } else {
364
+ break;
365
+ }
366
+ }
367
+ }
368
+ return tokens;
369
+ }
370
+ parseAssignmentValue(value) {
371
+ if (!value.includes("$")) {
372
+ return value;
373
+ }
374
+ const tokens = [];
375
+ let i = 0;
376
+ let currentString = "";
377
+ while (i < value.length) {
378
+ if (value[i] === "$") {
379
+ if (currentString) {
380
+ tokens.push({ type: "word", value: currentString });
381
+ currentString = "";
382
+ }
383
+ i++;
384
+ if (i >= value.length) {
385
+ tokens.push({ type: "word", value: "$" });
386
+ break;
387
+ }
388
+ if (value[i] === "(" && value[i + 1] === "(") {
389
+ i += 2;
390
+ let depth = 1;
391
+ let expr = "";
392
+ while (i < value.length && depth > 0) {
393
+ if (value[i] === "(" && value[i + 1] === "(") {
394
+ depth++;
395
+ expr += value[i] + value[i + 1];
396
+ i += 2;
397
+ } else if (value[i] === ")" && value[i + 1] === ")") {
398
+ depth--;
399
+ if (depth > 0) {
400
+ expr += value[i] + value[i + 1];
401
+ i += 2;
402
+ } else {
403
+ i += 2;
404
+ }
405
+ } else {
406
+ expr += value[i];
407
+ i++;
408
+ }
409
+ }
410
+ tokens.push({ type: "arithmetic", expression: expr });
411
+ } else if (value[i] === "{") {
412
+ i++;
413
+ let varName = "";
414
+ while (i < value.length && value[i] !== "}") {
415
+ varName += value[i];
416
+ i++;
417
+ }
418
+ if (i < value.length && value[i] === "}") {
419
+ i++;
420
+ }
421
+ tokens.push({ type: "variable", name: varName });
422
+ } else if (/[a-zA-Z_]/.test(value[i])) {
423
+ let varName = "";
424
+ while (i < value.length && /[a-zA-Z0-9_]/.test(value[i])) {
425
+ varName += value[i];
426
+ i++;
427
+ }
428
+ tokens.push({ type: "variable", name: varName });
429
+ } else if (value[i] === "(") {
430
+ i++;
431
+ let depth = 1;
432
+ let cmd = "";
433
+ while (i < value.length && depth > 0) {
434
+ if (value[i] === "(")
435
+ depth++;
436
+ else if (value[i] === ")")
437
+ depth--;
438
+ if (depth > 0) {
439
+ cmd += value[i];
440
+ }
441
+ i++;
442
+ }
443
+ tokens.push({ type: "substitution", command: cmd });
444
+ } else {
445
+ currentString += "$";
446
+ }
447
+ } else {
448
+ currentString += value[i];
449
+ i++;
450
+ }
451
+ }
452
+ if (currentString) {
453
+ tokens.push({ type: "word", value: currentString });
454
+ }
455
+ if (tokens.length === 1 && tokens[0].type === "word") {
456
+ return tokens[0].value;
457
+ }
458
+ return tokens.length > 0 ? tokens : value;
459
+ }
460
+ readHeredoc() {
461
+ const stripTabs = this.peek() === "-";
462
+ if (stripTabs) {
463
+ this.advance();
464
+ }
465
+ while (this.peek() === " " || this.peek() === "\t") {
466
+ this.advance();
467
+ }
468
+ const { delimiter, expand } = this.readHeredocDelimiter();
469
+ this.tokenizeRestOfLine();
470
+ if (this.peek() === `
471
+ `) {
472
+ this.advance();
473
+ }
474
+ let content = "";
475
+ while (!this.isAtEnd()) {
476
+ const lineStart = this.pos;
477
+ let line = "";
478
+ while (!this.isAtEnd() && this.peek() !== `
479
+ `) {
480
+ line += this.advance();
481
+ }
482
+ const strippedLine = stripTabs ? line.replace(/^\t+/, "") : line;
483
+ if (strippedLine === delimiter) {
484
+ if (this.peek() === `
485
+ `) {
486
+ this.advance();
487
+ }
488
+ break;
489
+ }
490
+ if (stripTabs) {
491
+ content += line.replace(/^\t+/, "");
492
+ } else {
493
+ content += line;
494
+ }
495
+ if (this.peek() === `
496
+ `) {
497
+ content += this.advance();
498
+ }
499
+ }
500
+ return { type: "heredoc", content, expand };
501
+ }
502
+ readHeredocDelimiter() {
503
+ const quoteChar = this.peek();
504
+ if (quoteChar === "'" || quoteChar === '"') {
505
+ this.advance();
506
+ let delimiter2 = "";
507
+ while (!this.isAtEnd() && this.peek() !== quoteChar && this.peek() !== `
508
+ `) {
509
+ delimiter2 += this.advance();
510
+ }
511
+ if (this.peek() === quoteChar) {
512
+ this.advance();
513
+ }
514
+ return { delimiter: delimiter2, expand: false };
515
+ }
516
+ let delimiter = "";
517
+ while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== `
518
+ `) {
519
+ if (this.peek() === "\\") {
520
+ this.advance();
521
+ if (!this.isAtEnd()) {
522
+ delimiter += this.advance();
523
+ }
524
+ } else {
525
+ delimiter += this.advance();
526
+ }
527
+ }
528
+ return { delimiter, expand: true };
529
+ }
530
+ tokenizeRestOfLine() {
531
+ while (!this.isAtEnd() && this.peek() !== `
532
+ `) {
533
+ while (this.peek() === " " || this.peek() === "\t") {
534
+ this.advance();
535
+ }
536
+ if (this.isAtEnd() || this.peek() === `
537
+ `)
538
+ break;
539
+ const token = this.readRestOfLineToken();
540
+ if (token) {
541
+ this.tokenQueue.push(token);
542
+ }
543
+ }
544
+ }
545
+ readRestOfLineToken() {
546
+ const char = this.peek();
547
+ if (char === "|") {
548
+ this.advance();
549
+ if (this.peek() === "|") {
550
+ this.advance();
551
+ return { type: "or" };
552
+ }
553
+ return { type: "pipe" };
554
+ }
555
+ if (char === "&") {
556
+ this.advance();
557
+ if (this.peek() === "&") {
558
+ this.advance();
559
+ return { type: "and" };
560
+ }
561
+ return { type: "word", value: "&" };
562
+ }
563
+ if (char === ";") {
564
+ this.advance();
565
+ return { type: "semicolon" };
566
+ }
567
+ if (char === ">") {
568
+ this.advance();
569
+ if (this.peek() === ">") {
570
+ this.advance();
571
+ return { type: "redirect", mode: ">>" };
572
+ }
573
+ return { type: "redirect", mode: ">" };
574
+ }
575
+ if (char === "<") {
576
+ this.advance();
577
+ return { type: "redirect", mode: "<" };
578
+ }
579
+ if (char === "$") {
580
+ return this.readVariable();
581
+ }
582
+ if (char === "'") {
583
+ return this.readSingleQuote();
584
+ }
585
+ if (char === '"') {
586
+ return this.readDoubleQuote();
587
+ }
588
+ let value = "";
589
+ while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== `
590
+ `) {
591
+ if (this.peek() === "\\") {
592
+ this.advance();
593
+ if (!this.isAtEnd()) {
594
+ value += this.advance();
595
+ }
596
+ } else {
597
+ value += this.advance();
598
+ }
599
+ }
600
+ if (value === "")
601
+ return null;
602
+ return { type: "word", value };
603
+ }
258
604
  isWordBreak(char) {
259
605
  return WORD_BREAK_CHARS.has(char);
260
606
  }
@@ -266,6 +612,11 @@ class Lexer {
266
612
  this.advance();
267
613
  }
268
614
  }
615
+ skipWhitespaceExceptNewlines() {
616
+ while (!this.isAtEnd() && /[ \t\r]/.test(this.peek())) {
617
+ this.advance();
618
+ }
619
+ }
269
620
  skipComment() {
270
621
  while (!this.isAtEnd() && this.peek() !== `
271
622
  `) {
@@ -294,12 +645,12 @@ class Lexer {
294
645
  return this.pos >= this.source.length;
295
646
  }
296
647
  }
297
- function lex(source) {
298
- return new Lexer(source).tokenize();
648
+ function lex(source, options) {
649
+ return new Lexer(source, options).tokenize();
299
650
  }
300
651
  export {
301
652
  lex,
302
653
  Lexer
303
654
  };
304
655
 
305
- //# debugId=819722A2CE193AAF64756E2164756E21
656
+ //# debugId=11B4DB819B360AA764756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lexer/lexer.ts"],
4
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"
5
+ "import { LexError } from \"../errors.mjs\";\nimport type { Token, RedirectMode, KeywordValue } from \"./tokens.mjs\";\nimport { KEYWORDS } 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 private tokenQueue: Token[] = [];\n private preserveNewlines: boolean;\n\n constructor(source: string, options?: { preserveNewlines?: boolean }) {\n this.source = source;\n this.preserveNewlines = options?.preserveNewlines ?? false;\n }\n\n tokenize(): Token[] {\n const tokens: Token[] = [];\n\n while (!this.isAtEnd() || this.tokenQueue.length > 0) {\n // Drain token queue first (for heredoc handling)\n if (this.tokenQueue.length > 0) {\n tokens.push(this.tokenQueue.shift()!);\n continue;\n }\n\n this.skipWhitespaceExceptNewlines();\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 // Check token queue first (used for heredoc handling)\n if (this.tokenQueue.length > 0) {\n return this.tokenQueue.shift()!;\n }\n\n const char = this.peek();\n\n // Newlines - significant for control flow\n if (char === \"\\n\") {\n this.advance();\n // Skip consecutive newlines\n while (this.peek() === \"\\n\") {\n this.advance();\n }\n if (this.preserveNewlines) {\n return { type: \"newline\" };\n }\n return null;\n }\n\n // Comments\n if (char === \"#\") {\n this.skipComment();\n return null;\n }\n\n // Parentheses - for case pattern grouping\n if (char === \"(\") {\n this.advance();\n return { type: \"openParen\" };\n }\n\n if (char === \")\") {\n this.advance();\n return { type: \"closeParen\" };\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 // Check for double semicolon (case terminator)\n if (this.peek() === \";\") {\n this.advance();\n return { type: \"doubleSemicolon\" };\n }\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 if (this.peek() === \"<\") {\n this.advance();\n return this.readHeredoc();\n }\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 // Arithmetic expansion $((...)) or command substitution $(...)\n if (this.peek() === \"(\") {\n this.advance(); // consume first (\n // Check for arithmetic expansion $((...))\n if (this.peek() === \"(\") {\n this.advance(); // consume second (\n const expression = this.readUntilDoubleCloseParen();\n return { type: \"arithmetic\", expression };\n }\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 readUntilDoubleCloseParen(): string {\n let depth = 1;\n let result = \"\";\n\n while (!this.isAtEnd() && depth > 0) {\n const char = this.peek();\n if (char === \"(\" && this.peekAhead(1) === \"(\") {\n depth++;\n result += this.advance();\n result += this.advance();\n } else if (char === \")\" && this.peekAhead(1) === \")\") {\n depth--;\n if (depth === 0) {\n this.advance(); // consume first )\n this.advance(); // consume second )\n break;\n }\n result += this.advance();\n result += this.advance();\n } else {\n result += this.advance();\n }\n }\n\n return result;\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 looks like an assignment with value starting with $ or quote\n // e.g., VAR=$(...) or VAR=\"...\" or VAR='...'\n const assignmentPrefixMatch = value.match(/^([a-zA-Z_][a-zA-Z0-9_]*)=$/);\n if (assignmentPrefixMatch && (this.peek() === \"$\" || this.peek() === \"'\" || this.peek() === '\"')) {\n const name = assignmentPrefixMatch[1]!;\n // Read the value part\n const valueTokens = this.readAssignmentValueTokens();\n return {\n type: \"assignment\",\n name,\n value: valueTokens.length === 1 && valueTokens[0]!.type === \"word\"\n ? (valueTokens[0] as { type: \"word\"; value: string }).value\n : valueTokens,\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 const name = assignmentMatch[1]!;\n const rawValue = assignmentMatch[2]!;\n\n // Parse the value to handle variables and arithmetic\n const parsedValue = this.parseAssignmentValue(rawValue);\n return {\n type: \"assignment\",\n name,\n value: parsedValue,\n };\n }\n\n // Check if this is a keyword\n if (KEYWORDS.has(value)) {\n return { type: \"keyword\", value: value as KeywordValue };\n }\n\n if (hasGlobChars) {\n return { type: \"glob\", pattern: value };\n }\n\n return { type: \"word\", value };\n }\n\n private readAssignmentValueTokens(): Token[] {\n const tokens: Token[] = [];\n\n // Read tokens until we hit a space, newline, semicolon, etc.\n while (!this.isAtEnd()) {\n const char = this.peek();\n\n // Stop at whitespace or command terminators\n if (char === \" \" || char === \"\\t\" || char === \"\\n\" || char === \"\\r\" ||\n char === \";\" || char === \"|\" || char === \"&\" || char === \">\" || char === \"<\") {\n break;\n }\n\n if (char === \"$\") {\n tokens.push(this.readVariable());\n } else if (char === \"'\") {\n tokens.push(this.readSingleQuote());\n } else if (char === '\"') {\n tokens.push(this.readDoubleQuote());\n } else {\n // Read until word break\n let word = \"\";\n while (!this.isAtEnd() && !this.isWordBreak(this.peek())) {\n word += this.advance();\n }\n if (word) {\n tokens.push({ type: \"word\", value: word });\n } else {\n break;\n }\n }\n }\n\n return tokens;\n }\n\n private parseAssignmentValue(value: string): string | Token[] {\n // If value contains no special characters, return as string\n if (!value.includes(\"$\")) {\n return value;\n }\n\n // Parse the value to handle $VAR, ${VAR}, $((expr))\n const tokens: Token[] = [];\n let i = 0;\n let currentString = \"\";\n\n while (i < value.length) {\n if (value[i] === \"$\") {\n if (currentString) {\n tokens.push({ type: \"word\", value: currentString });\n currentString = \"\";\n }\n\n i++; // consume $\n if (i >= value.length) {\n tokens.push({ type: \"word\", value: \"$\" });\n break;\n }\n\n // Arithmetic expansion $((expr))\n if (value[i] === \"(\" && value[i + 1] === \"(\") {\n i += 2; // consume ((\n let depth = 1;\n let expr = \"\";\n while (i < value.length && depth > 0) {\n if (value[i] === \"(\" && value[i + 1] === \"(\") {\n depth++;\n expr += value[i]! + value[i + 1]!;\n i += 2;\n } else if (value[i] === \")\" && value[i + 1] === \")\") {\n depth--;\n if (depth > 0) {\n expr += value[i]! + value[i + 1]!;\n i += 2;\n } else {\n i += 2; // consume ))\n }\n } else {\n expr += value[i];\n i++;\n }\n }\n tokens.push({ type: \"arithmetic\", expression: expr });\n }\n // ${VAR} syntax\n else if (value[i] === \"{\") {\n i++; // consume {\n let varName = \"\";\n while (i < value.length && value[i] !== \"}\") {\n varName += value[i];\n i++;\n }\n if (i < value.length && value[i] === \"}\") {\n i++; // consume }\n }\n tokens.push({ type: \"variable\", name: varName });\n }\n // $VAR syntax\n else if (/[a-zA-Z_]/.test(value[i]!)) {\n let varName = \"\";\n while (i < value.length && /[a-zA-Z0-9_]/.test(value[i]!)) {\n varName += value[i];\n i++;\n }\n tokens.push({ type: \"variable\", name: varName });\n }\n // $(cmd) command substitution\n else if (value[i] === \"(\") {\n i++; // consume (\n let depth = 1;\n let cmd = \"\";\n while (i < value.length && depth > 0) {\n if (value[i] === \"(\") depth++;\n else if (value[i] === \")\") depth--;\n if (depth > 0) {\n cmd += value[i];\n }\n i++;\n }\n tokens.push({ type: \"substitution\", command: cmd });\n }\n else {\n // Not a variable, just a $\n currentString += \"$\";\n }\n } else {\n currentString += value[i];\n i++;\n }\n }\n\n if (currentString) {\n tokens.push({ type: \"word\", value: currentString });\n }\n\n if (tokens.length === 1 && tokens[0]!.type === \"word\") {\n return (tokens[0] as { type: \"word\"; value: string }).value;\n }\n\n return tokens.length > 0 ? tokens : value;\n }\n\n private readHeredoc(): Token {\n // Check for tab-stripping variant (<<-)\n const stripTabs = this.peek() === \"-\";\n if (stripTabs) {\n this.advance();\n }\n\n // Skip whitespace before delimiter\n while (this.peek() === \" \" || this.peek() === \"\\t\") {\n this.advance();\n }\n\n // Read delimiter and determine if expansion is enabled\n const { delimiter, expand } = this.readHeredocDelimiter();\n\n // Tokenize the rest of the current line and queue those tokens\n this.tokenizeRestOfLine();\n\n // Skip the newline that starts the heredoc content\n if (this.peek() === \"\\n\") {\n this.advance();\n }\n\n // Read content until closing delimiter\n let content = \"\";\n while (!this.isAtEnd()) {\n const lineStart = this.pos;\n let line = \"\";\n\n // Read until end of line or end of input\n while (!this.isAtEnd() && this.peek() !== \"\\n\") {\n line += this.advance();\n }\n\n // Check if this line is the delimiter (after stripping leading tabs if <<-)\n const strippedLine = stripTabs ? line.replace(/^\\t+/, \"\") : line;\n if (strippedLine === delimiter) {\n // Found closing delimiter, consume newline if present\n if (this.peek() === \"\\n\") {\n this.advance();\n }\n break;\n }\n\n // Add the line to content\n if (stripTabs) {\n content += line.replace(/^\\t+/, \"\");\n } else {\n content += line;\n }\n\n // Add newline if present\n if (this.peek() === \"\\n\") {\n content += this.advance();\n }\n }\n\n return { type: \"heredoc\", content, expand };\n }\n\n private readHeredocDelimiter(): { delimiter: string; expand: boolean } {\n const quoteChar = this.peek();\n\n // Quoted delimiter - no expansion\n if (quoteChar === \"'\" || quoteChar === '\"') {\n this.advance(); // consume opening quote\n let delimiter = \"\";\n while (!this.isAtEnd() && this.peek() !== quoteChar && this.peek() !== \"\\n\") {\n delimiter += this.advance();\n }\n if (this.peek() === quoteChar) {\n this.advance(); // consume closing quote\n }\n return { delimiter, expand: false };\n }\n\n // Unquoted delimiter - expansion enabled\n let delimiter = \"\";\n while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== \"\\n\") {\n if (this.peek() === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n delimiter += this.advance();\n }\n } else {\n delimiter += this.advance();\n }\n }\n\n return { delimiter, expand: true };\n }\n\n private tokenizeRestOfLine(): void {\n // Tokenize the rest of the line (until newline or end)\n while (!this.isAtEnd() && this.peek() !== \"\\n\") {\n // Skip only spaces and tabs, not newlines\n while (this.peek() === \" \" || this.peek() === \"\\t\") {\n this.advance();\n }\n if (this.isAtEnd() || this.peek() === \"\\n\") break;\n\n const token = this.readRestOfLineToken();\n if (token) {\n this.tokenQueue.push(token);\n }\n }\n }\n\n private readRestOfLineToken(): Token | null {\n const char = this.peek();\n\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 return { type: \"word\", value: \"&\" };\n }\n\n if (char === \";\") {\n this.advance();\n return { type: \"semicolon\" };\n }\n\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 if (char === \"$\") {\n return this.readVariable();\n }\n\n if (char === \"'\") {\n return this.readSingleQuote();\n }\n\n if (char === '\"') {\n return this.readDoubleQuote();\n }\n\n // Read a word but stop at newline\n let value = \"\";\n while (!this.isAtEnd() && !this.isWordBreak(this.peek()) && this.peek() !== \"\\n\") {\n if (this.peek() === \"\\\\\") {\n this.advance();\n if (!this.isAtEnd()) {\n value += this.advance();\n }\n } else {\n value += this.advance();\n }\n }\n\n if (value === \"\") return null;\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 skipWhitespaceExceptNewlines(): void {\n while (!this.isAtEnd() && /[ \\t\\r]/.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, options?: { preserveNewlines?: boolean }): Token[] {\n return new Lexer(source, options).tokenize();\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "819722A2CE193AAF64756E2164756E21",
7
+ "mappings": "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",
8
+ "debugId": "11B4DB819B360AA764756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,8 +1,25 @@
1
1
  // src/lexer/tokens.ts
2
+ var KEYWORDS = new Set([
3
+ "if",
4
+ "then",
5
+ "elif",
6
+ "else",
7
+ "fi",
8
+ "for",
9
+ "in",
10
+ "do",
11
+ "done",
12
+ "while",
13
+ "until",
14
+ "case",
15
+ "esac"
16
+ ]);
2
17
  function tokenToString(token) {
3
18
  switch (token.type) {
4
19
  case "word":
5
20
  return token.value;
21
+ case "keyword":
22
+ return token.value;
6
23
  case "pipe":
7
24
  return "|";
8
25
  case "and":
@@ -11,12 +28,17 @@ function tokenToString(token) {
11
28
  return "||";
12
29
  case "semicolon":
13
30
  return ";";
31
+ case "newline":
32
+ return `
33
+ `;
14
34
  case "redirect":
15
35
  return token.mode;
16
36
  case "variable":
17
37
  return `$${token.name}`;
18
38
  case "substitution":
19
39
  return `$(${token.command})`;
40
+ case "arithmetic":
41
+ return `$((${token.expression}))`;
20
42
  case "glob":
21
43
  return token.pattern;
22
44
  case "singleQuote":
@@ -25,12 +47,23 @@ function tokenToString(token) {
25
47
  return `"${token.parts.map((p) => typeof p === "string" ? p : tokenToString(p)).join("")}"`;
26
48
  case "assignment":
27
49
  return `${token.name}=${typeof token.value === "string" ? token.value : token.value.map(tokenToString).join("")}`;
50
+ case "heredoc":
51
+ return `<<${token.expand ? "EOF" : "'EOF'"}
52
+ ${token.content}
53
+ EOF`;
54
+ case "openParen":
55
+ return "(";
56
+ case "closeParen":
57
+ return ")";
58
+ case "doubleSemicolon":
59
+ return ";;";
28
60
  case "eof":
29
61
  return "<EOF>";
30
62
  }
31
63
  }
32
64
  export {
33
- tokenToString
65
+ tokenToString,
66
+ KEYWORDS
34
67
  };
35
68
 
36
- //# debugId=D103DC901FB8A54E64756E2164756E21
69
+ //# debugId=6DFA4E9D27E55DE464756E2164756E21