Abstract tree in concrete syntax
In Camlp5, one often uses syntax trees. For example, in grammars of
the language (semantic actions), in pretty printing (as patterns), in
optimizing syntax code (typically streams parsers). Syntax trees are
mainly defined by sum types, one for each kind of tree:
"expr
" for expressions, "patt
" for patterns,
"ctyp
" for types, "str_item
" for structure
items, and so on. Each node corresponds to a possible value of this
type.
This syntax tree is defined in the module "MLast
"
provided by Camlp5.
For example, the syntax tree of the statement "if
" can
be written:
MLast.ExIfe loc e1 e2 e3
Where "loc
" is the location in the source, and
"e1
", "e2
" and "e3
" are
respectively the expression after the "if
", the one after
the "then
" and the one after the "else
".
In all programs, it is possible to manipulate syntax trees like that.
However, the quotations systems of Camlp5 provides a quotation kit
named "q_MLast.cmo
". When loaded, it is possible to
represent the syntax trees in concrete syntax. The example above can
be written:
<:expr< if $e1$ then $e2$ else $e3$ >>
The interest of this representation is when one must manipulate complicated syntax trees. An example taken from the Camlp5 sources is this quotation (found in a pattern):
<:expr< match try Some $f$ with [ Stream.Failure -> None ] with [ Some $p$ -> $e$ | _ -> raise (Stream.Error $e2$) ] >>
In abstract syntax, it should have been written:
MLast.ExMat _ (MLast.ExTry _ (MLast.ExApp _ (MLast.ExUid _ "Some") f) [(MLast.PaAcc _ (MLast.PaUid _ "Stream") (MLast.PaUid _ "Failure"), None, MLast.ExUid _ "None")]) [(MLast.PaApp _ (MLast.PaUid _ "Some") p, None, e); (MLast.PaAny _, None, MLast.ExApp _ (MLast.ExLid _ "raise") (MLast.ExApp _ (MLast.ExAcc _ (MLast.ExUid _ "Stream") (MLast.ExUid _ "Error")) e2))]
Which is less readable.
Instead of thinking of "a syntax tree", the programmer has to think of "a piece of program".