Skip to content

Commit 78e1f2e

Browse files
authored
Awk interpreter (#15)
* Migrate AWK to interpreter * more-depth * async * more-tests * lint * knip
1 parent 34a7f6a commit 78e1f2e

37 files changed

+8999
-2282
lines changed

src/commands/awk/ast.ts

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
/**
2+
* AWK Abstract Syntax Tree Types
3+
*
4+
* Follows the same discriminated union pattern as the main bash AST.
5+
*/
6+
7+
// ─── Expressions ───────────────────────────────────────────
8+
9+
export type AwkExpr =
10+
| AwkNumberLiteral
11+
| AwkStringLiteral
12+
| AwkRegexLiteral
13+
| AwkFieldRef
14+
| AwkVariable
15+
| AwkArrayAccess
16+
| AwkBinaryOp
17+
| AwkUnaryOp
18+
| AwkTernaryOp
19+
| AwkFunctionCall
20+
| AwkAssignment
21+
| AwkPreIncrement
22+
| AwkPreDecrement
23+
| AwkPostIncrement
24+
| AwkPostDecrement
25+
| AwkGetline
26+
| AwkInExpr
27+
| AwkTuple;
28+
29+
export interface AwkNumberLiteral {
30+
type: "number";
31+
value: number;
32+
}
33+
34+
export interface AwkStringLiteral {
35+
type: "string";
36+
value: string;
37+
}
38+
39+
export interface AwkRegexLiteral {
40+
type: "regex";
41+
pattern: string;
42+
}
43+
44+
export interface AwkFieldRef {
45+
type: "field";
46+
index: AwkExpr;
47+
}
48+
49+
export interface AwkVariable {
50+
type: "variable";
51+
name: string;
52+
}
53+
54+
export interface AwkArrayAccess {
55+
type: "array_access";
56+
array: string;
57+
key: AwkExpr;
58+
}
59+
60+
export interface AwkBinaryOp {
61+
type: "binary";
62+
operator:
63+
| "+"
64+
| "-"
65+
| "*"
66+
| "/"
67+
| "%"
68+
| "^"
69+
| "=="
70+
| "!="
71+
| "<"
72+
| ">"
73+
| "<="
74+
| ">="
75+
| "~"
76+
| "!~"
77+
| "&&"
78+
| "||"
79+
| " "; // concatenation
80+
left: AwkExpr;
81+
right: AwkExpr;
82+
}
83+
84+
export interface AwkUnaryOp {
85+
type: "unary";
86+
operator: "!" | "-" | "+";
87+
operand: AwkExpr;
88+
}
89+
90+
export interface AwkPreIncrement {
91+
type: "pre_increment";
92+
operand: AwkVariable | AwkArrayAccess | AwkFieldRef;
93+
}
94+
95+
export interface AwkPreDecrement {
96+
type: "pre_decrement";
97+
operand: AwkVariable | AwkArrayAccess | AwkFieldRef;
98+
}
99+
100+
export interface AwkPostIncrement {
101+
type: "post_increment";
102+
operand: AwkVariable | AwkArrayAccess | AwkFieldRef;
103+
}
104+
105+
export interface AwkPostDecrement {
106+
type: "post_decrement";
107+
operand: AwkVariable | AwkArrayAccess | AwkFieldRef;
108+
}
109+
110+
export interface AwkTernaryOp {
111+
type: "ternary";
112+
condition: AwkExpr;
113+
consequent: AwkExpr;
114+
alternate: AwkExpr;
115+
}
116+
117+
export interface AwkFunctionCall {
118+
type: "call";
119+
name: string;
120+
args: AwkExpr[];
121+
}
122+
123+
export interface AwkAssignment {
124+
type: "assignment";
125+
operator: "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "^=";
126+
target: AwkFieldRef | AwkVariable | AwkArrayAccess;
127+
value: AwkExpr;
128+
}
129+
130+
export interface AwkInExpr {
131+
type: "in";
132+
key: AwkExpr;
133+
array: string;
134+
}
135+
136+
export interface AwkGetline {
137+
type: "getline";
138+
variable?: string;
139+
file?: AwkExpr;
140+
}
141+
142+
export interface AwkTuple {
143+
type: "tuple";
144+
elements: AwkExpr[];
145+
}
146+
147+
// ─── Statements ────────────────────────────────────────────
148+
149+
export type AwkStmt =
150+
| AwkExpressionStmt
151+
| AwkPrintStmt
152+
| AwkPrintfStmt
153+
| AwkIfStmt
154+
| AwkWhileStmt
155+
| AwkDoWhileStmt
156+
| AwkForStmt
157+
| AwkForInStmt
158+
| AwkBreakStmt
159+
| AwkContinueStmt
160+
| AwkNextStmt
161+
| AwkNextFileStmt
162+
| AwkExitStmt
163+
| AwkReturnStmt
164+
| AwkDeleteStmt
165+
| AwkBlock;
166+
167+
export interface AwkExpressionStmt {
168+
type: "expr_stmt";
169+
expression: AwkExpr;
170+
}
171+
172+
export interface AwkPrintStmt {
173+
type: "print";
174+
args: AwkExpr[];
175+
output?: { redirect: ">" | ">>"; file: AwkExpr };
176+
}
177+
178+
export interface AwkPrintfStmt {
179+
type: "printf";
180+
format: AwkExpr;
181+
args: AwkExpr[];
182+
output?: { redirect: ">" | ">>"; file: AwkExpr };
183+
}
184+
185+
export interface AwkIfStmt {
186+
type: "if";
187+
condition: AwkExpr;
188+
consequent: AwkStmt;
189+
alternate?: AwkStmt;
190+
}
191+
192+
export interface AwkWhileStmt {
193+
type: "while";
194+
condition: AwkExpr;
195+
body: AwkStmt;
196+
}
197+
198+
export interface AwkDoWhileStmt {
199+
type: "do_while";
200+
body: AwkStmt;
201+
condition: AwkExpr;
202+
}
203+
204+
export interface AwkForStmt {
205+
type: "for";
206+
init?: AwkExpr;
207+
condition?: AwkExpr;
208+
update?: AwkExpr;
209+
body: AwkStmt;
210+
}
211+
212+
export interface AwkForInStmt {
213+
type: "for_in";
214+
variable: string;
215+
array: string;
216+
body: AwkStmt;
217+
}
218+
219+
export interface AwkBlock {
220+
type: "block";
221+
statements: AwkStmt[];
222+
}
223+
224+
export interface AwkBreakStmt {
225+
type: "break";
226+
}
227+
export interface AwkContinueStmt {
228+
type: "continue";
229+
}
230+
export interface AwkNextStmt {
231+
type: "next";
232+
}
233+
export interface AwkNextFileStmt {
234+
type: "nextfile";
235+
}
236+
export interface AwkExitStmt {
237+
type: "exit";
238+
code?: AwkExpr;
239+
}
240+
export interface AwkReturnStmt {
241+
type: "return";
242+
value?: AwkExpr;
243+
}
244+
export interface AwkDeleteStmt {
245+
type: "delete";
246+
target: AwkArrayAccess | AwkVariable;
247+
}
248+
249+
// ─── Program Structure ─────────────────────────────────────
250+
251+
export type AwkPattern =
252+
| AwkBeginPattern
253+
| AwkEndPattern
254+
| AwkExprPattern
255+
| AwkRegexPattern
256+
| AwkRangePattern;
257+
258+
export interface AwkBeginPattern {
259+
type: "begin";
260+
}
261+
export interface AwkEndPattern {
262+
type: "end";
263+
}
264+
export interface AwkExprPattern {
265+
type: "expr_pattern";
266+
expression: AwkExpr;
267+
}
268+
export interface AwkRegexPattern {
269+
type: "regex_pattern";
270+
pattern: string;
271+
}
272+
export interface AwkRangePattern {
273+
type: "range";
274+
start: AwkPattern;
275+
end: AwkPattern;
276+
}
277+
278+
export interface AwkRule {
279+
pattern?: AwkPattern;
280+
action: AwkBlock;
281+
}
282+
283+
export interface AwkFunctionDef {
284+
name: string;
285+
params: string[];
286+
body: AwkBlock;
287+
}
288+
289+
export interface AwkProgram {
290+
functions: AwkFunctionDef[];
291+
rules: AwkRule[];
292+
}

0 commit comments

Comments
 (0)