parseLines method

List<Node> parseLines({
  1. BlockSyntax? parentSyntax,
  2. bool disabledSetextHeading = false,
})

Implementation

List<Node> parseLines({
  BlockSyntax? parentSyntax,
  bool disabledSetextHeading = false,
}) {
  _parentSyntax = parentSyntax;
  _setextHeadingDisabled = disabledSetextHeading;

  final blocks = <Node>[];

  // If the `_pos` does not change before and after `parse()`, never try to
  // parse the line at `_pos` with the same syntax again.
  // For example the `TableSyntax` might not advance the `_pos` in `parse`
  // method, beause of the header row does not match the delimiter row in the
  // number of cells, which makes a table like structure not be recognized.
  BlockSyntax? neverMatch;

  var iterationsWithoutProgress = 0;
  while (!isDone) {
    final positionBefore = _pos;
    for (final syntax in blockSyntaxes) {
      if (neverMatch == syntax) {
        continue;
      }

      if (syntax.canParse(this)) {
        _previousSyntax = _currentSyntax;
        _currentSyntax = syntax;
        final block = syntax.parse(this);
        if (block != null) {
          blocks.add(block);
        }
        neverMatch = _pos != positionBefore ? null : syntax;

        if (block != null ||
            syntax is EmptyBlockSyntax ||
            syntax is LinkReferenceDefinitionSyntax) {
          _start = _pos;
        }

        break;
      }
    }
    // Count the number of iterations without progress.
    // This ensures that we don't have an infinite loop. And if we have an
    // infinite loop, it's easier to gracefully recover from an error, than
    // it is to discover an kill an isolate that's stuck in an infinite loop.
    // Technically, it should be perfectly safe to remove this check
    // But as it's possible to inject custom BlockSyntax implementations and
    // combine existing ones, it is hard to promise that no combination can't
    // trigger an infinite loop
    if (positionBefore == _pos) {
      iterationsWithoutProgress++;
      if (iterationsWithoutProgress > 2) {
        // If this happens we throw an error to avoid having the parser
        // running in an infinite loop. An error is easier to handle.
        // If you see this error in production please file a bug!
        throw AssertionError('BlockParser.parseLines is not advancing');
      }
    } else {
      iterationsWithoutProgress = 0;
    }
  }

  return blocks;
}