anchor.diff:        Token start = token;
   
         // Check for extraneous token in the middle of an import statement.
  -      if (token.keyword == null) {
  -        final String nextValue = token.next.stringValue;
  -        if (identical(nextValue, 'if') ||
  -            identical(nextValue, 'deferred') ||
  -            identical(nextValue, 'as') ||
  -            identical(nextValue, 'hide') ||
  -            identical(nextValue, 'show') ||
  -            identical(nextValue, ';')) {
  -          reportRecoverableErrorWithToken(token, fasta.templateUnexpectedToken);
  -          token = token.next;
  -        }
  -      }
  +      token = skipUnexpectedTokenOpt(
  +          token, const <String>['if', 'deferred', 'as', 'hide', 'show', ';']);
   
         // During recovery, clauses are parsed in the same order
         // and generate the same events as in the parseImport method above.
  
positive.code:       token = parseImportPrefixOpt(token, true);
        if (previous != token && optional('deferred', previous)) {
          if (firstDeferredKeyword != null) {
            reportRecoverableError(
                firstDeferredKeyword, fasta.messageDuplicateDeferred);
          } else {
            if (hasPrefix) {
              reportRecoverableError(token, fasta.messageDeferredAfterPrefix);
            }
            firstDeferredKeyword = previous;
          }
  
negative.code:       final String value = token.stringValue;
        if (identical(value, 'deferred')) {
          firstDeferredKeyword ??= token;
        } else if (identical(value, 'as')) {
          hasPrefix = true;
        } else if (identical(value, 'show') || identical(value, 'hide')) {
          hasCombinator = true;
          if (hasPrefix) {
            token = recoveryStart;
  