This isn't the total answer, but suggestions about possible approaches.
I don't know the specifics, but you can change what gets used to parse the incoming query to something else (probably solrconfig.xml). I don't know which of the available "processors" would do what you want however - or if one is even available with that kind of specific behavior, since I assume you will still want the other "benefits" provided by the BasePredicateProcessor. See next possibility...
An alternative would be to extend BasePredicateProcessor and use your extended class (again, probably solrconfig.xml) Your modified code would leave the "!" alone. This second option will require coding.
Third option is to see if there's an "escape sequence" you could use to modify the query string before you send it in to Solr... Something like an "escape the escape". I don't know if that's possible. It's worth investigating however.
Some possibly useful links for #3
http://lucene.472066.n3.nabble.com/How-do-you-query-for-a-string-containing-a-colon-td481672.html
https://lucene.apache.org/core/2_9_4/queryparsersyntax.html
From the second link:
Lucene supports escaping special characters that are part of the query syntax. The current list special characters are
- && || ! ( ) { } [ ] ^ " ~ * ? : \
To escape these character use the \ before the character. For example to search for (1+1):2 use the query:
\(1\+1\):2