next up previous contents index
Next: Including Other Definitions Up: Input Previous: Rewrite Definitions

Unparsing Definitions

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.

"a string"
Each string denotation will be printed as such.
{ ...}
Between curly brackets, arbitrary C code can be used, in which the pattern variables and $0 (which is a reference to the entire left hand term) can be used. This C text is inserted in the unparse function. The C text can contain curly brackets, nested in matching pairs. If a non matching bracket needs to be included it can be escaped with a $, e.g. ${ and $}.
An occurrence of a pattern variable is translated into an invocation of the unparse function for the phylum of the pattern variable.
variable $\rightarrow$attribute
An occurrence of an attribute is translated into an invocation of the unparse function for the phylum or type of the attribute. An attribute of an attribute is denoted by variable $\rightarrow$attribute $\rightarrow$attribute etc. The unparsing function for a type that is not a phylum has to be provided by the user in a separate piece of C code.
A prefixed cast has the effect that the unparse function for that type will be called for the variable (or its attribute). This is useful for the unparsing of non-pattern variables, eg. variables that are defined in C code.
An appended unparse view name (see below) has the effect that the unparse function for the variable will be called with this view rather than the current view. This can also be done with attributes, casted variables and their attributes, and even strings.
${ unparse items $}
A list of unparse items enclosed by escaped bracket is translated into a curly open-bracket followed by the translation of the unparse items followed by a curly close-bracket.
How an unparse item is actually printed will be discussed later. First an example, containing strings and pattern variables. 

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 ];
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.

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:

Plus(e1 e2) -> [ view1 view2: e1 "+" e2 ];
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.

Views can be declared as in the following example:  

%uview view1 view2; /* the `%' is part of the keyword */
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).

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.

next up previous contents index
Next: Including Other Definitions Up: Input Previous: Rewrite Definitions