HANDBOOK / GENTLE PRIMER / At a Glance /

# Traversal

In this section we show how to process abstract syntax. For this purpose we discuss a calculator which is based on abstract syntax.

The root clause of this specification has the form

    'root' expression(-> X) eval(X -> N) print(N)

where `expression` is defined as in the preceding example. It yields a term `X` of type `Expr`, as defined above.

`eval` is a procedure with one input parameter of type `Expr` and one output parameter of type `INT`. It maps its input value (the abstract syntax of a particular expression) onto the numeric value of this expression.

This mapping is defined by the following rules.

    'action' eval (Expr -> INT)

    'rule' eval(plus(X1, X2) -> N1+N2): eval(X1 -> N1) eval(X2 -> N2)
    'rule' eval(minus(X1, X2) -> N1-N2): eval(X1 -> N1) eval(X2 -> N2)
    'rule' eval(mult(X1, X2) -> N1*N2): eval(X1 -> N1) eval(X2 -> N2)
    'rule' eval(div(X1, X2) -> N1/N2): eval(X1 -> N1) eval(X2 -> N2)
    'rule' eval(neg(X) -> -N): eval(X -> N)
    'rule' eval(num(N) -> N)

Whereas in concrete syntax rules are selected according to the structure of the concrete input, here rules are selected according to the structure of the terms of the abstract syntax. In this example, there is a rule for each alternative of the type `Expr` that specifies how to compute the numerical value from the numerical value of the constituents of the term.

Consider the rule

    'rule' eval(plus(X1, X2) -> N1+N2): eval(X1 -> N1) eval(X2 -> N2)

which is selected if the input term of `eval` has the structure `plus(`S1`,`S2`)` with subterms S1 and S2. The variables `X1` and `X2` are defined as these subterms. The invocations `eval(X1 -> N1)` and `eval(X2 -> N2)` define `N1` and `N2` as the numeric values of the corresponding subterms. These values are then used to compute the output parameter `N1 + N2`.

For example, if the input term is `plus(num(10), mult(num(20), num(30))`, then `X1` is defined as `num(10)` and `X2` is defined as `mult(num(20), num(30))`. The recursive invocations of `eval` then define `N1` as 10 (the numeric value of `X1`) and `N2` as 600 (the numeric value of `X2`). With these values the output parameter of the left-hand side is computed, `N1+N2` yields 610.