26 Procedures, Assignment Statements 13-09-2024
26 Procedures, Assignment Statements 13-09-2024
n=f(a[i]); f is a function
( a [ i ] ) is the parameter of the function
Three-address code:
• The first two lines compute the value of the expression
a [ i ] into temporary t2
• Line 3 makes t2 an actual parameter for the call on
line 4 of f with one parameter.
• Line 5 assigns the value returned by the function call
to t3
Adding functions to the source language
• The productions shows the function definitions and function calls
Structure of a procedural P → MD
programming language (Pascal,C M → ε
or Ada) D → D; D| id: T | proc id; N D;S
N → ε
D → D; D | id: T | proc id; N D; S
• This is the rule for declarations (D), and it allows for:
• Sequences of declarations (D; D), allowing multiple declarations separated by
semicolons.
• Variable declaration (id: T), where id is an identifier and T is a type.
• Procedure declaration (proc id; N D; S), where
• id is a procedure name,
• N is an optional part (which is empty in this case)
• D is a block of declarations
• S represents the statements within the procedure.
Example
proc calculate; P → MD
num: int; M → ε
result: int; D → D; D| id: T | proc id; N D;S
begin N → ε
result := num * 10;
end;
D → proc id; N D; S:
begin
result := num * 10;
end;
• Consider the grammar
S → id := E
E → E1 + E2
E → E1 * E2
E → (E1)
E → id
Function Description
lookup() Searches particular variable or identifier in symbol table
emit() Generates 3 address code
newtemp() Used to generate new temporary variables (t1,t2,..)
E.place holds the value of E (tells about the name that will hold the value of
the expression). place is an attribute of E.
Production Semantic actions
• lookup check whether identifier
S → id :=E { p = lookup(id.name); (id.name) is present in symbol
If p ≠ nil then table. If present then that value
emit (p = E.place) will be assigned to p.
else Error; } • If p is not equal to null, then
E →E1 + E2 { E.place = newtemp(); emit, which will create a three
emit (E.place = E1.place '+' E2.place) address code and assign it to p.
}
E.place = t1
E → E1 * E2 { E.place = newtemp(); t1=E1+E2
emit (E.place = E1.place '*' E2.place)
} E.place = t2
E → -E1 { E.place : = newtemp; t2=E1*E2
emit ( E.place ‘: =’ ‘uminus’ E1.place ) E.place = t3
} t3=-E1
E → (E1) { E.place = E1.place }
• Whenever id is present, check
E → id { p = look_up(id.name); for symbol table.
If p ≠ nil then
• If p is null then return the error
emit (E.place=p)
else Error; }
value
Translation of Expressions
1. Operations Within Expressions
• The syntax-directed definition builds up the three-address code for an
assignment statement S
• Attribute code for assignment statement S
• Attributes addr and code for an expression E
• Attributes S.code and E.code denote the three-address code for S and E.
• Attribute E.addr denotes the address that will hold the value of E
• Can be a name, a constant, or a temporary
• top denote the current symbol table.
• top.get() retrieves the entry.
• newtemp() allocates and returns a new temporary symbol
• gen() – Helper function to create a 3AC instruction
E1 rel E2
• The attribute rel.op is used to indicate the operator represented by rel among
the 6 comparison operators
• Assume || and && are left-associative and || has the lowest precedence,
then && and finally !
• Given an expression
• If x > 200 is true, then the remaining part of the expression is checked (x!=y), if it is
false the whole expression again will become false and control will jump to label L1.
• Else if both expressions( x> 200 && x!=y) are true, then the control will jump to label
L2.
3. Flow-of-Control Statements
• Consider the translation of Boolean expressions into three-address code in the
context of statements generated by the following grammar
S → if (B) S1 • Nonterminal B represents a Boolean expression
S → if (B) S1 else S2 • Non-terminal S represents a statement.
S → while (B) S1
• B and S have a synthesized attribute code, which gives the translation into three-
address instructions.
• Using syntax-directed definitions we build up the
translations B.code and S.code as strings.
• Inherited attributes (B.true, B.false, S.next) are used to manage the labels for the
jumps in B.code and S.code
• With a boolean expression B, we associate two labels:
– B.true, the label to which control flows if B is true
– B.false, the label to which control flows if B is false.
• S.next that denotes a label for the instruction immediately following the code for S
• The translation of if (B) S1 consists of B.code followed by S1.code
B.true = newlabel();
SDD – Semantic Rule B.false = newlabel();
S1.next = S.next
S2.next = S.next;
S.code = B.code
|| label(B.true) ||S1.code
|| gen('goto' S.next)
gen ( ) – generates the code (string) passed || label(B.false) || S2.code;
as a parameter to it
Example
• The translation of S → while (B) S1
• A boolean expression
is translated into
three address
instructions that
evaluate the
expression using
create labels only
when they are
needed.
• A boolean B is
translated into three-
address instructions
that evaluate B using
conditional and
unconditional jumps
to one of two labels,
these are B.true and
B.false.
• B B1|| B2
– If B1 is true, then the B itself is true, so B1.true is the B1.true = B.true;
same as B.true. B1.false = newLabel();
– If B1 is false, then B2 must be evaluated, for B2.true = B.true;
evaluation we have to generate three address code for B2.false = B.false;
that we call the function newlabel(). So we make B.code = B1.code ||
B1.false be the label of the first instruction in the code label(B1.false) ||
for B2. B2.code;
• B B1&& B2
– If B1 is true, then we evaluate B2 for that we have to B1.true = newLabel();
generate three address code for that we call the B1.false = B.false;
function newlabel(). B2.true = B.true;
B2.false = B.false;
– If B1 is false, then no need to evaluate B2 and B is
B.code = B1.code ||
also false.
label(B1.true) ||
– If B1 is true and B2 is true then B is true B2.code;
– If B1 is false and B2 is true then B is fale
• B ! B1
B1.true = B.false;
– If B1 is true, then B will become false B1.false = B.true;
– If B1 is false, then B will become true B.code = B1.code;
• B E1 rel E2
– Translated directly into a comparison B.code = E1.code || E2.code ||
three-address instruction with jumps to gen('if' E1.addr rel.op E2.addr
the appropriate places. 'goto' B.true) ||
gen('goto' B.false)
– If we have B with the form of a < b. It
translates to