# Oberon Abstract Syntax Tree

The unit at [comp/oberon/ast.fs] builds expressions ASTs out of tokenized
[comp/oberon/tok] source. This unit works a lot like [comp/c/ast] and we don't
repeat everything its documentation already states, we focus on the differences.

## Almost pure AST

The "almost pure" principle stays true: symbols aren't evaluated *except* when
there's ambiguity.

### . vs ident.

An ambiguity is whether a "." is made on a module or on a structure. Therefore,
when we encounter a ".", we check if the name to the left corresponds to a
loaded module. If yes, we generate the "ident." AST. If no, we generate the
straight "." AST.

### funcall vs typeguard

When a "(" is encountered in the beginning of an expression, no problem, it's
always a subexpression.

When it's encountered as a postfix operator, it can be two things: a function
call or a typeguard. To differentiate between the two, we recurse AST parsing.
If the result is a "ident" or a "ident.", we perform a lookup to see if it
represents a type. If it does, our AST is a "typeguard", otherwise it's a
"funcall".

## Ambiguous operator symbols

Some operator symbols are ambiguous. In those cases, the symbol is associated
with one of the forms and the other form is given a constant:

-   --> binop    prefix: neg

## AST structure

An AST is a cons [mem/cons] with "car" being an operator ID and "cdr" being its
argument. This describes the cons structure of each operator's argument.

lit       number
ident     string
ident.    (modulename string)
str       zstring
`         string
unary     expr
  neg ^ LEN ADR ORD CHR ODD ABS
binary    (expr expr)
  ~ * / DIV MOD & + - = # < <= > >= IN
  VAL ROR LSL LSR ASR MIN MAX
IS        (modulename-or-0 typename expr)
[]        (designator expr)
.         (string designator)
funcall   ((designator (expr (expr (...)))))
  in other words, a list of ASTs
typeguard (designator ident-or-ident.)
{}        ((expr (expr (expr (...)))))
  in other words, a list of ASTs, but can also contain ".." elements
..        (expr expr)
LEN       expr

## Example usage

  needs comp/oberon/ast
  obtok$
  expr< a*(b+c(42)); read; .ast
  \ prints: (* (ident a) (+ (ident b) (() (ident c) (lit 0000002a))))

## API

expr< ( -- ast )
  Using comp/oberon/tok, parse one expression from the input stream, yielding
  the result as an AST structure as described above.

designator< ( -- ast )
  Same as expr<, but for a designator only.

.ast ( ast -- )
  Print AST in a human-readable form.
