Actually the form "@ID(parameters)" is used in Java, but the host language construct is not embedded inside the parameters of annotations (which are special constructor invocations that will instanciate separate objects, linked to the host language).
They have various use. The oldest form was for hinting the documentation (allowing inserting parsable comments that would be able to build API help files for example). But they evolved to be insertable in many places.
The rule (with which I agree) was to not modify the host language (or modify it a minimum: they are allowed almost anywhere a whitespace is allowed): you can always safely remove the whole annotation and parse the rest of the source code and compile it: all annotations are ignorable if needed and this should not make the program invalid and not working as expected (even if this causes some additional costs in memory or speed when not using them).
As well annotations should be complete bny themselves, not separated in multiple parts, so:
- the concept of using "!" as a prefix, and "{...}" is suffix for parameters is bad, and in fact it just adds various syntaxic ambiguities which are hard to resolve: this would prohibit using "{...}" table constructors in the host language)
- the same is true when using "@ID(..." for the annotation, followed by the host language constructor, and terminated just by a ")" would also be very quirky (dangerous I think)
My opinion is the the non-ambiguous form for annotation is: - "@ID" without parameters, or "@{ID, parameter...}". Then where we can place the whole annotation to attach it to the host language construct if left to specify (but these annotation tags can normally occur only between host tokens where spaces are allowed.
There may however be a need for annotation with long scopes (applying to multiple host-language constructs). Their form could be "@{begin ID, parameter...}" for the begining of scope, and ""@{end ID}" for the end of scope (the additional reindication of the annotation ID may help diagnose non matching end).
Now we can as well use "{}" or "()" or "[]" or "<>" to bracket the annotation ID and its parameters in the same tag (either the opening tag or close tag). The initial bracket is disambiguated by the leading "@", which should be one of the character unassigned in Lua: "@" is perfect for that fine (I don't like using "!" because sooner or later it will become an interesting operator).
Note that annotations have their own namespace: they create a secondary metadata language. Binding the metadata language to a specific recognizer (with its own resource loaders and so on) can also use scopes. For this reason, it would be convenient to support not just the forms "@ID" or "@{ID, parameters...}" or "@{begin ID, parameters...}, or "@{end ID}", but also "@namespace:ID" or "@{namespace:ID, parameters...}" or "@{begin namespace:ID, parameters...}, or "@{end namespace:ID}".
The identifiers without namespaces should be reserved to Lua specification (or there would be a special namespace declaration to specify which namespace is attached to annotation IDs without namespaces). Other metatdata languages will use their own namespaces. Namespaces may be either "strings" (like "org.lua") or suites of IDs separated by dots or columns. I have no preference about it:
If there are syntaxic ambiguities, the simple form "@namespace:ID" or "@ID" should always be equivalent (as a shortcut notation) for the complete annotation tag using delimiting brackets like "@{ID}" or "@{namespace:ID}" (i.e. the "{}" brackets surrounding the annotation typename and its parameters is also correct without parameters).