Tiger Language Reference Manual: Prof. Stephen A. Edwards Columbia University
Tiger Language Reference Manual: Prof. Stephen A. Edwards Columbia University
This document describes the Tiger language defined in Andrew lvalue := expr
Appel’s book Modern Compiler Implementation in Java (Cam- id ( expr-listopt )
bridge University Press, 1998). ( expr-seqopt )
The Tiger language is a small, imperative language with in- type-id { field-listopt }
teger and string variables, arrays, records, and nested functions. type-id [ expr ] of expr
Its syntax resembles some functional languages. if expr then expr
if expr then expr else expr
1 Lexical Aspects
while expr do expr
An identifier is a sequence of letters, digits, and underscores that for id := expr to expr do expr
starts with a letter. Case is significant. break
Whitespace (spaces, tabs, newlines, returns, and formfeeds) let declaration-list in expr-seqopt end
or comments may appear between tokens and is ignored. A com-
ment begins with /* and ends with */. Comments may nest. expr-seq:
An integer constant is a sequence of one or more decimal dig- expr
its (i.e., 0123456789). There are no negative integer constants; expr-seq ; expr
negative numbers may be obtained by negating an integer con- expr-list:
stant using the unary - operator. expr
A string constant is a sequence of zero or more printable char- expr-list , expr
acters, spaces, or escape sequences surrounded by double quotes
". Each escape sequence starts with a backslash \ and stands field-list:
for some sequence of characters. The escape sequences are id = expr
\n Newline field-list , id = expr
\t Tab
\" Double quote 2.1 Lvalues
\\ Backslash
\^c Control-c, where c is one of @A...Z[\]^_. lvalue:
\ddd The character with ASCII code ddd (three deci- id
mal digits) lvalue . id
\· · ·\ Any sequence of whitespace characters (spaces, lvalue [ expr ]
tabs, newlines, returns, and formfeeds) sur- An l-value represents a storage location that can be assigned
rounded by \s is ignored. This allows string con- a value: variables, parameters, fields of records, and elements
stants to span multiple lines by ending and start- of arrays. The elements of an array of size n are indexed by
ing each with a backslash. 0, 1, . . . , n − 1.
The reserved words are array break do else end for
function if in let nil of then to type var while. 2.2 Return values
The punctuation symbols are , : ; ( ) [ ] { } . + - Procedure calls, assignments, if-then, while, break, and some-
* / = <> < <= > >= & | := times if-then-else produce no value and may not appear where a
2 Expressions value is expected (e.g., (a:=b)+c is illegal). A let expression
with nothing between the in and end returns no value.
A Tiger program is a single expr. A sequence of zero or more expressions in parenthesis (e.g.,
expr: (a:=3; b:=a) separated by semicolons are evaluated in order
string-constant and returns the value produced by the final expression, if any.
integer-constant An empty pair of parenthesis () is legal and returns no value.
nil
lvalue 2.3 Record and Array Literals
- expr The expression type-id { field-listopt } (zero or more fields are
expr binary-operator expr allowed) creates a new record instance of type type-id. Field
1
names, expression types, and the order thereof must exactly 2.7 nil
match those of the given record type. The expression nil represents a value that can be assigned to
The expression type-id [ expr ] of expr creates a new array any record type. Accessing a field from a nil-valued record is
of type type-id whose size is given by the expression in brack- a runtime error. Nil must be used in a context were its actual
ets. Initially, the array is filled with elements whose values are record type can be determined, thus the following are legal.
given by the expression after the of. These two expressions are
evaluated in the order they appear. var a : rec := nil a := nil
if a <> nil then ... if a = nil then ...
2.4 Function Calls
function f(p: rec) = f(nil)
A function application is an expression id ( expr-listopt ) with
zero or more comma-separated expression parameters. When a But these are illegal.
function is called, the values of these actual parameters are eval-
uated from left to right and bound to the function’s formal pa- var a := nil if nil = nil then ...
rameters using conventional static scoping rules.
2.8 Flow control
2.5 Operators
The if-then-else expression, written if expr then expr else
The binary operators are + - * / = <> < > <= >= & | expr evaluates the first expression, which must return an integer.
Parentheses group expressions in the usual way. If the result is non-zero, the second expression is evaluated and
A leading minus sign negates an integer expression. becomes the result, otherwise the third expression is evaluated
The binary operators +, -, *, and / require integer operands and becomes the result. Thus, the second and third expressions
and return an integer result. must be of the same type or both not return a value.
The binary operators >, <, >=, and <= compare their operands, The if-then expression, if expr then expr evaluates its first
which may be either both integer or both string and produce expression, which must be an integer. If the result is non-zero, it
the integer 1 if the comparison holds and 0 otherwise. String evaluates the second expression, which must not return a value.
comparison is done using normal ASCII lexicographic order. The if-then expression does not return a value.
The binary operators = and <> can compare any two operands The while-do expression, while expr do expr evaluates its
of the same (non-valueless) type and return either integer 0 or 1. first expression, which must return an integer. If it is non-zero,
Integers are the same if they have the same value. Strings are the the second expression is evaluated, which must not return a
same if they contain the same characters. Two objects of record value, and the while-do expression is evaluated again.
type are the same if they refer to the same record. Two arrays The for expression, for id := expr to expr do expr, eval-
are the same if they refer to the same array. That is, records and uates the first and second expressions, which are loop bounds.
arrays are compared using “reference” or “pointer” equality, not Then, for each integer value between the values of these two ex-
componentwise. pressions (inclusive), the third expression is evaluated with the
The logical operators & and | are lazy logical operators on integer variable named by id bound to the loop index. The scope
integers. They do not evaluate their right argument if evaluating of this variable is limited to the third expression, and may not be
the left determines the result. Zero is considered false; every- assigned to. This expression may not produce a result and is not
thing else is considered true. executed if the loop’s upper bound is less than the lower bound.
Unary minus has the highest precedence followed by * and /, The break expression terminates the innermost enclosing
then + and -, then =, <>, >, <, >=, and <=, then &, then |, then while or for expression that is enclosed in the same func-
finally :=. tion/procedure. The break is illegal outside this.
The +, -, *, and / operators are left associative. The com-
2.9 Let
parison operators do not associate, e.g., a=b=c is erroneous, but
a=(b=c) is legal. The expression let declaration-list in expr-seqopt end evalu-
ates the declarations, binding types, variables, and functions to
2.6 Assignment the scope of the expression sequence, which is a sequence of
The assignment expression lvalue := expr evaluates the ex- zero or more semicolon-separated expressions. The result is that
pression then binds its value to the contents of the lvalue. As- of the last expression, or nothing if there are none.
signment expressions do not produce values, so something like 3 Declarations
a := b := 1 is illegal.
Array and record assignment is by reference, not value. As- declaration-list:
signing an array or record to a variable creates an alias, meaning declaration
later updates of the variable or the value will be reflected in both declaration-list declaration
places. Passing an array or record as an actual argument to a declaration:
function behaves similarly. type-declaration
A record or array value persists from the time it is created to variable-declaration
the termination of the program, even after control has left the function-declaration
scope of its definition.
2
3.1 Types In let . . . function-declaration . . . in expr-seqopt end, the
type-declaration: scope of the function declaration begins at the start of the se-
type type-id = type quence of function declarations to which it belongs (which may
be a singleton) and ends at the end.
type:
type-id 4 Standard Library
{ type-fieldsopt } function print(s : string)
array of type-id Print the string on the standard output.
type-fields: function printi(i : int)
type-field Print the integer on the standard output.
type-fields , type-field function flush()
type-field: Flush the standard output buffer.
id : type-id function getchar() : string
Read and return a character from standard input; return an
Tiger has two predefined types: int and string. New types
empty string at end-of-file.
may be defined and existing types redefined as follows.
The three forms of type refer to a type (creates an alias in a function ord(s : string) : int
declaration), a record with named, typed fields (like a C struct, Return the ASCII value of the first character of s, or −1 if s
different records may reuse field names), and an array. is empty.
Type expressions (e.g., {x:int}, array of ty) create dis- function chr(i : int) : string
tinct types, so two array types with the same base or two records Return a single-character string for ASCII value i. Terminate
with identical fields are different. Type a=b is an alias. program if i is out of range.
A sequence of type declarations (i.e., with no intervening function size(s : string) : int
variable or function declarations) may be mutually recursive. No Return the number of characters in s.
two defined types in such a sequence may have the same name.
function substring(s:string,f:int,n:int):string
Each recursion cycle must pass through a record or array type.
Return the substring of s starting at the character f (first char-
In let . . . type-declaration . . . in expr-seqopt end, the scope
acter is numbered zero) and going for n characters.
of the type declaration begins at the start of the sequence of type
declarations to which it belongs (which may be a singleton) and function concat (s1:string, s2:string):string
ends at the end. Return a new string consisting of s1 followed by s2.
Type names have their own name space. function not(i : int) : int
Return 1 if i is zero, 0 otherwise.
3.2 Variables
function exit(i : int)
variable-declaration: Terminate execution of the program with code i.
var id := expr
var id : type-id := expr 5 Example
let /* The eight queens solver from Appel */
This declares a new variable and its initial value. If the type is var N := 8
not specified, the variable’s type comes from the expression. type intArray = array of int
var row := intArray [ N ] of 0
In let . . . variable-declaration . . . in expr-seqopt end, the
var col := intArray [ N ] of 0
scope of the variable declaration begins just after the declaration var diag1 := intArray [ N+N-1 ] of 0
and ends at the end. A variable lasts throughout its scope. var diag2 := intArray [ N+N-1 ] of 0
Variables and functions share the same name space.
function printboard() =
(for i := 0 to N-1
3.3 Functions
do (for j := 0 to N-1
function-declaration: do print(if col[i]=j then " O" else " .");
print("\n"));
function id ( type-fieldsopt ) = expr print("\n"))
function id ( type-fieldsopt ) : type-id = expr
function try(c:int) =
The first form is a procedure declaration; the second is a func- if c=N then printboard()
tion. Functions return a value of the specified type; procedures else for r := 0 to N-1
are only called for their side-effects. Both forms allow the spec- do if row[r]=0 &
diag1[r+c]=0 & diag2[r+7-c]=0
ification of a list of zero or more typed arguments, which are
then (row[r] := 1; diag1[r+c] := 1;
passed by value. The scope of these arguments is the expr. diag2[r+7-c] := 1; col[c] := r;
The expr is the body of the function or procedure. try(c+1);
A sequence of function declarations (i.e., with no intervening row[r] := 0; diag1[r+c] := 0;
diag2[r+7-c] := 0)
variable or type declarations) may be mutually recursive. No two in try(0) end
functions in such a sequence may have the same name.