The input structure of terms is borrowed from the Synthesizer's Specification Language SSL. An example is the following.
This declares two phyla , or term types, or nonterminals, depending on your viewpoint. Each of these denotes a set of terms. As shown, there are two ways of constructing a phylum. One is by enumerating its variants, each of which is an operator applied to a list of phyla. It is possible to declare nullary operators, but it is not possible to define phyla that do not have operators. The other way is declaring it as a list phylum. This is effectively equivalent to declaring the following right recursive phylum:
expr: Plus(expr expr) | Minus(expr expr) | Neg(expr) | Zero() ;
exprlist: list expr;
exprlist:Nilexprlist() | Consexprlist(expr exprlist) ;
A list phylum therefore always has an empty list constructor, and a prefix operator. The advantage of a list declaration, apart from its brevity, is that it instructs the system to generate additional, list-specific, functions.
There are a number of predefined phyla, among them are casestring and nocasestring for case-sensitive and case-insensitive character strings respectively. The full list of predefined phyla is in Section 2.3.
Phyla can be defined more than once, and at each occurrence operators, attributes, and storage options (see below) can be added.
For each phylum, the term processor generates a C data type (a record) with the same name. This is discussed in more detail in Section 2.1.