Compiler structures
Download
1 / 53

Compiler Structures - PowerPoint PPT Presentation


  • 119 Views
  • Uploaded on

Compiler Structures. 241-437 , Semester 1 , 2011-2012. Objective extend the expressions language compiler to generate a parse tree for the input program, and then evaluate it. 9. Creating and Evaluating a Parse Tree. Overview. 1 . The Expressions Grammar 2 . exprParse2.c

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Compiler Structures' - flynn-humphrey


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Compiler structures
Compiler Structures

241-437, Semester 1, 2011-2012

  • Objective

    • extend the expressions language compiler to generate a parse tree for the input program, and then evaluate it

9. Creating and Evaluating a

Parse Tree


Overview
Overview

1. The Expressions Grammar

2. exprParse2.c

3. Parse Tree Data Structures

4. Revised Parse Functions

5. Tree Building

6. Tree Printing

7. Tree Evaluation


In this lecture

Source Program

In this lecture

Lexical Analyzer

Front

End

Syntax Analyzer

Semantic Analyzer

Int. Code Generator

concentrating

on parse tree

generation and

evaluation

Intermediate Code

Code Optimizer

Back

End

Target Code Generator

Target Lang. Prog.


1 the expressions grammar
1. The Expressions Grammar

  • It's LL(1) grammar:

    Stats => ( [ Stat ] \n )*

    Stat => let ID = Expr | Expr

    Expr => Term ( (+ | - ) Term )*

    Term => Fact ( (* | / ) Fact ) *

    Fact => '(' Expr ')' | Int | Id


An expressions program test3 txt
An Expressions Program (test3.txt)

5 + 6

let x = 2

3 + ( (x*y)/2) // comments

// y

let x = 5

let y = x /0

// comments


Exprparse2 c
exprParse2.c

  • A recursive descent parser using the expressions language.

  • This version of the parser differs from exprParse1.c by having the parse functions (e.g. statements(), statement()) create a parse tree as they execute.

continued


Compiler structures


Output for test1 txt
Output for test1.txt tree, and evalTree() which evaluates it.

let x = 2

let y = 3 + x

> exprParse2 < test1.txt

\n

\n

NULL

=

x

2

=

y

+

3

x

\n

\n

=

printed

tree;

same as

y

+

=

NULL

x

2

3

x

continued


Compiler structures

x being declared tree, and evalTree() which evaluates it.

x = 2

== 2

y being declared

y = 5

== 5

>

evaluation of the

parse tree


3 parse tree data structures
3. Parse Tree Data Structures tree, and evalTree() which evaluates it.

typedef struct TreeNode {

Token operTok;

union {

char *id;

int value;

struct {struct TreeNode *left, *right;} branches;

} u;

} Tree;

A tree is made from TreeNodes.


Graphically
Graphically tree, and evalTree() which evaluates it.

one of ID, INT,NEWLINE,ASSIGNOP,PLUSOP, MINUSOP,

MULTOP, DIVOP

TreeNode

operTok

id

variable name (for ID)

OR

a union, u

value

integer (for INT)

OR

children pointers of

this node (used by

NEWLINE, ASSIGNOP,PLUSOP, MINUSOP,

MULTOP, DIVOP)

left

right

branches


Macros for using treenode fields
Macros for Using TreeNode Fields tree, and evalTree() which evaluates it.

#define TreeOper(t) ((t)->operTok)

#define TreeID(t) ((t)->u.id)

#define TreeValue(t) ((t)->u.value)

#define TreeLeft(t) ((t)->u.branches.left)

#define TreeRight(t) ((t)->u.branches.right)


4 revised parse functions
4. Revised Parse Functions tree, and evalTree() which evaluates it.

  • The parse functions have the same 'shape' as the ones in exprParse0.c, but now call tree building functions, and return a Tree result.

  • Functions:

    • main(), statements(), statement(), expression(), term(), factor()


Main before and after

int main(void) tree, and evalTree() which evaluates it.

{

nextToken();

statements();

match(SCANEOF);

return 0;

}

int main(void)

// parse, then print and evaluate the resulting tree

{

Tree *t;

nextToken();

t = statements();

match(SCANEOF);

printTree(t, 0);

printf("\n\n");

evalTree(t);

return 0;

}

