Unparsing definitions describe textual representations of terms. The definitions describe a tree walk over terms by associating unparsing rules with patterns. For the collection of unparsing definitions Kimwitu generates a function unparse_phylum for each phylum. The patterns are the same patterns as can occur in rewrite definitions and with-statements. An unparsing rule contains a list of unparse views and a list of unparse items. We'll discuss the views later. An unparse item defines an action for an unparse_phylum function and can be any of the following.
In the case of overlapping patterns , the most specific match is preferred. This is used in the example for the introduction of list element separators, see the last line of the example. The number of separators is one less than the number of list elements. For each operator there is always a default pattern, in case none of the patterns match. The unparsing rule associated with this default pattern unparses all its subphyla.
Plus(e1, e2) -> [ : e1"+"
e2 ]; Minus(e1, e2) -> [ : e1"-"
e2 ]; Neg(e1) -> [ :"-"
e1 ]; Zero() -> [ :"0"
];
Nilexprlist() -> [ : ]; Consexprlist(ex, Nilexprlist())-> [ : ex ]; Consexprlist(ex, rest) -> [ : ex", "
rest ];
The use of the escaped brackets is illustrated in the example below.
Divideby(e1, e2) -> [ : { if (eq_expr(e2, Zero()) } ${ e1"/ /* <- division by zero -> */"
e2 $} { else } ${ e1"/"
e2 $} ];
The unparse functions have an additional argument of type uview. Unparsing rules can be made specific for a set of unparse views by naming these views between the square open bracket and the colon of an unparsing rule. For example:
An omitted view list defaults to all unparse views. This is equivalent to a view list that only contains the view name base_uview. The type uview is an enumeration type of all view names occurring in the unparsing rules. It always contains the view name base_uview.
Plus(e1 e2) -> [ view1 view2: e1"+"
e2 ];
Views can be declared as in the following example:
Unparse views should be declared. If the termprocessor input contains one or more unparse view declarations it will report errors for all unparse views that are used and not declared. The use of view declarations may help to find typing errors in view names - in term processor input that does not contain view declarations, the misspelling of a view name may just introduce a new view (with the misspelled name).
%uview view1 view2; /* the `%' is part of the keyword */
If several unparse rules share the same left-hand side, they may be combined by grouping the right-hand sides (with seperating commas). If several unparse rules share the same right-hand side, they may be combined by grouping the left-hand sides (with seperating commas). The general form of an unparse rule is shown below:
pattern1, pattern2, ... -> [ v1 v2 ... : ... ], ..., [ vn ... : ... ] ;
The unparse_phylum functions that are generated have three arguments: the term to be unparsed, a (void) function, the printer, to be applied to each string (including string denotations of the predefined phyla) and an argument of type uview, which is passed to the printer function. The C code in the unparsing rules can refer to the latter two arguments directly by the names kc_printer and kc_current_view respectively. The user provides the printer function. The simplest example of such a function and its use is as follows.
void printer(char *s, uview v) { printf("%s"
, s); }
{ /* example of usage */ unparse_exprlist(expression, printer, base_uview); }
There are two features that are notably missing from unparsing rules. A feature for handling list element separators is not necessary, as is shown above. A feature for specifying indentation in the output can be emulated in the printer function. How to do that is explained in Section 4.2.