-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAstStmt.java
More file actions
369 lines (269 loc) · 10.3 KB
/
Copy pathAstStmt.java
File metadata and controls
369 lines (269 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
package processing.mode.cpp;
import java.util.List;
/*
* Consolidated statement AST node types -- formerly 17 separate files
* under tools/cpp-parser's ast/stmt/ package. Merged for the same reason
* as AstExpr.java; see its header comment.
*/
/**
* Root of the statement AST hierarchy. Node set confirmed by walking the full
* test corpus (LSystem, Mandelbrot, Button, Handles, plus two synthetic
* kitchen-sink batches covering control flow, arrays, OOP features, lambdas,
* templates, function pointers, and namespaces).
*
* Note on if/else-if chains: there is no separate "ElseIfStatement" -- an
* "else if (...)" is just an IfStatement whose elseBranch is itself another
* IfStatement, the standard recursive-descent representation. Arbitrary-length
* chains (confirmed up to 5-way in the LSystem render() method) fall out of
* this for free with no special grammar rule.
*/
sealed interface Statement extends Node
permits ExprStatement, DeclStatement, Block, IfStatement, ForStatement,
RangeForStatement, WhileStatement, DoWhileStatement, SwitchStatement,
ReturnStatement, BreakStatement, ContinueStatement, TryStatement,
DeleteStatement {
}
/** A brace-delimited sequence of statements: "{ stmt; stmt; ... }". */
record Block(
List<Statement> statements,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* An expression used as a statement, terminated by ";": assignments
* ("production = iterate(...);"), bare calls ("ps.render();"), increments
* ("generations++;"), etc.
*/
record ExprStatement(
Expr expr,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* A single local variable declaration used as a statement, e.g. "int x = 5;",
* "float w = 4;", "Handle* h = handles.get(i);".
*
* Per the corpus-validation decision on multi-declarator statements (e.g.
* "int rectX, rectY;", "bool over, press;"), the parser desugars comma-separated
* declarator lists into multiple single-name DeclStatement nodes at parse time
* -- each sharing the same TypeRef but otherwise independent. This keeps every
* downstream semantic pass and the codegen stage working with a uniform single-
* name shape rather than needing to handle a list-of-declarators case everywhere.
* If exact source round-trip formatting of comma-lists is ever needed by codegen,
* that's recovered via a sourceGroupId correlation field, not by changing this
* node's shape -- not implemented yet since nothing has required it so far.
*
* @param arrayDims empty for scalars; one Expr per dimension for fixed-size
* C-style arrays (e.g. "int grid[3][3];" has two entries).
* An entry may itself be null-equivalent (use a Literal of
* empty text, or omit by convention -- TBD by the parser
* implementation) for an array with no explicit constant
* size when accompanied by an initializer list; not yet
* exercised by the corpus, flagged for when it is.
*
* isStatic/isConst added after a real bug was found via adversarial
* stress-case probing: "static int x = 5;" as a LOCAL variable (inside
* a function body) failed to parse at all -- "static" was only ever
* consumed by the TOP-LEVEL declaration path, never by
* parseDeclStatementsDesugared (the statement/local-scope path). This
* record had no field to even HOLD that information before this fix,
* which is also why the separately-documented "local const loses its
* const-ness" gap existed -- both are the same underlying problem (this
* record only ever modeled "no qualifier" local declarations), fixed
* together here.
*/
record DeclStatement(
TypeRef type,
String name,
List<Expr> arrayDims,
Expr initializer,
boolean isStatic,
boolean isConst,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* "if (condition) thenBranch [else elseBranch]".
*
* elseBranch is null when absent. An "else if (...)" chain is represented as
* elseBranch being another IfStatement directly (no separate ElseIfStatement
* node) -- confirmed sufficient for arbitrary-length chains by the LSystem
* render() method's 5-way else-if chain.
*
* thenBranch/elseBranch are themselves Statement, which permits both the brace
* form ("if (x) { ... }") and the single-statement-no-braces form
* ("if (i % 2 == 0) continue;") confirmed present in the corpus -- both parse
* to the same shape, just with elseBranch/thenBranch being a Block in one case
* and a single non-Block Statement in the other.
*/
record IfStatement(
Expr condition,
Statement thenBranch,
Statement elseBranch,
boolean isConstexpr,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* The classic 3-part for loop: "for (init; condition; update) body".
*
* init is a Statement (typically a DeclStatement, e.g. "int i = 0", or an
* ExprStatement) rather than a bare Expr, since the corpus shows the init
* clause is itself a declaration in every real occurrence -- modeling it as
* Statement keeps this uniform with how declarations are represented
* everywhere else rather than inventing a separate inline-decl shape just
* for this one grammar position. update is a plain Expr (e.g. "i++"),
* matched against the corpus's exclusively-expression update clauses.
*
* Distinct from {@link RangeForStatement} ("for (auto& x : items)"), a
* separate grammar form confirmed present in the corpus's synthetic fixtures.
*/
record ForStatement(
Statement init,
Expr condition,
Expr update,
Statement body,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* Range-based for loop: "for (Type& name : iterableExpr) body", e.g.
* "for (auto& item : items) { ... }". Confirmed as a distinct grammar form
* from the classic 3-part ForStatement by the synthetic kitchen-sink fixture.
*/
record RangeForStatement(
TypeRef declType,
String declName,
boolean isReference,
Expr iterableExpr,
Statement body,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/** "while (condition) body". */
record WhileStatement(
Expr condition,
Statement body,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/** "do body while (condition);". */
record DoWhileStatement(
Statement body,
Expr condition,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* A single "case" (or "default") clause within a switch statement.
*
* @param matchValue the case's constant expression (e.g. a Literal); null for
* the "default:" clause
* @param body the statements under this case, up to (but not including)
* the next case/default/closing brace. Fallthrough (a case
* with no "break;" at the end of its body) is simply
* represented as-is -- confirmed by the corpus's
* switchOnIntWithFallthrough fixture, where case 1 falls
* into case 2 with no special node needed; the absence of
* a trailing BreakStatement in body is itself the
* fallthrough signal for any later pass that cares.
*/
record SwitchCase(Expr matchValue, List<Statement> body) {
}
/**
* "switch (subject) { case ...: ...; case ...: ...; default: ...; }".
* Confirmed by the corpus to work uniformly whether switching on an int or a
* char subject -- the grammar doesn't need to know the subject's type, that's
* purely a later type-checking concern.
*/
record SwitchStatement(
Expr subject,
List<SwitchCase> cases,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* "return expr;" or bare "return;" (value is null for the latter -- needed by
* void-returning functions/methods, e.g. early-return patterns not yet seen
* in the corpus but required by the grammar's own completeness regardless).
*/
record ReturnStatement(
Expr value,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/** "break;" -- exits the nearest enclosing loop or switch. */
record BreakStatement(
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/** "continue;" -- skips to the next iteration of the nearest enclosing loop. */
record ContinueStatement(
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* "try { ... } catch (...) { ... } [catch (...) { ... } ...]".
* Pass-through parsing only, per the original grammar-scope decision --
* the parser doesn't attempt to model exception-handling semantics.
*/
record TryStatement(
Block tryBlock,
List<CatchClause> catchClauses,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}
/**
* A single "catch" clause. exceptionType/varName are both null for the
* catch-all "catch (...)" form confirmed in the corpus (tryCatchPassthrough
* fixture); a typed catch ("catch (const std::exception& e)") is not yet
* exercised by any fixture but supported by the grammar regardless, since
* pass-through parsing of try/catch was always the scope, not just the
* catch-all form specifically.
*/
record CatchClause(TypeRef exceptionType, String varName, Block body, boolean isCatchAll) {
}
/**
* "delete expr;" or "delete[] expr;" -- isArray distinguishes the two forms,
* both confirmed present in the corpus (arrayNewAndDelete / plainNewAndDelete
* fixtures). Modeled as a statement rather than an expression since "delete"
* is always used as a bare statement in every occurrence seen, and C++ itself
* treats it as an expression of type void in a context that's only ever used
* statement-like in practice -- no corpus evidence of "delete" appearing
* nested inside another expression, so the simpler statement-only shape is
* used unless a counterexample shows up.
*/
record DeleteStatement(
Expr target,
boolean isArray,
int line,
int col,
List<CppLexerToken> leadingComments
) implements Statement {
}