I think this is the kind of contextual "classification" we have the SyntaxClassifier for.
For example for "let x: Int" "Int" is an identifier token, but the classifier will mark it as 'type-identifier'. In the case of "weak" in your example it will mark it as 'builtin-attribute' classification kind.
In parser, we set the token kind to tok::contextual_keyword for several places such as accessor introducer (get, set, willSet, etc.), #selector, or attribute names for precedencegroup (higherThan etc.). But not for decl modifiers.