241-437 compilers: parse tree/9 1 compiler structures objective – –extend the expressions...
Post on 16-Dec-2015
236 Views
Preview:
TRANSCRIPT
241-437 Compilers: Parse Tree/9 1
Compiler Structures
• Objective– extend the expressions language compiler to generate a
parse tree for the input program, and then evaluate it
241-437, Semester 1, 2011-2012
9. Creating and Evaluating aParse Tree
241-437 Compilers: Parse Tree/9 2
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
241-437 Compilers: Parse Tree/9 3
In this lecture
Source Program
Target Lang. Prog.
Semantic Analyzer
Syntax Analyzer
Lexical Analyzer
FrontEnd
Code Optimizer
Target Code Generator
BackEnd
Int. Code Generator
Intermediate Codeconcentratingon parse treegeneration andevaluation
241-437 Compilers: Parse Tree/9 4
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
241-437 Compilers: Parse Tree/9 5
An Expressions Program (test3.txt)
5 + 6let x = 23 + ( (x*y)/2) // comments// ylet x = 5let y = x /0
// comments
241-437 Compilers: Parse Tree/9 6
2. 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
241-437 Compilers: Parse Tree/9 7
• There's a new printTree() function which prints the final tree, and evalTree() which evaluates it.
• Usage:$ gcc -Wall -o exprParse2 exprParse2.c$ ./exprParse2 < test1.txt
241-437 Compilers: Parse Tree/9 8
Output for test1.txt
> exprParse2 < test1.txt
\n
\n
NULL
=
x
2
=
y
+
3
x
continued
printedtree; same as
\n
\n
NULL =
x 2
=
y +
3 x
let x = 2let y = 3 + x
241-437 Compilers: Parse Tree/9 9
x being declared
x = 2
== 2
y being declared
y = 5
== 5
>
evaluation of theparse tree
241-437 Compilers: Parse Tree/9 10
3. Parse Tree Data Structures
typedef struct TreeNode { Token operTok; union { char *id; int value; struct {struct TreeNode *left, *right;}
branches; } u;} Tree;
A tree is made from TreeNodes.
241-437 Compilers: Parse Tree/9 11
Graphically
operTok
one of ID, INT,NEWLINE,ASSIGNOP,PLUSOP, MINUSOP,MULTOP, DIVOP
id variable name (for ID)OR
value integer (for INT)
OR
branches children pointers of this node (used byNEWLINE, ASSIGNOP,PLUSOP, MINUSOP,MULTOP, DIVOP)
TreeNodea
unio
n, u
left right
241-437 Compilers: Parse Tree/9 12
Macros for Using TreeNode Fields
#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)
241-437 Compilers: Parse Tree/9 13
4. Revised Parse Functions
• 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()
241-437 Compilers: Parse Tree/9 14
int main(void){ 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
241-437 Compilers: Parse Tree/9 15
statements() Before and After
void statements(void)
// statements ::= { [ statement] '\n' }
{
dprint("Parsing statements\n");
while (currToken != SCANEOF) {
if (currToken != NEWLINE)
statement();
match(NEWLINE);
}
} // end of statements()
with no semantic actions
241-437 Compilers: Parse Tree/9 16
Tree *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()
241-437 Compilers: Parse Tree/9 17
Tree Structure for statements
• A statements sequence:s1 \n1 s2 \n2 s3 \n3
becomes:\n3
\n2
\n1
NULL s1
s2
s3
241-437 Compilers: Parse Tree/9 18
statement() Before and After
void statement(void)// statement ::= ( 'let' ID '=' EXPR ) | EXPR{ if (currToken == LET) { match(LET); match(ID); match(ASSIGNOP); expression(); } else expression();} // end of statement()
with no semantic actions
241-437 Compilers: Parse Tree/9 19
Tree *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()
241-437 Compilers: Parse Tree/9 21
expression() Before and After
void expression(void)// expression ::= term ( ('+'|'-') term )*{ term(); while((currToken == PLUSOP) ||
(currToken == MINUSOP)) { match(currToken); term(); }} // end of expression()
with no semantic actions
241-437 Compilers: Parse Tree/9 22
Tree *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()
241-437 Compilers: Parse Tree/9 23
Tree Structure for expression
• An expression sequence:t1 +1 t2 - t3 +2 t4
becomes:+2
-
+1
t1 t2
t3
t4
241-437 Compilers: Parse Tree/9 24
term() Before and After
void term(void)// term ::= factor ( ('*'|'/') factor )*{ factor(); while((currToken == MULTOP) ||
(currToken == DIVOP)) { match(currToken); factor(); }} // end of term()
with no semantic actions
241-437 Compilers: Parse Tree/9 25
Tree *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()
241-437 Compilers: Parse Tree/9 26
Tree Structure for term
• An term sequence:f1 *1 f2 / f3 *2 f4
becomes:*2
/
*1
f1 f2
f3
f4
241-437 Compilers: Parse Tree/9 27
factor() Before and After
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()
with no semantic actions
241-437 Compilers: Parse Tree/9 28
Tree *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()
241-437 Compilers: Parse Tree/9 29
Match an ID (Extended)
Tree *matchId(void){ Tree *t; if (currToken == ID) t = makeIDLeaf(tokString); match(ID); return t;} // end of matchID()
241-437 Compilers: Parse Tree/9 30
Tree Structure for factor
• There are three possible nodes:
IDnode
orINTnode
ortreenode
241-437 Compilers: Parse Tree/9 31
5. Tree Building
• The nodes in a parse tree are connected by the parse functions.
• A tree node can have three different shapes:
operTok
id
OR
value
OR
branches
TreeNode
a un
ion
left right
241-437 Compilers: Parse Tree/9 32
Making a Tree Node
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()
241-437 Compilers: Parse Tree/9 33
Making an ID Node
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 entrycreated yet
IDoperTok
"id str"id
241-437 Compilers: Parse Tree/9 34
Making an INT Node
Tree *makeIntLeaf(int value){ Tree *t; t = treeMalloc(); TreeOper(t) = INT; TreeValue(t) = value; return t;} // end of makeIntLeaf()
INToperTok
integervalue
241-437 Compilers: Parse Tree/9 35
Making a Node with ChildrenTree *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()
opoperTok
branches
left right
241-437 Compilers: Parse Tree/9 36
6. Tree Printing
• 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.
241-437 Compilers: Parse Tree/9 37
void printTree(Tree *t, int indent)// print a tree, indenting by indent spaces{ printIndent(indent);
if (t == NULL) { printf("NULL\n"); return; }
:
continued
241-437 Compilers: Parse Tree/9 38
Token tok = 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()
241-437 Compilers: Parse Tree/9 39
void printIndent(int n){ int spaces; for(spaces = 0; spaces != n; spaces++) putchar(' ');} // end of printIndent()
241-437 Compilers: Parse Tree/9 40
Tree Printing Examples> exprParse2 < test2.txt\n \n \n NULL = x56 2 = bing_BONG - * 27 2 x56
* 5 / 67 3
let x56 = 2let bing_BONG = (27 * 2) - x565 * (67 / 3)
241-437 Compilers: Parse Tree/9 41
Graphically\n
\n
\n
NULL =
x56 2
=
bing_BONG
-
*
27 2
x56
*
5
67 3
/
S1S2
S3
241-437 Compilers: Parse Tree/9 42
test3.txt
5 + 6let x = 23 + ( (x*y)/2) // comments// ylet x = 5let y = x /0
// comments
241-437 Compilers: Parse Tree/9 43
> exprParse2 < test3.txt\n \n \n \n \n NULL + 5 6 = x 2
+ 3 / * x y 2 = x 5 = y / x 0
241-437 Compilers: Parse Tree/9 44
7. Tree Evaluation
• 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
241-437 Compilers: Parse Tree/9 45
Finding non-NEWLINEs\n
\n
\n
NULL =
x56 2
=
bing_BONG
-
*
27 2
x56
*
5
67 3
/
evalTree()used here
eval() used here
241-437 Compilers: Parse Tree/9 46
Codevoid 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()
241-437 Compilers: Parse Tree/9 47
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; }
:
The operator canbe one of ID, INT,ASSIGNOP,PLUSOP, MINUSOP,MULTOP, DIVOP
continued
7 possibilities
241-437 Compilers: Parse Tree/9 48
else if (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)); :
241-437 Compilers: Parse Tree/9 49
else if (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()
241-437 Compilers: Parse Tree/9 50
SymbolInfo *evalID(Tree *t){ char *id = TreeID(t); return getIDEntry(id);
// create sym. table entry for id} // end of evalID()
this function finds or creates asymbol table entry for the id, andreturn a pointer to the entry(same as in exprParse1.c)
241-437 Compilers: Parse Tree/9 51
Evaluation Examples
$ ./exprParse2 < test1.txt :x declaredx = 2== 2y declaredy = 5== 5
let x = 2 let y = 3 + x
241-437 Compilers: Parse Tree/9 52
$ ./exprParse2 < test2.txt :x56 declaredx56 = 2== 2bing_BONG declaredbing_BONG = 52== 52== 110
// test2.txt example
let x56 = 2let bing_BONG = (27 * 2) - x56
5 * (67 / 3)
top related