📄 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"
static void typeError(TreeNode * t, char * message);
/* 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);
}
}
static void defineError(TreeNode * t, char * message)
{
fprintf(listing,"Define error at line %d: %s\n",t->lineno,message);
Error = TRUE;
}
/* 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)
{
TreeNode*s=NULL;
switch (t->nodekind)
{
case StmtK:
switch (t->kind.stmt)
{
case IntK:
case BoolK:
case StringK:
if(st_lookup(t->child[0]->attr.name) == -1)
st_insertd(t->child[0]->attr.name,location++,t->type);
else
defineError(t->child[0],"Identifier redefined!");
for(s=t->child[0]->sibling;s!=NULL;s=s->sibling)
{
if(st_lookup(s->attr.name)==-1)
st_insertd(s->attr.name,location++,t->type);
else
defineError(s,"Identifier redefined!");
}
break;
case AssignK:
case ReadK:
if (st_lookup(t->attr.name) == -1)
defineError(t,"Identifier undefined!");
else
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)
defineError(t,"Identifier undefined!");
else
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]!=NULL&&t->child[1]!=NULL)
{
if (t->child[0]->type != t->child[1]->type)
typeError(t,"Types are not the same!");
}
if ((t->attr.op == EQ) || (t->attr.op == LT) || (t->attr.op == GT)
|| (t->attr.op == NGT) || (t->attr.op == NLT) || (t->attr.op == NOT)
|| (t->attr.op == AND) || (t->attr.op == OR))
t->type = Boolean;
else
t->type = Integer;
break;
case ConstK:
t->type = Integer;
break;
case IdK:
t->type = getType(t->attr.name);
break;
case StrK:
t->type = String;
break;
case BK:
t->type = Boolean;
break;
default:
break;
}
break;
case StmtK:
switch (t->kind.stmt)
{
case ReadK:
t->type = getType(t->attr.name);
if (t->type != Integer&&t->type != String&&t->type != Boolean)
typeError(t,"read of ID of illegal type!");
break;
case WhileK:
if (t->child[1]->type != Boolean)
typeError(t->child[1],"while test is not Boolean");
break;
case IfK:
if (t->child[0]->type != Boolean)
typeError(t->child[0],"if test is not Boolean");
break;
case AssignK:
t->type = getType(t->attr.name);
if (t->type != Integer&&t->type != String&&t->type != Boolean)
typeError(t,"assignment of ID of illegal type!");
if(t->type != t->child[0]->type)
typeError(t,"assignment of ID of different types!");
break;
case WriteK:
t->type = getType(t->child[0]->attr.name);
if (t->type != Integer&&t->type != String&&t->type != Boolean)
typeError(t,"write of ID of illegal type!");
break;
case RepeatK:
if (t->child[1]->type != Boolean)
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 + -