Compiler Structures. 241437 , Semester 1 , 20112012. 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
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.
241437, Semester 1, 20112012
9. Creating and Evaluating a
Parse Tree
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
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.
Stats => ( [ Stat ] \n )*
Stat => let ID = Expr  Expr
Expr => Term ( (+   ) Term )*
Term => Fact ( (*  / ) Fact ) *
Fact => '(' Expr ')'  Int  Id
5 + 6
let x = 2
3 + ( (x*y)/2) // comments
// y
let x = 5
let y = x /0
// comments
continued
$ gcc Wall o exprParse2 exprParse2.c$ ./exprParse2 < test1.txt
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
x being declared tree, and evalTree() which evaluates it.
x = 2
== 2
y being declared
y = 5
== 5
>
evaluation of the
parse tree
typedef struct TreeNode {
Token operTok;
union {
char *id;
int value;
struct {struct TreeNode *left, *right;} branches;
} u;
} Tree;
A tree is made from TreeNodes.
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
#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)
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 Afterwith 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()
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()
s1 \n1 s2 \n2 s3 \n3
becomes:
\n3
\n2
s3
s2
\n1
s1
NULL
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()
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()
=
or
expr
tree
ID
node
expr
tree
with no semantic actions
void expression(void)
// expression ::= term ( ('+''') term )*
{
term();
while((currToken == PLUSOP)  (currToken == MINUSOP)) {
match(currToken);
term();
}
} // end of expression()
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()
t1 +1 t2  t3 +2 t4
becomes:
+2

t4
t3
+1
t2
t1
with no semantic actions
void term(void)
// term ::= factor ( ('*''/') factor )*
{
factor();
while((currToken == MULTOP)  (currToken == DIVOP)) {
match(currToken);
factor();
}
} // end of term()
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()
f1 *1 f2 / f3 *2 f4
becomes:
*2
/
f4
f3
*1
f2
f1
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()
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()
Tree *matchId(void)
{
Tree *t;
if (currToken == ID)
t = makeIDLeaf(tokString);
match(ID);
return t;
} // end of matchID()
tree
node
INT
node
ID
node
or
or
TreeNode
operTok
id
OR
value
a union
OR
left
right
branches
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()
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
operTok
INT
Tree *makeIntLeaf(int value)
{
Tree *t;
t = treeMalloc();
TreeOper(t) = INT;
TreeValue(t) = value;
return t;
} // end of makeIntLeaf()
integer
value
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
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
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()
void printIndent(int n) tree, and evalTree() which evaluates it.
{ int spaces;
for(spaces = 0; spaces != n; spaces++)
putchar(' ');
} // end of printIndent()
> 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 Exampleslet x56 = 2
let bing_BONG = (27 * 2)  x56
5 * (67 / 3)
\n
\n
*
/
5
\n
=
67
3
bing_BONG

S3
=
NULL
x56
*
x56
2
27
2
S1
S2
5 + 6
let x = 2
3 + ( (x*y)/2) // comments
// y
let x = 5
let y = x /0
// comments
> 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
\n
evalTree()
used here
\n
*
/
5
\n
=
67
3
bing_BONG

=
NULL
x56
*
x56
2
27
2
eval() used here
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()
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
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));
:
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()
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)
let x = 2
let y = 3 + x
$ ./exprParse2 < test1.txt
:
x declared
x = 2
== 2
y declared
y = 5
== 5
$ ./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)
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