renderBody<I, O> function

BuildBodyResult renderBody<I, O>(
  1. ParserBuilder<I, O> parser,
  2. BuildContext context,
  3. bool hasResult,
  4. String template,
  5. String templateNoResult,
  6. Map<String, String> values, {
  7. List<(ParserBuilder<I, Object?>, bool?)>? parsers,
})

Implementation

BuildBodyResult renderBody<I, O>(
    ParserBuilder<I, O> parser,
    BuildContext context,
    bool hasResult,
    String template,
    String templateNoResult,
    Map<String, String> values,
    {List<(ParserBuilder<I, Object?>, bool?)>? parsers}) {
  parsers ??= parser.getCombinedParsers().toList();
  final allocator = context.localAllocator;
  final result = hasResult ? allocator.allocate() : 'unused';
  values = {...values};
  values['r'] = result;
  for (var i = 0; i < parsers.length; i++) {
    final k = i + 1;
    values['p$k'] = '';
    values['r$k'] = '';
    values['rv$k'] = '';
  }

  final re = RegExp(r'@([_a-zA-Z][_a-zA-Z0-9]*)');
  var source = hasResult ? template : templateNoResult;
  var keys = re.allMatches(source).map((m) => m[1]!).toSet().toList();
  for (final key in keys) {
    if (!values.containsKey(key)) {
      values[key] = allocator.allocate(key);
    }
  }

  for (var i = 0; i < parsers.length; i++) {
    final element = parsers[i];
    final parser = element.$1;
    final mode = element.$2 ?? hasResult;
    final r = parser.build(context, mode);
    final k = i + 1;
    values['p$k'] = r.source;
    values['r$k'] = r.result;
    values['rv$k'] = r.value;
  }

  keys.sort();
  keys = keys.reversed.toList();
  for (final key in keys) {
    final value = values[key]!;
    source = source.replaceAll('@$key', value);
  }

  return BuildBodyResult(
    result: result,
    source: source,
  );
}