forLoopStmt method
Implementation
Stmt forLoopStmt() {
final token = consume(TokenType.kFor, 'Expected "for" keyword.');
loopDepth++;
final List<Token> vars = [];
final List<MathExpr> exprs = [];
// Look-ahead to determine for-loop type.
final next = peek(offset: 1);
if (next.type != TokenType.kAssign) {
// This is an iterator for-loop.
final v = consume(TokenType.kRaw, 'Expected var.');
vars.add(v);
while(peek().type == TokenType.kComma) {
advance();
final v = consume(TokenType.kRaw, 'Expected var after comma.');
vars.add(v);
}
consume(TokenType.kIn, 'Expected "in" before exprs.');
exprs.add(math());
while(peek().type == TokenType.kComma) {
advance();
exprs.add(math());
}
consume(TokenType.kDo, 'Expected "do" before loop body.');
final body = bodyStmt(terminal: TokenType.kEnd);
loopDepth--;
consume(
TokenType.kEnd,
'Expected "end" keyword to terminate for-in loop.',
);
return ForIterLoopStmt(
token,
vars: vars,
exprs: exprs,
body: body,
);
}
/* else next.type == TokenType.kAssign*/
// This is a ranged for-loop.
final control = assignStmt(
RawExpr(
consume(TokenType.kRaw, 'Expected a variable name in assignment.'),
),
);
consume(TokenType.kComma, 'Expected "," before for-loop end term.');
final endExpr = math();
final MathExpr stepExpr;
final pk = peek();
if (pk.type == TokenType.kDo) {
// This is a ranged for-loop with implied step of 1.
stepExpr = NumberLiteral(
Token(TokenType.kNumber, "1", pk.pos),
value: 1.0,
);
} else {
consume(TokenType.kComma, 'Expected "," before for-loop step term.');
stepExpr = math();
}
consume(TokenType.kDo, 'Expected "do" before for-loop body.');
final body = bodyStmt(terminal: TokenType.kEnd);
loopDepth--;
consume(TokenType.kEnd, 'Expected for-loop to terminate with "end".');
return ForLoopStmt(
token,
control: control,
endExpr: endExpr,
stepExpr: stepExpr,
body: body,
);
}