TC-2 Pretty-Printing Samples
Warning
The ASTs outputed below are generated with the -X
option to
avoid useless repetition.
Do not forget to test your pretty-printer without the option.
print("Hello, World!")
$ tc -A hello-world.tig
/* == Abstract Syntax Tree. == */
primitive print(string : string)
primitive print_err(string : string)
primitive print_int(int : int)
primitive flush()
primitive getchar() : string
primitive ord(string : string) : int
primitive chr(code : int) : string
primitive size(string : string) : int
primitive streq(s1 : string, s2 : string) : int
primitive strcmp(s1 : string, s2 : string) : int
primitive substring(string : string, start : int, length : int) : string
primitive concat(fst : string, snd : string) : string
primitive not(boolean : int) : int
primitive exit(status : int)
function _main() =
(
print("Hello, World!");
()
)
$ echo $?
0
$ tc -XA hello-world.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
print("Hello, World!");
()
)
$ echo $?
0
The parser builds ASTs that can be output by a pretty-printing module.
/* Define a recursive function. */
let
/* Calculate n!. */
function fact (n : int) : int =
if n = 0
then 1
else n * fact (n - 1)
in
fact (10)
end
$ tc -XA simple-fact.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
let
function fact(n : int) : int =
if n = 0
then 1
else n * fact(n - 1)
in
fact(10)
end;
()
)
$ echo $?
0
Warning
The pretty-printed output must be valid and equivalent.
As a result, anything output by tc -A
is valid and equivalent
to what tc -A | tc -A -
displays!
$ tc -XA hello-world.tig | tc -XA -
/* == Abstract Syntax Tree. == */
function _main() =
(
print("Hello, World!");
()
)
$ echo $?
0
Note
Valid means that any Tiger compiler must be able to parse with success your output.
To label your output, you should use comments: /* == Abstract... */
.
Pay attention to special characters too.
print("\"\x45\x50ITA\"\n")
$ tc -XA string-escapes.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
print("\"EPITA\"\n");
()
)
$ echo $?
0
Warning
The AST representation induces the precedence of its nodes, so it has no needs to track input parenthesis. However, to explicit the precedences thought the pretty-printer, you should wrap certain syntagma into parenthesis.
To be sure and don’t miss any, place them every time at the right spots; even if sometimes it bloats a bit the output.
(if (1 + 2) * 3 / 4
then 5 * 6
else 7 + 8) - 9 / 10
$ tc -XA precedence.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
(if (1 + 2) * 3 / 4
then 5 * 6
else 7 + 8) - 9 / 10;
()
)
$ echo $?
0
$ tc --explicit-wrapping -XA precedence.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
((if (((1 + 2) * 3) / 4)
then (5 * 6)
else (7 + 8)) - (9 / 10));
()
)
$ echo $?
0
Note
Equivalent means that, except for syntactic sugar, the output and the input are equal.
Syntactic sugar refers to &
, |
, unary -
, etc.
1 = 1 & 2 = 2
$ tc -XA 1s-and-2s.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
if 1 = 1
then (2 = 2) <> 0
else 0;
()
)
$ echo $?
0
$ tc -XA 1s-and-2s.tig > output.tig
$ echo $?
0
$ tc -XA output.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
if 1 = 1
then (2 = 2) <> 0
else 0;
()
)
$ echo $?
0
Beware that for
loops are encoded using a ast::VarDec
:
do not display the var
.
for i := 0 to 100 do
(print_int (i))
$ tc -XA for-loop.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
for i := 0 to 100 do
print_int(i);
()
)
$ echo $?
0
Parentheses must not stack for free; you must even remove them as the following example demonstrates.
((((((((((0))))))))))
$ tc -XA parens.tig
/* == Abstract Syntax Tree. == */
function _main() =
(
0;
()
)
$ echo $?
0
Note
This is not a pretty-printer trick: the AST of this program and that of
0
are exactly the same: a single ast::IntExp
.
Objects constructs in Tiger can be pretty-printed when enabled with the
-o/--object
option.
let class B { var a := 42 method m() : int = self.a } var b := new B in b.a := 51 end$ tc -XoA simple-class.tig /* == Abstract Syntax Tree. == */ function _main() = ( let type B = class extends Object { var a := 42 method m() : int = self.a } var b := new B in b.a := 51 end; () ) $ echo $? 0