Professional Documents
Culture Documents
1.
2.
2.
Syntax-directed semantics
Attributes
An attribute is any property of a programming
language construct.
- Typical examples of attributes are:
the data type of a variable, the value of an
expression, the location of a variable in memory,
the object code of a procedure, the number of
significant digits in a number.
- Attribute corresponds to the name of a field of a
structure.
-
Attribute Grammars
10
11
number.val must be
computed prior to
factor.val
12
13
e.g. 345o
128d
128o (x)
16
17
term1.tree = mkOpNode(*,term2.tree,factor.tree)
*
34
(34 3) * 42
42
3
factor.tree =
mkNumNode(number.lexval)
19
Semantic Rules
var-list.dtype = type.dtype
type int
type.dtype = integer
type float
type.dtype = real
var-list1 id , var-list2
id.dtype = var-list1.dtype
var-list2.dtype = var-list1.dtype
var-list id
id.dtype = var-list.dtype
decl
type
(dtype = real)
float
var-list
(dtype = real)
,
id
(x)
(dtype = real)
var-list
(dtype = real)
id
(y)
(dtype = real)
decl
type
(dtype = real)
trivial
dependency
float
var-list
(dtype = real)
,
id
(x)
(dtype = real)
var-list
(dtype = real)
id
(y)
(dtype = real)
26
27
29
30
base is computed in
preorder and val in
postorder
Synthesized Attributes
An attribute a is synthesized if, given a grammar rule
A -> X1 X2 Xn, the only associated attribute equation
with an a on the left-hand side is of the form:
A.a = f (X1.a1 ,.., X1.ak ,.., Xn.a1 ,.., Xn.ak)
e.g., E1 -> E2 + E3
{E1.val = E2.val + E3.val; }
where E.val represents the attribute (numerical value
obtained) for E
An attribute grammar in which all the attributes are
synthesized is called S-attributed grammar.
32
S-attributed
grammar
33
term1.tree = mkOpNode(*,term2.tree,factor.tree)
*
34
42
factor.tree =
mkNumNode(number.lexval)
(34 3) * 42
34
42
3
Inherited Attributes
36
38
L-attributed grammars
39
Parsing
stack
40
Value
stack
41
42
43
Semantic Action
44
46
Symbol Table
47
51
52
53
----------------------------|
----|
|
| scope of x
| minus this |
|
|
----|
|
|
----------------------------
54
55
e.g.
56
float x;
------struct y{ ----|
int x; |
|
int z; | inner context | another context
.
|
|
} ------------
e.g.
float x;
-----struct y { ---|
int x; |
|
int z; | context #3
| context #2
.
|
|
} ----------
58
59
60
Suggested grammar:
(Note: This is a very simple grammar mainly
used for explanation.)
P -> MD;
M -> /* empty string */
D -> D, id
| int id
| float id
D , id
2
int id
int x , y ;
61
(Syntax-directed) Translation
4
1
62
Avoided grammar:
D -> int namelist ; | float namelist ;
namelist -> id, namelist | id
D
int
namelist
1
id
int x ;
64
Why?
When the 'id' is reduced into namelist, we cannot
know the type of 'id' (int or float?) immediately.
Therefore, it is troublesome to enter such type
information into the corresponding field of the 'id' in
the symbol table. Hence, we must use special coding
technique (e.g. linked list keeping the ids name
(pointers to symbol table) to achieve such a purpose.
(* In other words, we need backpatch to chain the
data type.)
Acceptable grammar:
D
-> int intlist ; | float floatlist ;
intlist -> id, intlist | id
floatlist -> id, floatlist | id
65
3
1
2
2
1
66
67
declarations
VAR
var
decl_list
declaration ; decl_list
ID : type declaration ;
x
real
ID : type
y
integer
69
e.g.,
declaration
id_list
type
id_list ,
2
id_list , ID
1
ID
ID
REAL
A unit
In Quadruples:
Operator
73
1. ==> op(1)
2. ==> op(2)
3. ==> goto
4. ==> relopgoto
5. ==> param
5. ==> call
6. ==> =[]
7. ==> []=
8. ==> =&
9. ==> =*
10. ==> *=
Arg1
Arg2
B
B
A
A
P
B
B
B
B
B
B
n
i
i
Result
A
A
L
L
A
A
A
A
A
Example:
D=A+B*C
D = A*B+C
T1 = A * B
T1 = B * C
T2 = T1 + C
T2 = A + T1
D = T2
D = T2
Interpret
this
Operator
=*
=+
=
Arg1
A
T1
T2
Arg2
B
C
Result
T1
T2
D
Arg1
6
9
11
Arg2
7
8
75
0
1
..
..
6
7
8
9
10
11
Result
9
11
10
Interpret
this
attributes
twa
K
..
..
A
B
C
T1 /* compiler generated temporary variable */
D
T2 /* compiler generated temporary variable */
2. Arithmetic Statements
76
A -> id = E
E -> E(1) + E(2)
E -> E(1) - E(2)
E -> E(1) * E(2)
E -> E(1) / E(2)
E -> - E(1)
E -> (E(1))
E -> id
A
id
E
3
id
x=a+b
id
T1 = a + b
x = T1
A -> id = E
{ T = NEWTEMP();
/* NEWTEMP() - a function used to generate a
temporary variable T and save T into symbol
table and return the index value of the symbol
table. */
E.place = T;
/* Ts index value in symbol table is assigned to
E.place */
GEN(E.place = E(1).place + E(2).place); }
T=a+b
E -> - E(1)
{ T = NEWTEMP();
E.place = T;
GEN(E.place = -E(1).place); }
E -> (E(1))
{ E.place = E(1).place; }
E -> id
{ E.place = id.place; }
/*idindexEfield 'place' ; In
implementation id.place refers to the index value
of id in the symbol table. */
E.type = float;
}
else if E(1).type == int and E(2). type == float then
{ U = NEWTEMP();
GEN (U = inttofloat E(1).place);
GEN (T = U floatop E(2).place);
E. type = float;
}
else /* E(1). type == float and E(2). type == int then
{ U = NEWTEMP();
GEN (U = inttofloat E(2).place);
GEN (T = E(1).place floatop U);
E. type = float;
}
}
3. Boolean Expression
M ->
E -> E or M E
| E and M E
| not E
|(E)
| id
| id relop id
81
An example
if p < q || r < s && t < u
x = y + z;
k = m n;
For the above boolean expression the
corresponding contents in the quadruples
are:
82
quadruples
counter = 100
Location
100
101
102
103
104
105
106
107
108
109
...
Three-Address Code
.
E
if p < q goto 106
7
goto 102
E or M E
6
if r < s goto 104
1
2
E and M E
goto 108
id < id
4
if t < u goto 106
3
1.
5. E -> ( E(1) )
{ E.true = E(1).true; E.false = E(1).false;}
6. E -> id
{
E.true = MAKELIST (NEXTQUAD);
E.false = MAKELIST(NEXTQUAD + 1);
GEN (if id.place goto _ );
GEN (goto _);
}
/* MAKELIST ( i ) a function that creates a list containing i, an
index into the array of quadruples, and returns a pointer to the
list it has made. */
/* GEN(x) a function that translates x (a kind of three-addresscode) into quadruple representation. */
E true
id(2).place goto _
21
false
goto _
22
20
88
21
4. Flow-of-Control statements
A. Conditional Statements
S -> if E then S else S
| if E then S
| A
| begin L end
L -> S
|L;S
/* A denotes a general assignment statement
L denotes statement list
S denotes statement
*/
89
90
4. N ->
{
N.next = MAKELIST (NEXTQUAD);
GEN (goto _);
}
20
91
NEXTQUAD
Goto ___
NEXTQUAD = 20
next
20
5. S -> A
{ S.next = MAKELIST ( ); }
/* initialize S.next to an empty list */
6.
7.
92
8.
B. Iterative Statement
S -> while E do S
9. S -> while M(1) E do M(2) S(1)
{
BACKPATCH (E.true, M(2).quad);
BACKPATCH (S(1).next, M(1).quad);
S.next = E.false;
GEN (goto M(1).quad);
}
93
An example:
while (A<B) do if (C<D) then X = Y + Z;
E
Index
100
101
102
103
104
105
106
107
Three-Address Code
..
2
if (A<B) goto 102
goto __ //will be resolved (filling 107) later
if (C<D) goto 104
goto 100
1 If (C<D) then X=Y+Z;
T=Y+Z
3
X=T
4
goto 100
5. Array References
Addressing Array Elements
one-dimension: A[low..high]
two-dimension: A[low1..high1, low2..high2]
n-dimension: A[low1..high1, low2..high2, ... , lown..highn]
Let: base = address of beginning of A, and
w = width of an array element
ni = the number of array elements in i-th dimension (row)
/* row major */
( e.g. n1 = high1 - low1 + 1; n2 = high2 - low2 + 1;
n3 = high3 - low3 + 1; ...)
In general, A[i1, i2, ... ,ik] has address: ((..(((i1* n2 + i2) * n3 + i3)
*n4 + ... ) * nk + ik) * w + base - ((..((low1* n2 + low2) * n3 +
low3)... ) * nk + lowk) * w, where base - ((..((low1* n2 + low2) *
n3 + low3) ... ) * nk + lowk) * w is compile-time invariant.
Therefore, we can compute as follows:
e1 = i1
e2 = e1* n2 + i2
e3 = e2* n3 + i3
.
em = em-1* nm + im
.
ek = ek-1* nk + ik
98
(1) S -> L = E
{ if L.offset = null then
GEN (L.place = E.place)
else
GEN (L.place[L.offset] = E.place); //
}
(2) E -> E1 + E2
{ E.place = newtemp(); //generate a temporary variable and
save its symbol table index
GEN (E.place = E1.place+ E2.place);
}
(4) E -> L
E
{ T = newtemp(); m = Elist (1).ndimen + 1;
GEN ( T = Elist (1).place * limit(Elist (1). array_name, m));
GEN ( T = T + E.place );
Elist.array_name = Elist (1).array_name;
Elist.place = tj;
// tj T
Elist.ndimen = mj; } // mj m
Elist.array_name := id.place; }
// : compile-time invariant id.place
6. Procedure calls
1. call -> id (args)
2. args -> args , E
3. args -> E
3 1. call -> id (args)
3. args -> E
{ initialize QUEUE to contain only
E.place; }
/* Originally, QUEUE is empty and, after the reduction
of E to args, QUEUE contains a single pointer to the
symbol table location for the name that denotes the
value of E. */
int x [10]
or
.......
8. Switch Statement
Syntax:
10
9
switch E
{
case V1: S1;
case V2: S2;
.............
.............
case Vn-1: Sn-1;
default: Sn;
}
Temporary variable
11
1