next up previous contents index
Next: Attribute Grammars Up: Cookbook Previous: Structural Induction


Unparsing is in some ways a special case of structural induction. An example of an unparsing definition has been given in Section 1.7. In this subsection we show how a printer function can look that implements indentation. The idea is to define special control sequences to indicate the increment or decrement of indentation. We have chosen these control sequences in accordance with the SSL style. For example, the string

should be printed as follows.

start level1 level1 end

An example of a printer function to do that is the following:   

#include <stdio.h> #include "unpk.h" static indent=0;
void printer(char *s, uview v) { char c; int j;
while(c=*s++) { if (c!='%') putchar(c); else switch(c=*s++) { case 'b': indent-; break; case 't': indent++; break; case 'n': putchar('\n'); for (j=indent; j>0; j-) putchar('\t'); break; case '\0': return; default: putchar(c); }}}

The approach above has an advantage that is at the same time a disadvantage. The printer function also prints casestring and nocasestring terms, which has the advantage that it is possible to dynamically adapt the indentation, simply by assigning an unparsing control sequence to a casestring and nocasestring variable before it will be unparsed. The disadvantage is that one has to be careful that casestring and nocasestring terms do not contain unexpected unparsing control sequences - it may be necessary to quote the `escape character' (the character % in the example above) in casestring and nocasestring terms, unless the `escape character' does not normally appear in the casestring and nocasestring terms.

The following alternative does not have this problem - but neither has it the advantage of `dynamic' control sequences. The idea is to use unparse views instead of control sequences - remember that the printer function was passed both a string and a view argument. Instead of a single string, a number of strings are unparsed, some of which have :view postfix - these strings are only meant to invoke the printer function with a `control view'. To reduce the number of printer calls, the `control views' can be combined with the `normal' strings. This is left as an exercise for the reader. In the following example the printer function recognizes newline characters (' $\backslash$n'):

"start" "":v_right "\nlevel1\nlevel1" "":v_left "\nend"
The printer function:

#include <stdio.h> #include "unpk.h"
void printer(char *s, uview v) { char c; int j; static indent=0; /* static here, or static at file level */
switch(v) { case v_left: indent-; break; case v_right: indent++; break; default: while(c=*s++) { switch(c){ case '\n':putchar(c); for (j=indent; j>0; j-) putchar('\t'); break; default: putchar(c); break; }}}}
If instead of newline characters a newline view would be used (eg. "":v_nl) the printer function could be simplified even more: the case ' $\backslash$n': code in the switch(c) can then be placed as case v_nl: in the switch(v), and the code for the default: case in that switch(v) can be replaced by a simple printf("%s",s); .

next up previous contents index
Next: Attribute Grammars Up: Cookbook Previous: Structural Induction