|
1 | 1 | use codeql_extractor::extractor::simple; |
2 | 2 | use yeast::{build::BuildCtx, rule, DesugaringConfig, PhaseKind}; |
3 | 3 |
|
4 | | -/// Names of output AST kinds that belong to the `expr` supertype. Kept in |
5 | | -/// sync with `ast_types.yml`. `unsupported_node` is intentionally omitted |
6 | | -/// because it is also a member of the `stmt` supertype. |
7 | | -const EXPR_KINDS: &[&str] = &[ |
8 | | - "name_expr", |
9 | | - "int_literal", |
10 | | - "string_literal", |
11 | | - "binary_expr", |
12 | | - "unary_expr", |
13 | | - "call_expr", |
14 | | - "member_access_expr", |
15 | | - "lambda_expr", |
16 | | -]; |
17 | | - |
18 | | -/// If `id` is an `expr`, wrap it in `expr_stmt` so it can sit in a `stmt` |
19 | | -/// position; otherwise return it unchanged. |
20 | | -fn wrap_expr_in_stmt(ctx: &mut BuildCtx, id: usize) -> usize { |
21 | | - let kind = ctx.ast.get_node(id).map(|n| n.kind()).unwrap_or(""); |
22 | | - if EXPR_KINDS.contains(&kind) { |
23 | | - yeast::tree!(ctx, (expr_stmt expr: {id})) |
24 | | - } else { |
25 | | - id |
26 | | - } |
27 | | -} |
28 | | - |
29 | 4 | fn translation_rules() -> Vec<yeast::Rule> { |
30 | 5 | vec![ |
31 | | - rule!( |
32 | | - (source_file (_)* @children) |
33 | | - => |
34 | | - (top_level |
35 | | - body: {..children} |
36 | | - ) |
37 | | - ), |
38 | | - // ---- Binary expressions ---- |
39 | | - // Swift's parser produces a different node kind for each operator |
40 | | - // family, but the field shape (`lhs` / `op` / `rhs`) is uniform, so |
41 | | - // each maps onto `binary_expr`. |
42 | | - rule!( |
43 | | - (additive_expression |
44 | | - lhs: (_) @left |
45 | | - op: _ @operator |
46 | | - rhs: (_) @right) |
47 | | - => |
48 | | - (binary_expr |
49 | | - left: {left} |
50 | | - operator: (operator #{operator}) |
51 | | - right: {right}) |
52 | | - ), |
53 | | - rule!( |
54 | | - (multiplicative_expression |
55 | | - lhs: (_) @left |
56 | | - op: _ @operator |
57 | | - rhs: (_) @right) |
58 | | - => |
59 | | - (binary_expr |
60 | | - left: {left} |
61 | | - operator: (operator #{operator}) |
62 | | - right: {right}) |
63 | | - ), |
64 | | - rule!( |
65 | | - (comparison_expression |
66 | | - lhs: (_) @left |
67 | | - op: _ @operator |
68 | | - rhs: (_) @right) |
69 | | - => |
70 | | - (binary_expr |
71 | | - left: {left} |
72 | | - operator: (operator #{operator}) |
73 | | - right: {right}) |
74 | | - ), |
75 | | - rule!( |
76 | | - (equality_expression |
77 | | - lhs: (_) @left |
78 | | - op: _ @operator |
79 | | - rhs: (_) @right) |
80 | | - => |
81 | | - (binary_expr |
82 | | - left: {left} |
83 | | - operator: (operator #{operator}) |
84 | | - right: {right}) |
85 | | - ), |
86 | | - rule!( |
87 | | - (conjunction_expression |
88 | | - lhs: (_) @left |
89 | | - op: _ @operator |
90 | | - rhs: (_) @right) |
91 | | - => |
92 | | - (binary_expr |
93 | | - left: {left} |
94 | | - operator: (operator #{operator}) |
95 | | - right: {right}) |
96 | | - ), |
97 | | - rule!( |
98 | | - (disjunction_expression |
99 | | - lhs: (_) @left |
100 | | - op: _ @operator |
101 | | - rhs: (_) @right) |
102 | | - => |
103 | | - (binary_expr |
104 | | - left: {left} |
105 | | - operator: (operator #{operator}) |
106 | | - right: {right}) |
107 | | - ), |
108 | | - rule!( |
109 | | - (nil_coalescing_expression |
110 | | - lhs: (_) @left |
111 | | - op: _ @operator |
112 | | - rhs: (_) @right) |
113 | | - => |
114 | | - (binary_expr |
115 | | - left: {left} |
116 | | - operator: (operator #{operator}) |
117 | | - right: {right}) |
118 | | - ), |
119 | | - rule!( |
120 | | - (range_expression |
121 | | - start: (_) @left |
122 | | - op: _ @operator |
123 | | - end: (_) @right) |
124 | | - => |
125 | | - (binary_expr |
126 | | - left: {left} |
127 | | - operator: (operator #{operator}) |
128 | | - right: {right}) |
129 | | - ), |
130 | | - // ---- Unary expressions ---- |
131 | | - rule!( |
132 | | - (prefix_expression |
133 | | - operation: _ @operator |
134 | | - target: (_) @operand) |
135 | | - => |
136 | | - (unary_expr |
137 | | - operand: {operand} |
138 | | - operator: (operator #{operator})) |
139 | | - ), |
140 | | - // ---- Identifiers / name expressions ---- |
141 | | - rule!( |
142 | | - (simple_identifier) @name |
143 | | - => |
144 | | - (name_expr |
145 | | - identifier: (identifier #{name})) |
146 | | - ), |
147 | | - // ---- Literals ---- |
148 | | - rule!( |
149 | | - (integer_literal) @lit |
150 | | - => |
151 | | - (int_literal #{lit}) |
152 | | - ), |
153 | | - // String literals: render the *raw* source text, including the |
154 | | - // surrounding quotes. Interpolations (e.g. `"hi \(x)"`) are not |
155 | | - // yet broken out into structured pieces \u2014 they show up as part |
156 | | - // of the literal's source text. |
157 | | - rule!( |
158 | | - (line_string_literal) @lit |
159 | | - => |
160 | | - (string_literal #{lit}) |
161 | | - ), // ---- Lambdas / closures ---- |
162 | | - // Map a `lambda_literal` whose body is a single statement to |
163 | | - // `lambda_expr`. Multi-statement bodies fall through to |
164 | | - // `unsupported_node` because `lambda_expr.body` is single-valued |
165 | | - // in the current `ast_types.yml`. Parameters from explicit-typed |
166 | | - // closures (`{ (x: Int) -> Int in ... }`) are not yet captured. |
167 | | - rule!( |
168 | | - (lambda_literal |
169 | | - (statements (_) @body)) |
170 | | - => |
171 | | - (lambda_expr |
172 | | - body: {body}) |
173 | | - ), |
174 | | - // ---- Block / statement wrapping ---- |
175 | | - // A `(statements ...)` node corresponds to a brace-delimited block. |
176 | | - // Each child is mapped through translation; bare expression results |
177 | | - // get wrapped in `expr_stmt` so they fit the `body*: stmt` field. |
178 | | - rule!( |
179 | | - (statements (_)* @stmts) |
180 | | - => |
181 | | - (block_stmt body: {..stmts.iter().copied().map(|n| |
182 | | - wrap_expr_in_stmt(&mut __yeast_ctx, n.into()) |
183 | | - ).collect::<Vec<usize>>()}) |
184 | | - ), |
185 | | - // ---- Calls and member access ---- |
186 | | - // Member access, e.g. `obj.member`. The Swift parser wraps the |
187 | | - // member name as `(navigation_suffix suffix: (simple_identifier))`. |
188 | | - rule!( |
189 | | - (navigation_expression |
190 | | - target: (_) @target |
191 | | - suffix: (navigation_suffix |
192 | | - suffix: (simple_identifier) @member)) |
193 | | - => |
194 | | - (member_access_expr |
195 | | - target: {target} |
196 | | - member: (identifier #{member})) |
197 | | - ), |
198 | | - // Function / method call. The callee is the first child of |
199 | | - // `call_expression`; the second is a `call_suffix` whose |
200 | | - // `value_arguments` (if present) hold the parenthesized args. A |
201 | | - // trailing closure (`call_suffix` with a `lambda_literal` child) |
202 | | - // is appended as a final argument. |
203 | | - rule!( |
204 | | - (call_expression |
205 | | - (_) @callee |
206 | | - (call_suffix |
207 | | - (value_arguments |
208 | | - (value_argument value: (_) @args)*)? |
209 | | - (lambda_literal)? @trailing)) |
210 | | - => |
211 | | - (call_expr |
212 | | - function: {callee} |
213 | | - argument: {..args} |
214 | | - argument: {..trailing} |
215 | | - ) |
216 | | - ), |
217 | | - // ---- Guard statement ---- |
218 | | - // `guard let x = e else { ... }` — currently only handles the |
219 | | - // let-binding form. The Swift parser models the `let` keyword as a |
220 | | - // `value_binding_pattern` child of `condition`, followed by an |
221 | | - // unnamed `=` and the source expression. |
222 | | - rule!( |
223 | | - (guard_statement |
224 | | - bound_identifier: (simple_identifier) @id |
225 | | - condition: (value_binding_pattern) |
226 | | - condition: (_) @value |
227 | | - (else) |
228 | | - (statements) @else_branch) |
229 | | - => |
230 | | - (guard_if_stmt |
231 | | - condition: (let_pattern_condition |
232 | | - pattern: (var_pattern identifier: (identifier #{id})) |
233 | | - value: {value}) |
234 | | - else: {else_branch}) |
235 | | - ), |
236 | | - // ---- If statement ---- |
237 | | - // if-let binding (with optional else branch). The Swift parser puts |
238 | | - // the bound name in `bound_identifier`, the `let` keyword as a |
239 | | - // `value_binding_pattern` child of `condition`, and the source |
240 | | - // expression as a separate child of `condition`. |
241 | | - rule!( |
242 | | - (if_statement |
243 | | - bound_identifier: (simple_identifier) @id |
244 | | - condition: (value_binding_pattern) |
245 | | - condition: (_) @value |
246 | | - (statements) @then |
247 | | - (else) |
248 | | - (_) @else_branch) |
249 | | - => |
250 | | - (if_stmt |
251 | | - condition: (let_pattern_condition |
252 | | - pattern: (var_pattern identifier: (identifier #{id})) |
253 | | - value: {value}) |
254 | | - then: {then} |
255 | | - else: {else_branch}) |
256 | | - ), |
257 | | - rule!( |
258 | | - (if_statement |
259 | | - bound_identifier: (simple_identifier) @id |
260 | | - condition: (value_binding_pattern) |
261 | | - condition: (_) @value |
262 | | - (statements) @then) |
263 | | - => |
264 | | - (if_stmt |
265 | | - condition: (let_pattern_condition |
266 | | - pattern: (var_pattern identifier: (identifier #{id})) |
267 | | - value: {value}) |
268 | | - then: {then}) |
269 | | - ), |
270 | | - // With explicit else branch (block or chained if). |
271 | | - rule!( |
272 | | - (if_statement |
273 | | - condition: (_) @cond |
274 | | - (statements) @then |
275 | | - (else) |
276 | | - (_) @else_branch) |
277 | | - => |
278 | | - (if_stmt |
279 | | - condition: (expr_condition expr: {cond}) |
280 | | - then: {then} |
281 | | - else: {else_branch}) |
282 | | - ), |
283 | | - // Without else branch. |
284 | | - rule!( |
285 | | - (if_statement |
286 | | - condition: (_) @cond |
287 | | - (statements) @then) |
288 | | - => |
289 | | - (if_stmt |
290 | | - condition: (expr_condition expr: {cond}) |
291 | | - then: {then}) |
292 | | - ), // ---- Patterns ---- |
293 | | - // The Swift parser uses a `pattern` node with a `bound_identifier` |
294 | | - // field for simple bindings such as `let x = ...`. |
295 | | - rule!( |
296 | | - (pattern bound_identifier: (simple_identifier) @id) |
297 | | - => |
298 | | - (var_pattern |
299 | | - identifier: (identifier #{id})) |
300 | | - ), |
301 | | - // Inside tuple patterns, the inner `pattern` node holds a bare |
302 | | - // `simple_identifier` (with no `bound_identifier` field). |
303 | | - rule!( |
304 | | - (pattern (simple_identifier) @id) |
305 | | - => |
306 | | - (var_pattern |
307 | | - identifier: (identifier #{id})) |
308 | | - ), |
309 | | - // Tuple destructuring pattern, e.g. `let (a, b) = pair`. The parser |
310 | | - // emits a `pattern` node whose unnamed children are themselves |
311 | | - // `pattern` nodes. |
312 | | - rule!( |
313 | | - (pattern (pattern)+ @parts) |
314 | | - => |
315 | | - (tuple_pattern element: {..parts}) |
316 | | - ), |
317 | | - // ---- Variable declarations ---- |
318 | | - // Handles single (`let x = e`), multiple (`let x = 1, y = 2`), |
319 | | - // and uninitialized (`var x: T`) bindings. |
320 | | - rule!( |
321 | | - (property_declaration |
322 | | - name: (_)* @pats |
323 | | - value: (_)* @vals) |
324 | | - => |
325 | | - (variable_declaration_stmt |
326 | | - variable_declarator: {..pats.iter().enumerate().map(|(i, &pat)| { |
327 | | - match vals.get(i).copied() { |
328 | | - Some(val) => yeast::tree!( |
329 | | - (variable_declarator |
330 | | - pattern: {pat} |
331 | | - value: {val})), |
332 | | - None => yeast::tree!( |
333 | | - (variable_declarator |
334 | | - pattern: {pat})), |
335 | | - } |
336 | | - })}) |
337 | | - ), |
338 | 6 | // ---- Fallbacks ---- |
339 | 7 | rule!( |
340 | 8 | (_) |
|
0 commit comments