📄 analyze.c
字号:
/* analyze.c
* Semantic analyzer implementation for TINY compiler
*
* Compiler Construction: Principles and Practice
* Kenneth C. Louden
* 编译原理及实践
* (美) Kenneth C. Louden 著
* 冯博琴 冯岚 等译
* 机械工业出版社 IBSN 7-111-07703-2
* 源代码:zwf编辑并修订
*
*/
#include "globals.h"
#include "symtab.h"
#include "analyze.h"
/* counter for variable memory location */
static int location = 0;
/* Procedure traverse is a generic recursive
* syntax tree traversal rountine:
* 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 stores in t into
* the symbol table
*/
static void insertNode(TreeNode * t)
{
switch (t->nodekind) {
case StmtK:
switch (t->kind.stmt) {
case AssignK:
case ReadK:
/* not yet in table, so treat as new definition */
if (st_lookup(t->attr.name) == -1)
st_insert(t->attr.name, t->lineno, location++);
else
/* alraedy 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:
/* not yet in table, so treat as new definition */
if (st_lookup(t->attr.name) == -1)
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;
}
}
/* Function buildSymtab constructs the symbol
* table by preorder traversal of the syntax tree
*/
void buildSymtab(TreeNode * syntaxTree)
{
traverse(syntaxTree, insertNode, nullProc);
if (TraceAnalyze) {
#ifdef CHINESE
fprintf(listing, "\n符号表:\n\n");
#else
fprintf(listing, "\nSymbol table:\n\n");
#endif
printSymTab(listing);
}
}
static void typeError(TreeNode * t, char *msg)
{
#ifdef CHINESE
fprintf(listing, "类型错误, %d 行: %s\n", t->lineno, msg);
#else
fprintf(listing, "Type error at line %d: %s\n", t->lineno, msg);
#endif
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))
#ifdef CHINESE
typeError(t, "操作符未使用整数变量");
#else
typeError(t, "Op applied to non-integer");
#endif
if ((t->attr.op == EQ) || (t->attr.op == LT)
|| (t->attr.op == GT)
|| (t->attr.op == NE) || (t->attr.op == LE)
|| (t->attr.op == GE))
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 != Boolean)
#ifdef CHINESE
typeError(t->child[0], "如果判断语句未使用布尔变量");
#else
typeError(t->child[0], "if test is not Boolean");
#endif
break;
case AssignK:
if (t->child[0]->type != Integer)
#ifdef CHINESE
typeError(t->child[0], "赋值语句未使用整数变量");
#else
typeError(t->child[0], "assignment of non-integer value");
#endif
break;
case WriteK:
if (t->child[0]->type != Integer)
#ifdef CHINESE
typeError(t->child[0], "输出语句未使用整数变量");
#else
typeError(t->child[0], "write of non-integer vlue");
#endif
break;
case RepeatK:
if (t->child[1]->type != Boolean)
#ifdef CHINESE
typeError(t->child[0], "循环判断语句未使用布尔变量");
#else
typeError(t->child[0], "repeat test is not Boolean");
#endif
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 + -