1212import lombok .Getter ;
1313import lombok .RequiredArgsConstructor ;
1414import org .jetbrains .annotations .NotNull ;
15+ import org .jetbrains .annotations .Nullable ;
1516
1617/**
1718 * A for loop.
2021@ RequiredArgsConstructor
2122public class ForLoopStatement extends StatementNode {
2223
23- private final StatementNode initialization ;
24+ private final @ Nullable StatementNode initialization ;
2425 private final ExpressionNode condition ;
25- private final StatementNode iteration ;
26+ private final @ Nullable StatementNode iteration ;
2627 private final StatementNode child ;
2728
2829 @ Override
2930 public void validateTypes (@ NotNull TypesContext context ) {
3031 TypesContext childContext = context .childContext ();
31- initialization .validateTypes (childContext );
32+ if ( initialization != null ) initialization .validateTypes (childContext );
3233 assertExpressionType (condition , CollectionFilter .MONO_ELEMENT , childContext , TypePrimitive .BOOLEAN );
33- iteration .validateTypes (childContext );
34+ if ( iteration != null ) iteration .validateTypes (childContext );
3435 child .validateTypes (childContext );
3536 }
3637
@@ -48,12 +49,27 @@ public void visit(@NotNull StatementVisitor visitor) {
4849 public static @ NotNull ForLoopStatement parseForLoop (@ NotNull TokenStream tokens ) {
4950 tokens .dropOrThrow (TokenType .BRACKET_OPEN );
5051
51- StatementNode init = StatementNode .parseNextStatement (tokens );
52+ // Optional init
53+ StatementNode init ;
54+ if (tokens .peek ().getType () == TokenType .SEMI_COLON ) {
55+ init = null ;
56+ tokens .drop ();
57+ } else {
58+ init = StatementNode .parseNextStatement (tokens );
59+ }
60+
61+ // Required condition
5262 ExpressionNode condition = ExpressionNode .readNextExpression (tokens );
5363 tokens .dropOrThrow (TokenType .SEMI_COLON );
54- StatementNode iterator = StatementNode .parseNextStatement (tokens );
5564
56- tokens .dropOrThrow (TokenType .BRACKET_CLOSE );
65+ // Optional iteration
66+ StatementNode iterator ;
67+ if (tokens .dropOptional (TokenType .BRACKET_CLOSE )) {
68+ iterator = null ;
69+ } else {
70+ iterator = StatementNode .parseNextStatement (tokens );
71+ tokens .dropOrThrow (TokenType .BRACKET_CLOSE );
72+ }
5773 StatementNode child = StatementNode .parseNextStatement (tokens );
5874
5975 return new ForLoopStatement (init , condition , iterator , child );
0 commit comments