main() Before and After


Statements before and after
statements() Before and After tree, and evalTree() which evaluates it.

with no semantic actions

void statements(void)

// statements ::= { [ statement] '\n' }

{

dprint("Parsing statements\n");

while (currToken != SCANEOF) {

if (currToken != NEWLINE)

statement();

match(NEWLINE);

}

} // end of statements()


Compiler structures

Tree tree, and evalTree() which evaluates it. *statements(void)

{

Tree *t, *left, *statTree;

left = NULL;

dprint("Parsing statements\n");

while (currToken != SCANEOF) {

if (currToken != NEWLINE)

statTree = statement();

else

statTree = NULL;

match(NEWLINE);

if (statTree != NULL) {

t = makeTreeNode(NEWLINE, left, statTree);

left = t;

}

}

return left;

} // end of statements()


Tree structure for statements
Tree Structure for statements tree, and evalTree() which evaluates it.

  • A statements sequence:

    s1 \n1 s2 \n2 s3 \n3

    becomes:

\n3

\n2

s3

s2

\n1

s1

NULL


Statement before and after
statement() Before and After tree, and evalTree() which evaluates it.

with no semantic actions

void statement(void)

// statement ::= ( 'let' ID '=' EXPR ) | EXPR

{

if (currToken == LET) {

match(LET);

match(ID);

match(ASSIGNOP);

expression();

}

else

expression();

} // end of statement()


Compiler structures

Tree tree, and evalTree() which evaluates it. *statement(void)

{

Tree *t, *idTree, *exprTree;

dprint("Parsing statement\n");

if (currToken == LET) {

match(LET);

idTree = matchId();

// build tree node, not symbol table entry

match(ASSIGNOP);

exprTree = expression();

t = makeTreeNode(ASSIGNOP, idTree, exprTree);

}

else // expression

t = expression();

return t;

} // end of statement()


Tree structures for statement
Tree Structures for statement tree, and evalTree() which evaluates it.

=

or

expr

tree

ID

node

expr

tree


Expression before and after
expression() Before and After tree, and evalTree() which evaluates it.

with no semantic actions

void expression(void)

// expression ::= term ( ('+'|'-') term )*

{

term();

while((currToken == PLUSOP) || (currToken == MINUSOP)) {

match(currToken);

term();

}

} // end of expression()


Compiler structures

Tree tree, and evalTree() which evaluates it. *expression(void)

{ Tree *t, *left, *right;

int isAddOp;

dprint("Parsing expression\n");

left = term();

while((currToken == PLUSOP)||(currToken == MINUSOP)) {

isAddOp = (currToken == PLUSOP) ? 1 : 0;

nextToken();

right = term();

if (isAddOp == 1) // addition

t = makeTreeNode(PLUSOP, left, right);

else // subtraction

t = makeTreeNode(MINUSOP, left, right);

left = t;

}

return left;

} // end of expression()


Tree structure for expression
Tree Structure for expression tree, and evalTree() which evaluates it.

  • An expression sequence:

    t1 +1 t2 - t3 +2 t4

    becomes:

+2

-

t4

t3

+1

t2

t1


Term before and after
term() Before and After tree, and evalTree() which evaluates it.

with no semantic actions

void term(void)

// term ::= factor ( ('*'|'/') factor )*

{

factor();

while((currToken == MULTOP) || (currToken == DIVOP)) {

match(currToken);

factor();

}

} // end of term()


Compiler structures

Tree tree, and evalTree() which evaluates it. *term(void)

{ Tree *t, *left, *right;

int isMultOp;

dprint("Parsing term\n");

left = factor();

while((currToken == MULTOP) || (currToken == DIVOP)) {

isMultOp = (currToken == MULTOP) ? 1 : 0;

nextToken();

right = factor();

if (isMultOp == 1) // multiplication

t = makeTreeNode(MULTOP, left, right);

else // division

t = makeTreeNode(DIVOP, left, right);

left = t;

}

return left;

} // end of term()


Tree structure for term
Tree Structure for term tree, and evalTree() which evaluates it.

  • An term sequence:

    f1 *1 f2 / f3 *2 f4

    becomes:

*2

/

f4

f3

