Compiler Structures 242 437 Semester 2 2019 2020

  • Slides: 53
Download presentation
Compiler Structures 242 -437 , Semester 2 , 2019 -2020 9. Creating and Evaluating

Compiler Structures 242 -437 , Semester 2 , 2019 -2020 9. Creating and Evaluating a Parse Tree • Objective �extend the expressions language compiler to generate a parse tree for the input program, and then evaluate it 1

Overview 1. The Expressions Grammar 2. expr. Parse 2. c 3. Parse Tree Data

Overview 1. The Expressions Grammar 2. expr. Parse 2. c 3. Parse Tree Data Structures 4. Revised Parse Functions 5. Tree Building 6. Tree Printing 7. Tree Evaluation 2

Source Program Lexical Analyzer In this lecture Syntax Analyzer Semantic Analyzer Front End Int.

Source Program Lexical Analyzer In this lecture Syntax Analyzer Semantic Analyzer Front End Int. Code Generator concentrating on parse tree generation and evaluation Intermediate Code Optimizer Target Code Generator Back End Target Lang. Prog. 3

1. The Expressions Grammar • Its LL(1) grammar: Stats => ( [ Stat ]

1. The Expressions Grammar • Its LL(1) grammar: Stats => ( [ Stat ] n )* Stat => let ID = Expr | Expr => Term ( (+ | - ) Term )* Term => Fact ( (* | / ) Fact ) * Fact => '(' Expr ')' | Int | Id 4

An Expressions Program (test 3. txt) 5+6 let x 3) ) + //y let

An Expressions Program (test 3. txt) 5+6 let x 3) ) + //y let x let y =2 x*y/(2 // (comments =5 =x /0 //comments 5

2. expr. Parse 2. c • A recursive descent parser using the expressions language.

2. expr. Parse 2. c • A recursive descent parser using the expressions language. • This version of the parser differs from expr. Parse 1. c by having the parse functions (e. g. statements(), statement()) create a parse tree as they execute. continued 6

 • There's a new print. Tree() function which prints the final tree, and

• There's a new print. Tree() function which prints the final tree, and eval. Tree() which evaluates it. • Usage: $ gcc -Wall -o expr. Parse 2. c $. /expr. Parse 2 < test 1. txt 7

Output for test 1. txt > expr. Parse 2 < test 1. txt n

Output for test 1. txt > expr. Parse 2 < test 1. txt n n NULL = x 2 printed = tree; y same as + 3 x let x = 2 let y = 3 + x n n NULL = y = x 2 + 3 x continued 8

x being declared x = 2 == 2 y being declared y = 5

x being declared x = 2 == 2 y being declared y = 5 == 5 evaluation of the parse tree > 9

