anchor.diff:      listener.beginPartOf(token);
       Token partKeyword = token;
       Token ofKeyword = token.next;
  -    token = ofKeyword.next;
  -    bool hasName = token.isIdentifier;
  +    bool hasName = ofKeyword.next.isIdentifier;
       if (hasName) {
  -      token = parseQualified(token, IdentifierContext.partName,
  +      token = parseQualified(ofKeyword.next, IdentifierContext.partName,
                 IdentifierContext.partNameContinuation)
             .next;
       } else {
  -      token = parseLiteralStringOrRecoverExpression(token);
  +      token = parseLiteralStringOrRecoverExpression(ofKeyword);
       }
       token = ensureSemicolon(token);
       listener.endPartOf(partKeyword, ofKeyword, token, hasName);
  
positive.code:     assert(optional('part', token));
      Token partKeyword = token;
      listener.beginPart(token);
      token = parseLiteralStringOrRecoverExpression(token.next);
      token = ensureSemicolon(token);
      listener.endPart(partKeyword, token);
      return token;
  
negative.code:   }
  
    Token parseLiteralStringOrRecoverExpression(Token token) {
      // TODO(brianwilkerson) Return the last consumed token.
      Token next = token.next;
      if (identical(next.kind, STRING_TOKEN)) {
        return parseLiteralString(next).next;
      } else if (next is ErrorToken) {
        return reportErrorToken(next, false);
      } else {
        reportRecoverableErrorWithToken(next, fasta.templateExpectedString);
        return parseRecoverExpression(
            token, fasta.templateExpectedString.withArguments(next));
      }
    }
  
  