*1

f2

f1


Factor before and after
factor() Before and After tree, and evalTree() which evaluates it.

with no semantic actions

void factor(void)

// factor ::= '(' expression ')' | INT | ID

{

if(currToken == LPAREN) {

match(LPAREN);

expression();

match(RPAREN);

}

else if(currToken == INT)

match(INT);

else if (currToken == ID)

match(ID);

else

syntax_error(currToken);

} // end of factor()


Compiler structures

Tree tree, and evalTree() which evaluates it. *factor(void)

{ Tree *t = NULL;

dprint("Parsing factor\n");

if(currToken == LPAREN) {

match(LPAREN);

t = expression();

match(RPAREN);

}

else if(currToken == INT) {

t = makeIntLeaf(currTokValue);

match(INT);

}

else if (currToken == ID)

t = matchId();// do not access symbol table

else

syntax_error(currToken);

return t;

} // end of factor()


Match an id extended
Match an ID (Extended) tree, and evalTree() which evaluates it.

Tree *matchId(void)

{

Tree *t;

if (currToken == ID)

t = makeIDLeaf(tokString);

match(ID);

return t;

} // end of matchID()


Tree structure for factor
Tree Structure for factor tree, and evalTree() which evaluates it.

  • There are three possible nodes:

tree

node

INT

node

ID

node

or

or


5 tree building
5. Tree Building tree, and evalTree() which evaluates it.

TreeNode

  • The nodes in a parse tree are connected by the parse functions.

  • A tree node can have three different shapes:

operTok

id

OR

value

a union

OR

left

right

branches


Making a tree node
Making a Tree Node tree, and evalTree() which evaluates it.

Tree *treeMalloc(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 treeMalloc()


Making an id node
Making an ID Node tree, and evalTree() which evaluates it.

operTok

ID

"id str"

id

Tree *makeIDLeaf(char *id)

{

Tree *t;

t = treeMalloc();

TreeOper(t) = ID;

TreeID(t) = (char *) malloc(strlen(id)+1);

strcpy(TreeID(t), id);

return t;

} // end of makeIDLeaf()

no symbol table entry

created yet


Making an int node
Making an INT Node tree, and evalTree() which evaluates it.

operTok

INT

Tree *makeIntLeaf(int value)

{

Tree *t;

t = treeMalloc();

TreeOper(t) = INT;

TreeValue(t) = value;

return t;

} // end of makeIntLeaf()

integer

value


Making a node with children
Making a Node with Children tree, and evalTree() which evaluates it.

Tree *makeTreeNode(Token op, Tree *left, Tree *right)

/* Build an internal tree node, which contains an operator and points to two subtrees.*/

{

Tree *t;

t = treeMalloc();

TreeOper(t) = op;

TreeLeft(t) = left;

TreeRight(t) = right;

return t;

} // end of makeTreeNode()

operTok

op

branches

left

right


6 tree printing
6. Tree Printing tree, and evalTree() which evaluates it.

  • The printTree() 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.


Compiler structures

void printTree tree, and evalTree() which evaluates it. (Tree *t, int indent)

// print a tree, indenting by indent spaces

{

printIndent(indent);

if (t == NULL) {

printf("NULL\n");

return;

} :

continued


Compiler structures

Token tok tree, and evalTree() which evaluates it. = TreeOper(t);

if (tok == INT)

printf("%d\n", TreeValue(t));

else if (tok == ID)

printf("%s\n", TreeID(t));

else { // operator

if (tok == NEWLINE)

printf("\\n\n"); // show the \n

else

printf("%s\n", tokSyms[tok]);

printTree(TreeLeft(t), indent+2);

printTree(TreeRight(t), indent+2);

}

} // end of printTree()


Compiler structures

void printIndent(int n) tree, and evalTree() which evaluates it.

{ int spaces;

for(spaces = 0; spaces != n; spaces++)

putchar(' ');

} // end of printIndent()


Tree printing examples

> exprParse2 < test2.txt tree, and evalTree() which evaluates it.

\n

\n

\n

NULL

=

x56

2

=

bing_BONG

-

*

27

2

x56

*

5

/

67

3

Tree Printing Examples

let x56 = 2

let bing_BONG = (27 * 2) - x56

5 * (67 / 3)


Graphically1
Graphically tree, and evalTree() which evaluates it.

\n

\n

*

/

5

\n

=

67

3

bing_BONG

-

S3

=

NULL

x56

*

x56

2

27

2

S1

S2


Test3 txt
test3.txt tree, and evalTree() which evaluates it.

5 + 6

let x = 2

3 + ( (x*y)/2) // comments

// y

let x = 5

let y = x /0

// comments


Compiler structures

> exprParse2 < test3.txt tree, and evalTree() which evaluates it.

\n

\n

\n

\n

\n

NULL

+

5

6

=

x

2

+

3

/

*

x

y

2

=

x

5

=

y

/

x

0


7 tree evaluation
7. Tree Evaluation tree, and evalTree() which evaluates it.

  • Tree evaluation works in two stages:

    • evalTree() 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


Finding non newlines
Finding non-NEWLINEs tree, and evalTree() which evaluates it.

\n

evalTree()

used here

\n

*

/

5

\n

=

67

3

bing_BONG

-

=

NULL

x56

*

x56

2

27

2

eval() used here


Compiler structures
Code tree, and evalTree() which evaluates it.

void evalTree(Tree *t)

{

if (t == NULL)

return;

Token tok = TreeOper(t);

if (tok == NEWLINE) {

evalTree( TreeLeft(t));

evalTree( TreeRight(t));

}

else

printf("== %d\n", eval(t));

} // end of evalTree()


Compiler structures

The operator can tree, and evalTree() which evaluates it.

be one of ID, INT,ASSIGNOP,PLUSOP, MINUSOP,

MULTOP, DIVOP

int eval(Tree *t)

{

SymbolInfo *si;

if (t == NULL)

return 0;

Token tok = TreeOper(t);

if (tok == ID) {

si = getIDEntry( TreeID(t) ); // lookup ID in symbol table

return si->value;

} :

7 possibilities

continued


Compiler structures

else if tree, and evalTree() which evaluates it. (tok == INT)

return TreeValue(t);

else if (tok == ASSIGNOP) { // id = expr

si = evalID(TreeLeft(t)); //add ID to sym. table

int result = eval(TreeRight(t));

si->value = result;

printf("%s = %d\n", si->id, result);

return result;

}

else if (tok == PLUSOP)

return eval(TreeLeft(t)) + eval(TreeRight(t));

else if (tok == MINUSOP)

return eval(TreeLeft(t)) - eval(TreeRight(t));

:


Compiler structures

else if tree, and evalTree() which evaluates it. (tok == MULTOP)

return eval(TreeLeft(t)) * eval(TreeRight(t));

else if (tok == DIVOP) {

int right = eval(TreeRight(t));

if (right == 0) {

printf("Error: Div by 0; using 1 instead\n");

return eval(TreeLeft(t));

}

else

return eval(TreeLeft(t)) / right;

}

return 0; // shouldn't reach here

} // end of eval()


Compiler structures

SymbolInfo *evalID(Tree *t) tree, and evalTree() which evaluates it.

{

char *id = TreeID(t);

return getIDEntry(id); // create sym. table entry for id

} // end of evalID()

this function finds or creates a

symbol table entry for the id, and

return a pointer to the entry

(same as in exprParse1.c)


Evaluation examples
Evaluation Examples tree, and evalTree() which evaluates it.

let x = 2

let y = 3 + x

$ ./exprParse2 < test1.txt

:

x declared

x = 2

== 2

y declared

y = 5

== 5


Compiler structures

$ ./exprParse2 < test2.txt tree, and evalTree() which evaluates it.

:

x56 declared

x56 = 2

== 2

bing_BONG declared

bing_BONG = 52

== 52

== 110

// test2.txt example

let x56 = 2

let bing_BONG = (27 * 2) - x56

5 * (67 / 3)


Compiler structures

5 tree, and evalTree() which evaluates it. + 6

let x = 2

3 + ( (x*y)/2) // comments

// y

let x = 5

let y = x /0

$ ./exprParse2 < test3.txt

:

== 11

x declared

x = 2

== 2

y declared

== 3

x = 5

== 5

Error: Division by zero; using 1 instead

y = 5

== 5