See More

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 statements, int line, int col, List 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 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 arrayDims, Expr initializer, boolean isStatic, boolean isConst, int line, int col, List 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, int line, int col, List 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 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 leadingComments ) implements Statement { } /** "while (condition) body". */ record WhileStatement( Expr condition, Statement body, int line, int col, List leadingComments ) implements Statement { } /** "do body while (condition);". */ record DoWhileStatement( Statement body, Expr condition, int line, int col, List 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 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 cases, int line, int col, List 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 leadingComments ) implements Statement { } /** "break;" -- exits the nearest enclosing loop or switch. */ record BreakStatement( int line, int col, List leadingComments ) implements Statement { } /** "continue;" -- skips to the next iteration of the nearest enclosing loop. */ record ContinueStatement( int line, int col, List 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 catchClauses, int line, int col, List 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 leadingComments ) implements Statement { }