3. Parse Tree Data Structures typedef struct Tree. Node { Token oper. Tok; union

3. Parse Tree Data Structures typedef struct Tree. Node { Token oper. Tok; union { char *id; int value; struct {struct Tree. Node *left, *right; } branches; } u; } Tree; A tree is made from Tree. Nodes. 10

Graphically Tree. Node oper. Tok a union, u id one of ID, INT, NEWLINE,

Graphically Tree. Node oper. Tok a union, u id one of ID, INT, NEWLINE, ASSIGNOP, PLUSOP, MINUSOP, MULTOP, DIVOP variable name (for ID) OR value OR branches left right integer (for INT) children pointers of this node (used by NEWLINE, ASSIGNOP, PLUSOP, MINUSOP, MULTOP, DIVOP) 11

Macros for Using Tree. Node Fields #define Tree. Oper)t)) (t-(>oper. Tok( #define Tree. ID)t))

Macros for Using Tree. Node Fields #define Tree. Oper)t)) (t-(>oper. Tok( #define Tree. ID)t)) (t-(>u. id( #define Tree. Value)t)) (t-(>u. value( #define Tree. Left)t)) (t-(>u. branches. left( #define Tree. Right)t)) (t-(>u. branches. right( 12

4. Revised Parse Functions • The parse functions have the same 'shape' as the

4. Revised Parse Functions • The parse functions have the same 'shape' as the ones in expr. Parse 0. c, but now call tree building functions, and return a Tree result. • Functions: �main(), statements(), statement(), expression(), term(), factor() 13

main() Before and After int main(void) { next. Token(); statements(); match(SCANEOF); return 0; }

main() Before and After int main(void) { next. Token(); statements(); match(SCANEOF); return 0; } int main(void) // parse, then print and evaluate the resulting tree { Tree *t; next. Token(); t = statements(); match(SCANEOF); print. Tree(t, 0); printf("nn"); eval. Tree(t); return 0; } 14

statements() Beforewithand After no semantic actions void statements)void( //statements =: : { ]statement ['n'

statements() Beforewithand After no semantic actions void statements)void( //statements =: : { ]statement ['n' } { dprint")Parsing statementsn("; while )curr. Token =!SCANEOF ({ if )curr. Token =!NEWLINE( statement(); match)NEWLINE(; } } //end of statements() 15

Tree *statements)void( { Tree *t, *left, *stat. Tree; left =NULL; dprint")Parsing statementsn("; while )curr.

Tree *statements)void( { Tree *t, *left, *stat. Tree; left =NULL; dprint")Parsing statementsn("; while )curr. Token =!SCANEOF ({ if )curr. Token =!NEWLINE( stat. Tree =statement(); else stat. Tree =NULL; // error so no tree match)NEWLINE(; if )stat. Tree =!NULL ({ t =make. Tree. Node)NEWLINE, left, stat. Tree(; left =t; } } return left; } //end of statements() 16

Tree Structure for statements • A statements sequence: s 1 n 1 s 2

Tree Structure for statements • A statements sequence: s 1 n 1 s 2 n 2 s 3 n 3 becomes: n n 3 s 3 n s 2 n NULL s 1 which I'll draw as: n 2 s 2 n 1 NULL s 3 s 1 17

statement() Before and After with no semantic actions void statement(void) // statement : :

statement() Before and After with no semantic actions void statement(void) // statement : : = ( 'let' ID '=' EXPR ) | EXPR { if (curr. Token == LET) { match(LET); match(ID); match(ASSIGNOP); expression(); } else expression(); } // end of statement() 18

Tree *statement)void( { Tree *t, *id. Tree, *expr. Tree; dprint")Parsing statementn("; if )curr. Token

Tree *statement)void( { Tree *t, *id. Tree, *expr. Tree; dprint")Parsing statementn("; if )curr. Token ==LET ({ match)LET(; id. Tree =match. Id(); // build tree node, not symbol table entry match)ASSIGNOP(; expr. Tree =expression(); t =make. Tree. Node)ASSIGNOP, id. Tree, expr. Tree(; } else //expression t =expression(); return t; } //end of statement() 19

Tree Structures for statement = or ID node expr tree 20

Tree Structures for statement = or ID node expr tree 20

expression() Beforewith and After no semantic actions void expression(void) // expression : : =

expression() Beforewith and After no semantic actions void expression(void) // expression : : = term ( ('+'|'-') term )* { term(); while((curr. Token == PLUSOP) || (curr. Token == MINUSOP)) { match(curr. Token); term(); } } // end of expression() 21

Tree *expression)void( { Tree *t, *left, *right; int is. Add. Op; dprint")Parsing expressionn("; left

Tree *expression)void( { Tree *t, *left, *right; int is. Add. Op; dprint")Parsing expressionn("; left =term(); while))curr. Token ==PLUSOP(||)curr. Token == MINUSOP (({ is. Add. Op ) =curr. Token ==PLUSOP (? 1 : 0; next. Token(); right =term(); if )is. Add. Op ==1 // (addition t =make. Tree. Node)PLUSOP, left, right(; else //subtraction t =make. Tree. Node)MINUSOP, left, right(; left =t; } return left; } //end of expression() 22

Tree Structure for expression • An expression sequence: t 1 +1 t 2 -

Tree Structure for expression • An expression sequence: t 1 +1 t 2 - t 3 +2 t 4 becomes: +2 t 3 +1 t 4 t 2 23

term() Before and After with no semantic actions void term)void( //term =: : factor

term() Before and After with no semantic actions void term)void( //term =: : factor ( )'*'|'/' (factor )* { factor(); while))curr. Token ==MULTOP (|| )curr. Token ==DIVOP (({ match)curr. Token(; factor(); } } //end of term() 24

Tree *term)void( { Tree *t, *left, *right; int is. Mult. Op; dprint")Parsing termn("; left

Tree *term)void( { Tree *t, *left, *right; int is. Mult. Op; dprint")Parsing termn("; left =factor(); while))curr. Token ==MULTOP (|| )curr. Token ==DIVOP (( { is. Mult. Op ) =curr. Token ==MULTOP (? 1 : 0; next. Token(); right =factor(); if )is. Mult. Op ==1 // (multiplication t =make. Tree. Node)MULTOP, left, right(; else //division t =make. Tree. Node)DIVOP, left, right(; left =t; } return left; } //end of term() 25

Tree Structure for term • An term sequence: f 1 *1 f 2 /

Tree Structure for term • An term sequence: f 1 *1 f 2 / f 3 *2 f 4 becomes: *2 / f 3 *1 f 4 f 2 26

factor() Before and with After no semantic actions void factor)void( //factor =: : ')'

factor() Before and with After no semantic actions void factor)void( //factor =: : ')' expression '(' | INT | ID { if)curr. Token ==LPAREN ({ match)LPAREN(; expression(); match)RPAREN(; } else if)curr. Token ==INT( match)INT(; else if )curr. Token ==ID( match)ID(; else syntax_error)curr. Token(; } //end of factor() 27

Tree *factor)void( { Tree *t =NULL; dprint")Parsing factorn("; if)curr. Token ==LPAREN ({ match)LPAREN(; t

Tree *factor)void( { Tree *t =NULL; dprint")Parsing factorn("; if)curr. Token ==LPAREN ({ match)LPAREN(; t =expression(); match)RPAREN(; } else if)curr. Token ==INT ({ t =make. Int. Leaf)curr. Tok. Value(; match)INT(; } else if )curr. Token ==ID( t =match. Id(); //do not access symbol table else syntax_error)curr. Token(; return t; } //end of factor() 28

Match an ID (Extended) Tree *match. Id(void) { Tree *t; if (curr. Token ==

Match an ID (Extended) Tree *match. Id(void) { Tree *t; if (curr. Token == ID) t = make. IDLeaf(tok. String); match(ID); return t; } // end of match. ID() 29

Tree Structure for factor • There are three possible nodes: tree node or INT

Tree Structure for factor • There are three possible nodes: tree node or INT node or ID node 30

5. Tree Building Tree. Node • The nodes in a parse tree are connected

5. Tree Building Tree. Node • The nodes in a parse tree are connected by the parse functions. • A tree node can have three different shapes: oper. Tok a union id OR value OR branches left right 31

Making a Tree Node Tree *tree. Malloc(void) // a tree node with no fields

Making a Tree Node Tree *tree. Malloc(void) // a tree node with no fields specified { Tree *t; t = (Tree *) malloc( sizeof(Tree) ); if(t == NULL) { /* out of memory? */ perror("Tree Node not made; out of memory"); exit(1); } return t; } // end of tree. Malloc() 32

Making an ID Node oper. Tok Tree *make. IDLeaf)char *id( { id Tree *t;

Making an ID Node oper. Tok Tree *make. IDLeaf)char *id( { id Tree *t; t =tree. Malloc(); Tree. Oper)t = (ID; Tree. ID)t) = (char (*malloc)strlen)id(+1(; strcpy)Tree. ID)t(, id(; return t; } //end of make. IDLeaf() ID "id str" no symbol table entry created yet 33

Making an INT Node Tree *make. Int. Leaf(int value) { Tree *t; t =

Making an INT Node Tree *make. Int. Leaf(int value) { Tree *t; t = tree. Malloc(); Tree. Oper(t) = INT; Tree. Value(t) = value; return t; } // end of make. Int. Leaf() oper. Tok INT value integer 34

Making a Node with Children Tree *make. Tree. Node(Token op, Tree *left, Tree *right)

Making a Node with Children Tree *make. Tree. Node(Token op, Tree *left, Tree *right) /* Build an internal tree node, which contains an operator and points to two subtrees. */ { Tree *t; t = tree. Malloc(); Tree. Oper(t) = op; oper. Tok op Tree. Left(t) = left; Tree. Right(t) = right; branches return t; left right } // end of make. Tree. Node() 35

6. Tree Printing • The print. Tree() function recurses over the tree, and does

6. Tree Printing • The print. Tree() function recurses over the tree, and does three different things depending on the three possible 'shapes' for a tree node. • It includes an indent counter, which is used to print spaces (indents) in front of the node information. 36

void print. Tree)Tree *t, int indent( //print a tree, indenting by indent spaces {

void print. Tree)Tree *t, int indent( //print a tree, indenting by indent spaces { print. Indent)indent(; if )t ==NULL ({ printf")NULLn("; return; } : continued 37

Token tok =Tree. Oper)t(; if )tok ==INT( printf%")dn", Tree. Value)t((; else if )tok ==ID(

Token tok =Tree. Oper)t(; if )tok ==INT( printf%")dn", Tree. Value)t((; else if )tok ==ID( printf%")sn", Tree. ID)t((; else { //operator if )tok ==NEWLINE( printf")\nn("; //show the n else printf%")sn", tok. Syms]tok([; print. Tree)Tree. Left)t(, indent+2(; print. Tree)Tree. Right)t(, indent+2(; } } //end of print. Tree() 38

void print. Indent(int n) { int spaces; for(spaces = 0; spaces != n; spaces++)

void print. Indent(int n) { int spaces; for(spaces = 0; spaces != n; spaces++) putchar(' '); } // end of print. Indent() 39

Tree Printing Examples > expr. Parse 2 < test 2. txt * n 5

Tree Printing Examples > expr. Parse 2 < test 2. txt * n 5 n / n 67 NULL 3 = x 56 2 = bing_BONG * let x 56 = 2 27 let bing_BONG ) =27 * 2 - (x 56 2 5) * 67 / 3( x 56 40

Graphically n n * n = bing_ BONG = NULL S 1 67 S

Graphically n n * n = bing_ BONG = NULL S 1 67 S 3 - 3 x 56 * x 56 / 5 2 27 S 2 2 41

test 3. txt 5+6 let x 3) ) + //y let x let y

test 3. txt 5+6 let x 3) ) + //y let x let y =2 x*y/(2 // (comments =5 =x /0 //comments 42

> expr. Parse 2 < test 3. txt n n n NULL + 5

> expr. Parse 2 < test 3. txt n n n NULL + 5 6 = x 2 + = = y / 3 / * 2 x y x 5 x 0 43

7. Tree Evaluation • Tree evaluation works in two stages: �eval. Tree() searches over

7. Tree Evaluation • Tree evaluation works in two stages: �eval. Tree() searches over the tree looking for subtrees which start with an operator which is not NEWLINE �these subtrees are evaluated by eval(), using the operators in their nodes 44

Finding non-NEWLINEs n eval. Tree() used here n * n / 5 = 67

Finding non-NEWLINEs n eval. Tree() used here n * n / 5 = 67 bing_ BONG = NULL x 56 * x 56 3 2 27 2 eval() used here 45

Code void eval. Tree)Tree *t( { if )t ==NULL( return; Token tok =Tree. Oper)t(;

Code void eval. Tree)Tree *t( { if )t ==NULL( return; Token tok =Tree. Oper)t(; if )tok ==NEWLINE ({ eval. Tree) Tree. Left)t( (; eval. Tree) Tree. Right)t( (; } else printf% ==")dn", eval)t((; } //end of eval. Tree() 46

int eval)Tree *t( { Symbol. Info *si; if )t ==NULL( return 0; Token tok

int eval)Tree *t( { Symbol. Info *si; if )t ==NULL( return 0; Token tok =Tree. Oper)t(; if )tok ==ID ({ si =get. IDEntry )Tree. ID)t( (; //lookup ID in symbol table return si->value; } : The operator can be one of ID, INT, ASSIGNOP, PLUSOP, MINUSOP, MULTOP, DIVOP 7 possibilities continued 47

else if )tok ==INT( return Tree. Value)t(; else if )tok ==ASSIGNOP ({ //id =expr

else if )tok ==INT( return Tree. Value)t(; else if )tok ==ASSIGNOP ({ //id =expr si =eval. ID)Tree. Left)t((; //add ID to sym. table int result =eval)Tree. Right)t((; si->value =result; printf%")s % =dn", si->id, result(; return result; } else if )tok ==PLUSOP( return eval)Tree. Left)t + ((eval)Tree. Right)t((; else if )tok ==MINUSOP( return eval)Tree. Left)t - ((eval)Tree. Right)t((; : 48

else if )tok ==MULTOP( return eval)Tree. Left)t * ((eval)Tree. Right)t((; else if )tok ==DIVOP

else if )tok ==MULTOP( return eval)Tree. Left)t * ((eval)Tree. Right)t((; else if )tok ==DIVOP ({ int right =eval)Tree. Right)t((; if )right ==0 ({ printf")Error : Div by 0; using 1 insteadn("; return eval)Tree. Left)t((; } else return eval)Tree. Left)t / ((right; } return 0; //shouldn't reach here } //end of eval() 49

Symbol. Info *eval. ID(Tree *t) { char *id = Tree. ID(t); return get. IDEntry(id);

Symbol. Info *eval. ID(Tree *t) { char *id = Tree. ID(t); return get. IDEntry(id); // create sym. table entry for id } // end of eval. ID() this function finds or creates a symbol table entry for the id, and return a pointer to the entry (same as in expr. Parse 1. c) 50

Evaluation Examples $. /expr. Parse 2 < test 1. txt : x declared x

Evaluation Examples $. /expr. Parse 2 < test 1. txt : x declared x = 2 == 2 y declared y = 5 == 5 let x = 2 let y = 3 + x 51

$. /expr. Parse 2 < test 2. txt : x 56 declared x 56

$. /expr. Parse 2 < test 2. txt : x 56 declared x 56 = 2 == 2 // test 2. txt example bing_BONG declared bing_BONG = 52 let x 56 = 2 == 52 let bing_BONG = (27 == 110 * 2) - x 56 5 * (67 / 3) 52

5+6 $ /. expr. Parse 2 < test 3. txt let x =2 :

5+6 $ /. expr. Parse 2 < test 3. txt let x =2 : 3) ) + x*y/(2 // ==11 x declared //y x =2 let x =5 ==2 let y =x /0 y declared ==3 x =5 ==5 Error : Division by zero; using 1 instead y =5 ==5 (comments 53