anchor.diff:      return references;
     }
   
  -  @override
  -  void debugEvent(String name) {
  -    // printEvent('AstBuilder: $name');
  -  }
  -
  -  @override
  -  void discardTypeReplacedWithCommentTypeAssign() {
  -    pop();
  -  }
  -
  -  @override
  -  void addProblem(Message message, int charOffset, int length,
  -      {bool wasHandled: false, List<LocatedMessage> context}) {
  -    if (directives.isEmpty &&
  -        (message.code.analyzerCodes
  -                ?.contains('NON_PART_OF_DIRECTIVE_IN_PART') ??
  -            false)) {
  -      message = messageDirectiveAfterDeclaration;
  -    }
  -    errorReporter.reportMessage(message, charOffset, length);
  -  }
  -
  -  /// Return `true` if [token] is either `null` or is the symbol or keyword
  -  /// [value].
  -  bool optionalOrNull(String value, Token token) {
  -    return token == null || identical(value, token.stringValue);
  +  List<CollectionElement> popCollectionElements(int count) {
  +    final elements = new List<CollectionElement>()..length = count;
  +    for (int index = count - 1; index >= 0; --index) {
  +      var element = pop();
  +      elements[index] = element as CollectionElement;
  +    }
  +    return elements;
  +  }
  +
  +  List popList(int n, List list) {
  +    if (n == 0) return null;
  +    return stack.popList(n, list, null);
     }
   
     List<T> popTypedList<T>(int count, [List<T> list]) {
  
positive.code:     push(forLoopParts);
    }
  
    @override
    void endForControlFlow(Token token) {
      debugEvent("endForControlFlow");
      var entry = pop();
      ForParts forLoopParts = pop();
      Token leftParen = pop();
      Token forToken = pop();
  
      pushForControlFlowInfo(null, forToken, leftParen, forLoopParts, entry);
    }
  
    void pushForControlFlowInfo(Token awaitToken, Token forToken,
        Token leftParenthesis, ForLoopParts forLoopParts, Object entry) {
      if (entry == _invalidCollectionElement) {
        push(_invalidCollectionElement);
      } else if (enableControlFlowCollections) {
        push(ast.forElement(
          awaitKeyword: awaitToken,
          forKeyword: forToken,
          leftParenthesis: leftParenthesis,
          forLoopParts: forLoopParts,
          rightParenthesis: leftParenthesis.endGroup,
          body: entry as CollectionElement,
        ));
      } else {
        handleRecoverableError(
            templateExperimentNotEnabled
                .withArguments(EnableString.control_flow_collections),
            forToken,
            forToken);
        push(_invalidCollectionElement);
      }
    }
  
    @override
    void endForStatement(Token endToken) {
      debugEvent("ForStatement");
      Statement body = pop();
      ForParts forLoopParts = pop();
      Token leftParen = pop();
      Token forToken = pop();
  
      if (enableControlFlowCollections || enableSpreadCollections) {
        push(ast.forStatement2(
          forKeyword: forToken,
          leftParenthesis: leftParen,
          forLoopParts: forLoopParts,
          rightParenthesis: leftParen.endGroup,
          body: body,
        ));
      } else {
        VariableDeclarationList variableList;
        Expression initializer;
        if (forLoopParts is ForPartsWithDeclarations) {
          variableList = forLoopParts.variables;
        } else {
          initializer = (forLoopParts as ForPartsWithExpression).initialization;
        }
        push(ast.forStatement(
            forToken,
            leftParen,
            variableList,
            initializer,
            forLoopParts.leftSeparator,
            forLoopParts.condition,
            forLoopParts.rightSeparator,
            forLoopParts.updaters,
            leftParen?.endGroup,
            body));
      }
    }
  
    void handleLiteralList(
  
negative.code:     }
    }
  
    void doInvocation(
        TypeArgumentList typeArguments, MethodInvocation arguments) {
      Expression receiver = pop();
      if (receiver is SimpleIdentifier) {
        arguments.methodName = receiver;
        if (typeArguments != null) {
          arguments.typeArguments = typeArguments;
        }
        push(arguments);
      } else {
        push(ast.functionExpressionInvocation(
            receiver, typeArguments, arguments.argumentList));
      }
    }
  
    void doPropertyGet() {}
  
    void endArguments(int count, Token leftParenthesis, Token rightParenthesis) {
      assert(optional('(', leftParenthesis));
      assert(optional(')', rightParenthesis));
      debugEvent("Arguments");
  
      List<Expression> expressions = popTypedList(count);
      ArgumentList arguments =
          ast.argumentList(leftParenthesis, expressions, rightParenthesis);
      push(ast.methodInvocation(null, null, null, null, arguments));
    }
  
    @override
    void endAssert(Token assertKeyword, Assert kind, Token leftParenthesis,
        Token comma, Token semicolon) {
      assert(optional('assert', assertKeyword));
      assert(optional('(', leftParenthesis));
      assert(optionalOrNull(',', comma));
      assert(kind != Assert.Statement || optionalOrNull(';', semicolon));
      debugEvent("Assert");
  
      Expression message = popIfNotNull(comma);
      Expression condition = pop();
      switch (kind) {
        case Assert.Expression:
          // The parser has already reported an error indicating that assert
          // cannot be used in an expression. Insert a placeholder.
          List<Expression> arguments = <Expression>[condition];
          if (message != null) {
            arguments.add(message);
          }
          push(ast.functionExpressionInvocation(
              ast.simpleIdentifier(assertKeyword),
              null,
              ast.argumentList(
                  leftParenthesis, arguments, leftParenthesis?.endGroup)));
          break;
        case Assert.Initializer:
          push(ast.assertInitializer(assertKeyword, leftParenthesis, condition,
              comma, message, leftParenthesis?.endGroup));
          break;
        case Assert.Statement:
          push(ast.assertStatement(assertKeyword, leftParenthesis, condition,
              comma, message, leftParenthesis?.endGroup, semicolon));
          break;
      }
    }
  
    void endAwaitExpression(Token awaitKeyword, Token endToken) {
      assert(optional('await', awaitKeyword));
      debugEvent("AwaitExpression");
  
      push(ast.awaitExpression(awaitKeyword, pop()));
    }
  
    @override
    void endBinaryExpression(Token operatorToken) {
      assert(operatorToken.isOperator ||
          optional('.', operatorToken) ||
          optional('?.', operatorToken) ||
          optional('..', operatorToken));
      debugEvent("BinaryExpression");
  
      if (identical(".", operatorToken.stringValue) ||
          identical("?.", operatorToken.stringValue) ||
          identical("..", operatorToken.stringValue)) {
        doDotExpression(operatorToken);
      } else {
        Expression right = pop();
        Expression left = pop();
        reportErrorIfSuper(right);
        push(ast.binaryExpression(left, operatorToken, right));
      }
    }
  
    void endBlock(int count, Token leftBracket, Token rightBracket) {
      assert(optional('{', leftBracket));
      assert(optional('}', rightBracket));
      debugEvent("Block");
  
      List<Statement> statements = popTypedList(count) ?? <Statement>[];
      push(ast.block(leftBracket, statements, rightBracket));
    }
  
    void endBlockFunctionBody(int count, Token leftBracket, Token rightBracket) {
      assert(optional('{', leftBracket));
      assert(optional('}', rightBracket));
      debugEvent("BlockFunctionBody");
  
      List<Statement> statements = popTypedList(count);
      Block block = ast.block(leftBracket, statements, rightBracket);
      Token star = pop();
      Token asyncKeyword = pop();
      if (parseFunctionBodies) {
        push(ast.blockFunctionBody(asyncKeyword, star, block));
      } else {
        // TODO(danrubel): Skip the block rather than parsing it.
        push(ast.emptyFunctionBody(
            new SyntheticToken(TokenType.SEMICOLON, leftBracket.charOffset)));
      }
    }
  
    void endCascade() {
      debugEvent("Cascade");
  
      Expression expression = pop();
      CascadeExpression receiver = pop();
      pop(); // Token.
      receiver.cascadeSections.add(expression);
      push(receiver);
    }
  
    @override
    void endClassDeclaration(Token beginToken, Token endToken) {
      debugEvent("ClassDeclaration");
      classDeclaration = null;
    }
  
    @override
    void endClassOrMixinBody(
        int memberCount, Token leftBracket, Token rightBracket) {
      assert(optional('{', leftBracket));
      assert(optional('}', rightBracket));
      debugEvent("ClassOrMixinBody");
  
      ClassOrMixinDeclarationImpl declaration =
          classDeclaration ?? mixinDeclaration;
      declaration.leftBracket = leftBracket;
      declaration.rightBracket = rightBracket;
    }
  
    @override
    void endCombinators(int count) {
      debugEvent("Combinators");
      push(popTypedList<Combinator>(count) ?? NullValue.Combinators);
    }
  
    @override
    void endCompilationUnit(int count, Token endToken) {
      debugEvent("CompilationUnit");
  
      Token beginToken = pop();
      checkEmpty(endToken.charOffset);
  
      push(ast.compilationUnit(
          beginToken, scriptTag, directives, declarations, endToken));
    }
  
    void endConditionalExpression(Token question, Token colon) {
      assert(optional('?', question));
      assert(optional(':', colon));
      debugEvent("ConditionalExpression");
  
      Expression elseExpression = pop();
      Expression thenExpression = pop();
      Expression condition = pop();
      reportErrorIfSuper(elseExpression);
      reportErrorIfSuper(thenExpression);
      push(ast.conditionalExpression(
          condition, question, thenExpression, colon, elseExpression));
    }
  
    void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
      assert(optional('if', ifKeyword));
      assert(optionalOrNull('(', leftParen));
      assert(optionalOrNull('==', equalSign));
      debugEvent("ConditionalUri");
  
      StringLiteral libraryUri = pop();
      StringLiteral value = popIfNotNull(equalSign);
      if (value is StringInterpolation) {
        for (var child in value.childEntities) {
          if (child is InterpolationExpression) {
            // This error is reported in OutlineBuilder.endLiteralString
            handleRecoverableError(
                messageInterpolationInUri, child.beginToken, child.endToken);
            break;
          }
        }
      }
      DottedName name = pop();
      push(ast.configuration(ifKeyword, leftParen, name, equalSign, value,
          leftParen?.endGroup, libraryUri));
    }
  
    @override
    void endConditionalUris(int count) {
      debugEvent("ConditionalUris");
  
      push(popTypedList<Configuration>(count) ?? NullValue.ConditionalUris);
    }
  
    @override
    void endConstExpression(Token constKeyword) {
      assert(optional('const', constKeyword));
      debugEvent("ConstExpression");
  
      _handleInstanceCreation(constKeyword);
    }
  
    @override
    void endConstLiteral(Token token) {
      debugEvent("endConstLiteral");
    }
  
    @override
    void endConstructorReference(
        Token start, Token periodBeforeName, Token endToken) {
      assert(optionalOrNull('.', periodBeforeName));
      debugEvent("ConstructorReference");
  
      SimpleIdentifier constructorName = pop();
      TypeArgumentList typeArguments = pop();
      Identifier typeNameIdentifier = pop();
      push(ast.constructorName(ast.typeName(typeNameIdentifier, typeArguments),
          periodBeforeName, constructorName));
    }
  
    @override
    void endDoWhileStatement(
        Token doKeyword, Token whileKeyword, Token semicolon) {
      assert(optional('do', doKeyword));
      assert(optional('while', whileKeyword));
      assert(optional(';', semicolon));
      debugEvent("DoWhileStatement");
  
      ParenthesizedExpression condition = pop();
      Statement body = pop();
      push(ast.doStatement(
          doKeyword,
          body,
          whileKeyword,
          condition.leftParenthesis,
          condition.expression,
          condition.rightParenthesis,
          semicolon));
    }
  
    @override
    void endDoWhileStatementBody(Token token) {
      debugEvent("endDoWhileStatementBody");
    }
  
    @override
    void endElseStatement(Token token) {
      debugEvent("endElseStatement");
    }
  
    @override
    void endEnum(Token enumKeyword, Token leftBrace, int count) {
      assert(optional('enum', enumKeyword));
      assert(optional('{', leftBrace));
      debugEvent("Enum");
  
      List<EnumConstantDeclaration> constants = popTypedList(count);
      SimpleIdentifier name = pop();
      List<Annotation> metadata = pop();
      Comment comment = _findComment(metadata, enumKeyword);
      declarations.add(ast.enumDeclaration(comment, metadata, enumKeyword, name,
          leftBrace, constants, leftBrace?.endGroup));
    }
  
    void endExport(Token exportKeyword, Token semicolon) {
      assert(optional('export', exportKeyword));
      assert(optional(';', semicolon));
      debugEvent("Export");
  
      List<Combinator> combinators = pop();
      List<Configuration> configurations = pop();
      StringLiteral uri = pop();
      List<Annotation> metadata = pop();
      Comment comment = _findComment(metadata, exportKeyword);
      directives.add(ast.exportDirective(comment, metadata, exportKeyword, uri,
          configurations, combinators, semicolon));
    }
  
    @override
    void endFactoryMethod(
        Token beginToken, Token factoryKeyword, Token endToken) {
      assert(optional('factory', factoryKeyword));
      assert(optional(';', endToken) || optional('}', endToken));
      debugEvent("FactoryMethod");
  
      FunctionBody body;
      Token separator;
      ConstructorName redirectedConstructor;
      Object bodyObject = pop();
      if (bodyObject is FunctionBody) {
        body = bodyObject;
      } else if (bodyObject is _RedirectingFactoryBody) {
        separator = bodyObject.equalToken;
        redirectedConstructor = bodyObject.constructorName;
        body = ast.emptyFunctionBody(endToken);
      } else {
        unhandled("${bodyObject.runtimeType}", "bodyObject",
            beginToken.charOffset, uri);
      }
  
      FormalParameterList parameters = pop();
      TypeParameterList typeParameters = pop();
      Object constructorName = pop();
      _Modifiers modifiers = pop();
      List<Annotation> metadata = pop();
      Comment comment = _findComment(metadata, beginToken);
  
      assert(parameters != null);
  
      if (typeParameters != null) {
        // TODO(danrubel): Update OutlineBuilder to report this error message.
        handleRecoverableError(messageConstructorWithTypeParameters,
            typeParameters.beginToken, typeParameters.endToken);
      }
  
      // Decompose the preliminary ConstructorName into the type name and
      // the actual constructor name.
      SimpleIdentifier returnType;
      Token period;
      SimpleIdentifier name;
      Identifier typeName = constructorName;
      if (typeName is SimpleIdentifier) {
        returnType = typeName;
      } else if (typeName is PrefixedIdentifier) {
        returnType = typeName.prefix;
        period = typeName.period;
        name =
            ast.simpleIdentifier(typeName.identifier.token, isDeclaration: true);
      }
  
      (classDeclaration ?? mixinDeclaration).members.add(
          ast.constructorDeclaration(
              comment,
              metadata,
              modifiers?.externalKeyword,
              modifiers?.finalConstOrVarKeyword,
              factoryKeyword,
              ast.simpleIdentifier(returnType.token),
              period,
              name,
              parameters,
              separator,
              null,
              redirectedConstructor,
              body));
    }
  
    void endFieldInitializer(Token assignment, Token token) {
      assert(optional('=', assignment));
      debugEvent("FieldInitializer");
  
      Expression initializer = pop();
      SimpleIdentifier name = pop();
      push(_makeVariableDeclaration(name, assignment, initializer));
    }
  
    @override
    void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
        int count, Token beginToken, Token semicolon) {
      assert(optional(';', semicolon));
      debugEvent("Fields");
  
      List<VariableDeclaration> variables = popTypedList(count);
      TypeAnnotation type = pop();
      _Modifiers modifiers = new _Modifiers()
        ..staticKeyword = staticToken
        ..covariantKeyword = covariantToken
        ..finalConstOrVarKeyword = varFinalOrConst;
      var variableList = ast.variableDeclarationList(
          null, null, modifiers?.finalConstOrVarKeyword, type, variables);
      Token covariantKeyword = modifiers?.covariantKeyword;
      List<Annotation> metadata = pop();
      Comment comment = _findComment(metadata, beginToken);
      (classDeclaration ?? mixinDeclaration).members.add(ast.fieldDeclaration2(
          comment: comment,
          metadata: metadata,
          covariantKeyword: covariantKeyword,
          staticKeyword: modifiers?.staticKeyword,
          fieldList: variableList,
          semicolon: semicolon));
    }
  
    @override
    void endForControlFlow(Token token) {
      debugEvent("endForControlFlow");
      var entry = pop();
      ForParts forLoopParts = pop();
      Token leftParen = pop();
      Token forToken = pop();
  
      pushForControlFlowInfo(null, forToken, leftParen, forLoopParts, entry);
    }
  
    @override
    void endForIn(Token endToken) {
      debugEvent("ForInExpression");
  
      Statement body = pop();
      ForEachParts forLoopParts = pop();
      Token leftParenthesis = pop();
      Token forToken = pop();
      Token awaitToken = pop(NullValue.AwaitToken);
  
      if (enableControlFlowCollections || enableSpreadCollections) {
        push(ast.forStatement2(
          awaitKeyword: awaitToken,
          forKeyword: forToken,
          leftParenthesis: leftParenthesis,
          forLoopParts: forLoopParts,
          rightParenthesis: leftParenthesis.endGroup,
          body: body,
        ));
      } else if (forLoopParts is ForEachPartsWithDeclaration) {
        push(ast.forEachStatementWithDeclaration(
            awaitToken,
            forToken,
            leftParenthesis,
            forLoopParts.loopVariable,
            forLoopParts.inKeyword,
            forLoopParts.iterable,
            leftParenthesis?.endGroup,
            body));
      } else {
        push(ast.forEachStatementWithReference(
            awaitToken,
            forToken,
            leftParenthesis,
            (forLoopParts as ForEachPartsWithIdentifier).identifier,
            forLoopParts.inKeyword,
            forLoopParts.iterable,
            leftParenthesis?.endGroup,
            body));
      }
    }
  
    @override
    void endForInBody(Token token) {
      debugEvent("endForInBody");
    }
  
    @override
    void endForInControlFlow(Token token) {
      debugEvent("endForInControlFlow");
  
      var entry = pop();
      ForEachParts forLoopParts = pop();
      Token leftParenthesis = pop();
      Token forToken = pop();
      Token awaitToken = pop(NullValue.AwaitToken);
  
      pushForControlFlowInfo(
          awaitToken, forToken, leftParenthesis, forLoopParts, entry);
    }
  
    @override
    void endForInExpression(Token token) {
      debugEvent("ForInExpression");
    }
  
    @override
    void endFormalParameter(Token thisKeyword, Token periodAfterThis,
        Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
      assert(optionalOrNull('this', thisKeyword));
      assert(thisKeyword == null
          ? periodAfterThis == null
          : optional('.', periodAfterThis));
      debugEvent("FormalParameter");
  
      _ParameterDefaultValue defaultValue = pop();
      SimpleIdentifier name = pop();
      AstNode typeOrFunctionTypedParameter = pop();
      _Modifiers modifiers = pop();
      Token keyword = modifiers?.finalConstOrVarKeyword;
      Token covariantKeyword = modifiers?.covariantKeyword;
      List<Annotation> metadata = pop();
      Comment comment = _findComment(metadata,
          thisKeyword ?? typeOrFunctionTypedParameter?.beginToken ?? nameToken);
  
      NormalFormalParameter node;
      if (typeOrFunctionTypedParameter is FunctionTypedFormalParameter) {
        // This is a temporary AST node that was constructed in
        // [endFunctionTypedFormalParameter]. We now deconstruct it and create
        // the final AST node.
        if (thisKeyword == null) {
          node = ast.functionTypedFormalParameter2(
              identifier: name,
              comment: comment,
              metadata: metadata,
              covariantKeyword: covariantKeyword,
              returnType: typeOrFunctionTypedParameter.returnType,
              typeParameters: typeOrFunctionTypedParameter.typeParameters,
              parameters: typeOrFunctionTypedParameter.parameters);
        } else {
          node = ast.fieldFormalParameter2(
              identifier: name,
              comment: comment,
              metadata: metadata,
              covariantKeyword: covariantKeyword,
              type: typeOrFunctionTypedParameter.returnType,
              thisKeyword: thisKeyword,
              period: periodAfterThis,
              typeParameters: typeOrFunctionTypedParameter.typeParameters,
              parameters: typeOrFunctionTypedParameter.parameters);
        }
      } else {
        TypeAnnotation type = typeOrFunctionTypedParameter;
        if (thisKeyword == null) {
          node = ast.simpleFormalParameter2(
              comment: comment,
              metadata: metadata,
              covariantKeyword: covariantKeyword,
              keyword: keyword,
              type: type,
              identifier: name);
        } else {
          node = ast.fieldFormalParameter2(
              comment: comment,
              metadata: metadata,
              covariantKeyword: covariantKeyword,
              keyword: keyword,
              type: type,
              thisKeyword: thisKeyword,
              period: thisKeyword.next,
              identifier: name);
        }
      }
  
      ParameterKind analyzerKind = _toAnalyzerParameterKind(kind);
      FormalParameter parameter = node;
      if (analyzerKind != ParameterKind.REQUIRED) {
        parameter = ast.defaultFormalParameter(
            node, analyzerKind, defaultValue?.separator, defaultValue?.value);
      } else if (defaultValue != null) {
        // An error is reported if a required parameter has a default value.
        // Record it as named parameter for recovery.
        parameter = ast.defaultFormalParameter(node, ParameterKind.NAMED,
            defaultValue.separator, defaultValue.value);
      }
      localDeclarations[nameToken.offset] = parameter;
      push(parameter);
    }
  
    @override
    void endFormalParameterDefaultValueExpression() {
      debugEvent("FormalParameterDefaultValueExpression");
    }
  
    void endFormalParameters(
        int count, Token leftParen, Token rightParen, MemberKind kind) {
      assert(optional('(', leftParen));
      assert(optional(')', rightParen));
      debugEvent("FormalParameters");
  
      List<Object> rawParameters = popTypedList(count) ?? const <Object>[];
      List<FormalParameter> parameters = <FormalParameter>[];
      Token leftDelimiter;
      Token rightDelimiter;
      for (Object raw in rawParameters) {
        if (raw is _OptionalFormalParameters) {
          parameters.addAll(raw.parameters ?? const <FormalParameter>[]);
          leftDelimiter = raw.leftDelimiter;
          rightDelimiter = raw.rightDelimiter;
        } else {
          parameters.add(raw as FormalParameter);
        }
      }
      push(ast.formalParameterList(
          leftParen, parameters, leftDelimiter, rightDelimiter, rightParen));
    }
  
    @override
    void endForStatement(Token endToken) {
      debugEvent("ForStatement");
      Statement body = pop();
      ForParts forLoopParts = pop();
      Token leftParen = pop();
      Token forToken = pop();
  
      if (enableControlFlowCollections || enableSpreadCollections) {
        push(ast.forStatement2(
          forKeyword: forToken,
          leftParenthesis: leftParen,
          forLoopParts: forLoopParts,
          rightParenthesis: leftParen.endGroup,
          body: body,
        ));
      } else {
        VariableDeclarationList variableList;
        Expression initializer;
        if (forLoopParts is ForPartsWithDeclarations) {
          variableList = forLoopParts.variables;
        } else {
          initializer = (forLoopParts as ForPartsWithExpression).initialization;
        }
        push(ast.forStatement(
            forToken,
            leftParen,
            variableList,
            initializer,
            forLoopParts.leftSeparator,
            forLoopParts.condition,
            forLoopParts.rightSeparator,
            forLoopParts.updaters,
            leftParen?.endGroup,
            body));
      }
    }
  
    @override
    void endForStatementBody(Token token) {
      debugEvent("endForStatementBody");
    }
  
    @override
    void endFunctionExpression(Token beginToken, Token token) {
      // TODO(paulberry): set up scopes properly to resolve parameters and type
      // variables.  Note that this is tricky due to the handling of initializers
      // in constructors, so the logic should be shared with BodyBuilder as much
      // as possible.
      debugEvent("FunctionExpression");
  
      FunctionBody body = pop();
      FormalParameterList parameters = pop();
      TypeParameterList typeParameters = pop();
      push(ast.functionExpression(typeParameters, parameters, body));
    }
  
    @override
    void endFunctionName(Token beginToken, Token token) {
      debugEvent("FunctionName");
    }
  
    @override
    void endFunctionType(Token functionToken, Token questionMark) {
      assert(optional('Function', functionToken));
      debugEvent("FunctionType");
      if (!enableNonNullable) {
        reportErrorIfNullableType(questionMark);
      }
  
      FormalParameterList parameters = pop();
      TypeAnnotation returnType = pop();
      TypeParameterList typeParameters = pop();
      push(ast.genericFunctionType(
          returnType, functionToken, typeParameters, parameters,
          question: questionMark));
    }
  
    @override
    void endFunctionTypeAlias(
        Token typedefKeyword, Token equals, Token semicolon) {
      assert(optional('typedef', typedefKeyword));
      assert(optionalOrNull('=', equals));
      assert(optional(';', semicolon));
      debugEvent("FunctionTypeAlias");
  
      if (equals == null) {
        FormalParameterList parameters = pop();
        TypeParameterList typeParameters = pop();
        SimpleIdentifier name = pop();
        TypeAnnotation returnType = pop();
        List<Annotation> metadata = pop();
        Comment comment = _findComment(metadata, typedefKeyword);
        declarations.add(ast.functionTypeAlias(comment, metadata, typedefKeyword,
            returnType, name, typeParameters, parameters, semicolon));
      } else {
        TypeAnnotation type = pop();
        TypeParameterList templateParameters = pop();
        SimpleIdentifier name = pop();
        List<Annotation> metadata = pop();
        Comment comment = _findComment(metadata, typedefKeyword);
        if (type is! GenericFunctionType) {
          // This error is also reported in the OutlineBuilder.
          handleRecoverableError(messageTypedefNotFunction, equals, equals);
          type = null;
        }
        declarations.add(ast.genericTypeAlias(
            comment,
            metadata,
            typedefKeyword,
            name,
            templateParameters,
            equals,
            type as GenericFunctionType,
            semicolon));
      }
    }
  
    @override
    void endFunctionTypedFormalParameter(Token nameToken) {
      debugEvent("FunctionTypedFormalParameter");
  
      FormalParameterList formalParameters = pop();
      TypeAnnotation returnType = pop();
      TypeParameterList typeParameters = pop();
  
      // Create a temporary formal parameter that will be dissected later in
      // [endFormalParameter].
      push(ast.functionTypedFormalParameter2(
          identifier: null,
          returnType: returnType,
          typeParameters: typeParameters,
          parameters: formalParameters));
    }
  
    @override
    void endHide(Token hideKeyword) {
      assert(optional('hide', hideKeyword));
      debugEvent("Hide");
  
      List<SimpleIdentifier> hiddenNames = pop();
      push(ast.hideCombinator(hideKeyword, hiddenNames));
    }
  
    @override
    void endIfControlFlow(Token token) {
      CollectionElement thenElement = pop();
      ParenthesizedExpression condition = pop();
      Token ifToken = pop();
      pushIfControlFlowInfo(ifToken, condition, thenElement, null, null);
    }
  
    @override
    void endIfElseControlFlow(Token token) {
      CollectionElement elseElement = pop();
      Token elseToken = pop();
      CollectionElement thenElement = pop();
      ParenthesizedExpression condition = pop();
      Token ifToken = pop();
      pushIfControlFlowInfo(
          ifToken, condition, thenElement, elseToken, elseElement);
    }
  
    void endIfStatement(Token ifToken, Token elseToken) {
  