synthesized attribute pp :: Document; inherited attribute env<a> :: Map<String a>;
Attribute declarations begin by indicating whether the attribute is
inherited, give a name for the attribute, and the type of the attribute.
Attributes may also be parameterized in their types.
If they are not parameterized, the angle brackets are omitted:
synthesized attribute name < type variables... > :: type; inherited attribute name < type variables... > :: type;
All type variables that appear in the type must be declared in the type parameter list.
For language processing, nearly all
inherited attributes are better described as
autocopy attribute name :: type;
Autocopy attributes differ from inherited attributes in that some equations are automatically generated. Unless an attribute equation in a production body gives a different rule, the attribute is simply copied from the parent to all children the attribute also occurs on.
Note that currently, autocopy attributes are not permitted to be parameterized. This restriction may or may not be lifted in the future.
Attributes that may have their value influenced by aspects are called collection attributes, and are declared by giving the attribute an associated composition operator using
synthesized attribute errors :: [Message] with ++;
This operator must be either
++ (for lists or strings),
&&, or any user-defined function of type
(a ::= a a).
In practice, this is almost always list append.
See collection attributes.
Some repetitive idioms exist in synthesized attribute specifications that we would like to avoid writing boilerplate for by hand. These attributes fall into various common patterns (“functor”, “monoid”, etc.)
A set of extensions to Silver allows for such attributes to be specially declared, and a new statement
propagate attr1, attr2, ...; to
be used to specify on a production or nonterminal that equations for the attributes should be automatically generated.
See automatic attributes.
Attributes declarations and occurs-on declarations can be merged:
synthesized attribute pp :: String occurs on Expr, Stmt;
However, this should not be used in any circumstance where the nonterminal and the occurs-on declarations can be merged instead. (See the nonterminal documentation for that syntax.) For more reasons that just the stylistic: this syntax is more inflexible for parameterized attributes.
Example: To demonstrate the inflexibility, the following code will raise an error:
synthesized attribute ast<a> :: a occurs on ConcreteExpr;
Because there is no place where we are able to describe what the type parameter of the
astattribute should be on