📄 analyzer.cpp
字号:
#include "Analyzer.h"
// initial the static member here
//-----------------------------------------------------------------------------
symTable Analyzer::symbolTab;
FunArgsCheck Analyzer::FunArgs;
int Analyzer::location=0;
int Analyzer::err=0;
int Analyzer::warn=0;
// constructer
//-----------------------------------------------------------------------------
Analyzer::Analyzer(const string &filename):traceAnalyze(true), traceParse(true)
{
parse = new Parser(filename);
program = NULL;
symbolTab.initial(); // because symbolTab and FunArgs is static member,
FunArgs.initial(); // so, before use , should reset/initial them
symFile = filename;
int pos = symFile.rfind('.');
symFile.erase(pos, symFile.length()-1);
symFile += ".tab"; // symbol table file
is_good_ = true;
location = 0; // intial memory location
err = 0; // there are static member, should initial before use
warn = 0;
}
//-----------------------------------------------------------------------------
Analyzer::~Analyzer()
{
if (parse) delete parse;
}
bool Analyzer::is_good() const
{
return (is_good_ && (err <= 0) && (warn <= 0) && parse->is_good());
}
/**: getSymbolFile
&
* 主要接口,直接用来构造语法树,完成语义分析, 得到结果,
* 即,符号表。
*/
//-----------------------------------------------------------------------------
void Analyzer::getSymbolFile()
{
outputMsg(-1, "building syntax tree...");
program = parse->BuildSyntaxTree();
if (parse->is_good())
{
parse->getListFile();
if (traceParse) parse->getTreeFile();
//outputMsg(-1, "successfully build the syntax tree!");
outputMsg(-1, "constructing symbol table and type cheching...");
/* 语法树文件可以完全在后面生成,但是总出错, 不得不放在这里,
* 再加上我调试器坏了,实在没有办法调试了,似乎错误出现在
* Parser::PrintTree(TreeNode *pNode) 函数中的一条 if 语句,
* 我没有跟踪内存数据的变化,调试器有问题,,
* 算了, 放在这里虽然布局比较凌乱,但是还算是效果满意!! 呵呵
*/
buildSymtab(program);
if (is_good()) // if no parse error ..
{
//outputMsg(-1, "now, type checking...");
typeCheck(program);
if (is_good()) outputMsg(-1, "type check is done, its no error(s)!");
else outputMsg(-1, "error(s) occur while type checking!");
}
else
{
outputMsg(-1, "errors occur while constructing symbol table, stop type checking!");
}
if (traceAnalyze && is_good()) // if has no parse and ananlyze error
{
//outputMsg(-1, "symbol table complated, printing symbol table file ...");
symbolTab.printSymTable(symFile);
}
}
else
{
outputMsg(-1, "errors occur while parsing, stop constructing symbol table!");
err++; // only list file
parse->getListFile();
}
}
/**: buildSymtab(TreeNode *pNode)
&
* Function buildSymtab constructs the symbol
* table by preorder traversal of the syntax tree
&
* author: lonelyforest.
* data: 2006.04.08
*/
//-----------------------------------------------------------------------------
void Analyzer::buildSymtab(TreeNode *pNode)
{
traverse(pNode, insertNode, nullProc);
}
/* Procedure typeCheck performs type checking
* by a postorder syntax tree traversal
*/
//-----------------------------------------------------------------------------
void Analyzer::typeCheck(TreeNode *pNode)
{
traverse(pNode, nullProc, checkNode);
if ( symbolTab.lookup("main", "global") == -1)
{
err++;
is_good_ = false;
outputMsg(-1, "Unresolved external symbol _main");
warn++;
outputMsg(-1, "program must have function \"main(void)\" !");
}
}
/*---------------------------------------------------------------------------*/
void Analyzer::nullProc(TreeNode *pNode)
{
return;
}
//-----------------------------------------------------------------------------
void Analyzer::traverse(TreeNode *t,
void(*preProc)(TreeNode *),
void (*postProc)(TreeNode *))
{
if (t)
{
preProc(t);
for (int i = 0; i < MAX_CHILDREN; ++i)
{
traverse( t->child[i], preProc, postProc);
}
postProc(t);
traverse( t->sibling, preProc, postProc );
}
}
//-----------------------------------------------------------------------------
void Analyzer::insertNode(TreeNode *t)
{
if (!t) return;
switch (t->nodekind ){
case funK:
if ( symbolTab.lookup(t->name, t->scope) == -1)
{
symbolTab.insert(t->name, t->scope, t->type, t->lineno, location, false);
addMemLoc();
FunArgs.insert(t);
}
else
{
//Analyzer::parse->add_err();
err++;
sprintf(msg_temp, "function \"%s\"(...) redefinition", t->name.c_str());
outputMsg(t->lineno, msg_temp);
}
break;
case varK:
case paramK:
if (symbolTab.lookup(t->name, t->scope) == -1)
{
symbolTab.insert(t->name, t->scope, t->type, t->lineno, location, t->bArr);
addMemLoc();
}
else
{
err++;
sprintf(msg_temp, "variable \"%s\" redefinition", t->name.c_str());
outputMsg(t->lineno, msg_temp);
}
break;
case stmtK: // just call
if (t->kind.stmt == callK)
{
if (symbolTab.lookup(t->name, t->scope) == -1)
{
err++;
sprintf(msg_temp, "unresolved external symbol \"%s\"", t->name.c_str());
outputMsg(t->lineno, msg_temp);
}
else
{
symbolTab.insert(t->name, t->scope, k_ID, t->lineno, 0, false);
}
}
break;
case expK:
if (t->kind.exp == IDK) {
if ( symbolTab.lookup(t->name, t->scope) == -1
&& symbolTab.lookup(t->name, "global") == -1)
{ // undeclared
//Analyzer::parse->add_err();
err++;
sprintf(msg_temp, "undeclared identifier: \"%s\"", t->name.c_str());
outputMsg(t->lineno, msg_temp);
}
else if (symbolTab.lookup(t->name, t->scope) != -1)
{ // local variable
if( t->father && (t->father->nodekind != stmtK || t->father->kind.stmt != callK)/* not in call statement */ &&
t->bArr != symbolTab.search_arr(t->name,t->scope))
{
//Analyzer::parse->add_err();
err++;
sprintf(msg_temp, "\"%s\" is %s declared as array", t->name.c_str(), t->bArr? "not" : "");
outputMsg(t->lineno, msg_temp);
}
else
{
symbolTab.insert(t->name, t->scope, t->type, t->lineno, 0, false);
}
}
else
{ // global variable
t->scope = "global";
if( t->father && (t->father->nodekind != stmtK || t->father->kind.stmt != callK)/* not in call statement */ &&
t->bArr != symbolTab.search_arr(t->name, t->scope) ) {
//Analyzer::parse->add_err();
err++;
sprintf(msg_temp, "\"%s\" is %s declared as array", t->name.c_str(), t->bArr? "not" : "");
outputMsg(t->lineno, msg_temp);
}
else symbolTab.insert(t->name, t->scope, t->type, t->lineno, 0, false);
}
}
break;
default:
break;
}
}
/**: checkNode
&
* author: lonelyforest
* data: 2006.04.09
*/
//-----------------------------------------------------------------------------
void Analyzer::checkNode(TreeNode *pNode)
{
TreeNode *t;
string args;
int ret, oldline; // record the return value and function defined lineno if its defined.
// initial them
ret = oldline = -1;
args = "";
t = pNode;
switch (t->nodekind) {
case stmtK:
switch (t->kind.stmt) {
case readK:
if (t->child[0]) {
t->type = t->child[0]->type;
if (t->type != k_INT){
outputMsg(t->lineno, "read statement can only read a \"int\" value to a int variable!");
err++;
}
}
else
{
err++;
outputMsg(-1, "maybe compiler bug!");
}
break;
case writeK:
if (t->child[0]) {
t->type = t->child[0]->type;
if (t->type != k_INT){
outputMsg(t->lineno, "write statement can only output a \"int\" variable or a number output!");
err++;
}
}
else
{
err++;
outputMsg(-1, "maybe compiler bug!");
}
break;
case returnK:
if (t->child[0] == NULL) { // return should be a void
if (symbolTab.search_type(t->name, "global") != k_VOID) {
sprintf(msg_temp, " function \"int %s(...)\" must have return value ", t->name.c_str());
outputMsg(t->lineno, msg_temp);
err++;
}
}
break;
case callK:
ret = FunArgs.check(t, args, oldline);
if (ret != -3) // -3 is ok
{
err++;
warn++;
if (ret >= 0) {
sprintf(msg_temp,
"too few or many paramenters to call function \"%s(%s)\", its has %d params",
t->name.c_str(),
args.c_str(),
ret);
outputMsg(t->lineno, msg_temp);
// out put the functions' declaration,
sprintf(msg_temp,
"see the function \"%s(%s)\" declaration here!!",
t->name.c_str(),
args.c_str());
outputMsg(oldline, msg_temp);
} else if (ret == -1) {
sprintf(msg_temp, "function \"%s\"(...) has not declared before use it", t->name.c_str());
outputMsg(t->lineno, msg_temp);
} else {
sprintf(msg_temp,
" call function \"%s(%s)\" with no matched type paramenters!",
t->name.c_str(), args.c_str());
outputMsg(t->lineno, msg_temp);
sprintf(msg_temp,
"see the function \"%s(%s)\" declaration here!!",
t->name.c_str(),
args.c_str());
outputMsg(oldline, msg_temp);
}
}
else
{
t->type = symbolTab.search_type(t->name, t->scope);
}
break;
default:
break;
}
case expK:
switch (t->kind.exp) {
case OpK:
if (t->type == ASSIGN)
{
t->type = t->child[0]->type;
}
else
{
if (t->child[0]->type == k_VOID || t->child[1]->type == k_VOID)
{
err++;
outputMsg(t->lineno, "illegal use of type \"void\"");
}
else if ( t->child[0]->type == k_INT || t->child[1]->type == k_INT)
{
t->type = k_INT;
}
else
{
// ...
}
}
break;
case IDK:
t->type = symbolTab.search_type(t->name, t->scope);
t->bArr = symbolTab.search_arr(t->name, t->scope);
break;
default:
break;
}
break;
default:
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -