substitute static method

List<Token> substitute(
  1. List<Token> body,
  2. List<List<Token>> args,
  3. SourceSpan span, {
  4. int? cutOffArg,
})

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;
}