substitute static method
Replaces #n in body with args and ## with #. Body tokens get
span; argument tokens keep their own.
When argument cutOffArg (0-based) was cut off by the end of input,
the expansion stops right after its first use: the rest of the body
(closing delimiters, \right…) belongs to input that has not arrived.
Implementation
static List<Token> substitute(
List<Token> body,
List<List<Token>> args,
SourceSpan span, {
int? cutOffArg,
}) {
final out = <Token>[];
for (var i = 0; i < body.length; i++) {
final t = body[i];
if (t.kind == TokenKind.character &&
t.text == '#' &&
i + 1 < body.length) {
final n = body[i + 1];
if (n.kind == TokenKind.character && n.text == '#') {
out.add(n.withSpan(span));
i++;
continue;
}
final index = int.tryParse(n.text);
if (n.kind == TokenKind.character &&
index != null &&
index >= 1 &&
index <= 9) {
if (index <= args.length) out.addAll(args[index - 1]);
if (cutOffArg != null && index - 1 == cutOffArg) return out;
i++;
continue;
}
}
out.add(t.withSpan(span));
}
return out;
}