?? analyze.c
字號:
/****************************************************/
/* File: analyze.c */
/* Semantic analyzer implementation */
/* for the TINY compiler */
/* Compiler Construction: Principles and Practice */
/* Kenneth C. Louden */
/****************************************************/
#include "globals.h"
#include "symtab.h"
#include "analyze.h"
/* counter for variable memory locations */
static int location = 0;
/* Procedure traverse is a generic recursive
* syntax tree traversal routine:
* it applies preProc in preorder and postProc
* in postorder to tree pointed to by t
*/
static void traverse(TreeNode * t, void(* preProc)(TreeNode *),
void(* postProc)(TreeNode *))
{
if (t != NULL)
{
preProc(t);
{
int i;
for (i = 0; i < MAXCHILDREN; i++)
traverse(t->child[i], preProc, postProc);
}
postProc(t);
traverse(t->sibling, preProc, postProc);
}
}
/* nullProc is a do-nothing procedure to
* generate preorder-only or postorder-only
* traversals from traverse
*/
static void nullProc(TreeNode * t)
{
if (t == NULL)
return;
else
return;
}
/* Procedure insertNode inserts
* identifiers stored in t into
* the symbol table
*/
static void insertNode(TreeNode * t)
{
switch (t->nodekind)
{
case StmtK:
switch (t->kind.stmt)
{
case AssignK:
case ReadK:
if (st_lookup(t->attr.name) == -1)
/* not yet in table, so treat as new definition */
st_insert(t->attr.name, t->lineno, location++);
else
/* already in table, so ignore location,
add line number of use only */
st_insert(t->attr.name, t->lineno, 0);
break;
default:
break;
}
break;
case ExpK:
switch (t->kind.exp)
{
case IdK:
if (st_lookup(t->attr.name) == -1)
/* not yet in table, so treat as new definition */
st_insert(t->attr.name, t->lineno, location++);
else
/* already in table, so ignore location,
add line number of use only */
st_insert(t->attr.name, t->lineno, 0);
break;
default:
break;
}
break;
default:
break;
}
}
/* Function buildSymtab constructs the symbol
* table by preorder traversal of the syntax tree
*/
void buildSymtab(TreeNode * syntaxTree)
{
traverse(syntaxTree, insertNode, nullProc);
if (TraceAnalyze)
{
fprintf(listing, "\nSymbol table:\n\n");
printSymTab(listing);
}
}
static void typeError(TreeNode * t, char * message)
{
fprintf(listing, "Type error at line %d: %s\n", t->lineno, message);
Error = TRUE;
}
/* Procedure checkNode performs
* type checking at a single tree node
*/
static void checkNode(TreeNode * t)
{
switch (t->nodekind)
{
case ExpK:
switch (t->kind.exp)
{
case OpK:
if ((t->child[0]->type != Integer)
|| (t->child[1]->type != Integer))
typeError(t, "Op applied to non-integer");
if ((t->attr.op == EQ) || (t->attr.op == LT))
t->type = Boolean;
else
t->type = Integer;
break;
case ConstK:
case IdK:
t->type = Integer;
break;
default:
break;
}
break;
case StmtK:
switch (t->kind.stmt)
{
case IfK:
if (t->child[0]->type == Integer)
typeError(t->child[0], "if test is not Boolean");
break;
case AssignK:
if (t->child[0]->type != Integer)
typeError(t->child[0], "assignment of non-integer value");
break;
case WriteK:
if (t->child[0]->type != Integer)
typeError(t->child[0], "write of non-integer value");
break;
case RepeatK:
if (t->child[1]->type == Integer)
typeError(t->child[1], "repeat test is not Boolean");
break;
default:
break;
}
break;
default:
break;
}
}
/* Procedure typeCheck performs type checking
* by a postorder syntax tree traversal
*/
void typeCheck(TreeNode * syntaxTree)
{
traverse(syntaxTree, nullProc, checkNode);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -