BASH will not know that you are attempting to assign something. The parser will see varname with no = and treat it as a command name, and then pass = and vardata to it as arguments.
Match tilde, hash or colon special characters that have either a word character or a string-end on each side, you can use this pattern:
(?<!\W)[~#:@?!](?!\W)