External formatting

Centaur provides a way to define Le-Lisp functions that may be referenced within the formatting part of a Ppml rule. We store such functions in a file with the same name as the file containing the Ppml rules, with the suffixe .at, which in our case would be Exp-basic.at. There are several cases where such functions are useful. The first concerns overriding Ppml's automatic treatment of atomic operators. Patterns that recognize atomic operators have the general form:

atomic-operator-name *x -> ...

where *x receives the value of the atomic tree.

To treat our atomic operator variable, we might write the following rule:

variable *x -> [ var-handler(*x)]

The Ppml formatter understands that var-handler is an external function call, so it looks in the Exp-basic.at for the function definition and executes it with the argument *x. Although we may choose any names we like for our functions, the package name must have the following form:

#:pplanguageprettyprinter:atm:myfunction

so that our variable handler must be named:

#:ppExpbasic:atm:var-handler

Since we only want our handler to return the value of *x as a string, the function is simply:

 
   (de #:ppExpbasic:atm:var-handler (x)
       (string x))

We could, of course, perform other operations on x.

Another handy external function that we define allows us to associate tokens and operators. We have named this function getsymbol, which returns a string of characters for a given node name. For instance, we want to associate the token + with the operator plus. The function call:

getsymbol(plus)

within the formatting part of a rule should return the token +.

The function getsymbol, in combination with where allows us to do some fancy maneuvering. The where instruction allows us to limit operator matches to those operators found in a specific set. For example, the pattern:

*x where *x in {plus,minus,prod}

corresponds to any tree node whose operator matches one of the names within the braces. Once the variable *x has been matched, it may be used in the formatting section of the rule. Similarly, the pattern

*x where *x in {plus(*e1,*e2),minus(*e1,*e2)}

not only corresponds to the plus and minus nodes, but allows *e1 and *e2 to be instantiated so that they too may be used in the formatting section of the rule.

Instead of putting a set of operators to the right side of the word in, you can reference a phylum. Thus, the pattern:

*x where *x in EXP

means that *x can be any operator found in the phylum EXP as defined in our abstract syntax.

The following rule demonstrates how where and getsymbol may function together:


   *x where *x in {plus(*e1,*e2), 
                   minus(*e1,*e2),
                   prod(*e1,*e2)} ->
       
     [<hv> *e1 getsymbol(*x) *e2] ;

The variable *x in the Ppml rule instantiates to the operator that matches the current node in the syntax tree. Of course we have to define what these tokens are in the function getsymbol:

 
   (de #:ppExpbasic:atm:getsymbol (tree)
      (selectq ({tree}:operator-name tree)
         (plus "+")
         (prod "*")
         (minus "-")
         (uminus "-")
         (assign ":=")))

If you want to know more about the Vtp functions that act on the tree argument, consult the Vtp manual. All we need to remark here is that first argument of selectq is an operator name.

N.B.


                  



Tutorial