/*********以下程序只完成了部分静态语义检查,需自行补充完整*******************/ #include #include "def.h" #define YYSTYPE int //此行是为了包含parser.tab.hpp不引起错误而加,可以在后面使用相关常量 #include "parser.tab.hpp" SymbolStackDef AST::SymbolStack = SymbolStackDef(); //初始化静态成员符号表 FunctionCallTable AST::functionCallTable = FunctionCallTable(); map TypeWidth = {{T_CHAR, 1}, {T_INT, 4}, {T_FLOAT, 8}}; //各类型所占字节数 map KindName = {{'V', "变量"}, {'F', "函数"}, {'P', "形参"}, {'A', "数组"}}; //各类型所占字节数 vectorErrors::Errs = {}; void Errors::ErrorAdd(int Line, int Column, string ErrMsg) { Error e = {Line, Column, std::move(ErrMsg)}; Errs.push_back(e); } void Errors::ErrorsDisplay() { for (const auto& a: Errs) cout << "第" << a.Line << "行、第" << a.Column << "列处错误: " << a.ErrMsg << endl; } string NewAlias() { static int num = 0; return "V_" + to_string(++num); } void DisplaySymbolTable(SymbolStackDef *SYM) { for (auto i = 0; i < SYM->Symbols.size(); i++) { cout << "----------------------------------------------------------------------" << endl; cout << " 层号: " << i << endl; cout << " 符 号 名 别名 类型 种 类 其它信息" << endl; cout << "----------------------------------------------------------------------" << endl; if (SYM->Symbols.at(i)->Symbols.empty()) cout << " 空 表" << endl; else for (auto SymPtr : SYM->Symbols.at(i)->Symbols) { //取第i层第j个符号对象的指针 cout.width(20); cout << SymPtr->Name; cout.width(8); if (SymPtr->Kind == 'V' || SymPtr->Kind == 'A' || SymPtr->Kind == 'P') //符号是变量,形参,显示别名 cout << ((VarSymbol *) SymPtr)->Alias; else cout << " "; cout.width(8); cout << SymbolMap[SymPtr->Type]; cout.width(8); cout << KindName[SymPtr->Kind]; if (SymPtr->Kind == 'V' || SymPtr->Kind == 'P') //符号是变量,形参 cout << "偏移量: " << ((VarSymbol *) SymPtr)->Offset << " 全局: " << ((VarSymbol *) SymPtr)->isGolbal; else if (SymPtr->Kind == 'F') //符号是函数 { cout << "形参数: " << ((FuncSymbol *) SymPtr)->ParamNum; cout << " 变量空间: " << ((FuncSymbol *) SymPtr)->ARSize; } else if (SymPtr->Kind == 'A') //符号是数组,需要显示各维大小 { cout << "偏移量: " << ((VarSymbol *) SymPtr)->Offset << " 全局: " << ((VarSymbol *) SymPtr)->isGolbal << " "; cout << ((VarSymbol *) SymPtr)->Dims.size() << "维:"; for (int Dim : ((VarSymbol *) SymPtr)->Dims) cout << Dim << " "; } cout << endl; } cout << "----------------------------------------------------------------------" << endl; } } bool IsLeftValue(ExpAST *PExp) { if (typeid(*PExp) == typeid(VarAST)) return true; //对简单变量、数组下标变量,需要查符号表 return false; } bool IsConstValue(ExpAST *PExp) { if (typeid(*PExp) == typeid(ConstAST)) return true; return false; } Symbol *SymbolStackDef::LocateNameCurrent(const string& Name) //在当前(最内层)作用域中查找该符号是否有定义 { SymbolsInAScope *curScope = Symbols.back(); for (auto & Symbol : curScope->Symbols) if (Symbol->Name == Name) return Symbol; return nullptr; } Symbol *SymbolStackDef::LocateNameGlobal(const string& Name)//由内向外,整个符号表中查找该符号是否有定义 { for (int i = Symbols.size() - 1; i >= 0; i--) { for (auto & Symbol : Symbols.at(i)->Symbols) if (Symbol->Name == Name) return Symbol; } return nullptr; } void FunctionCallTable::addFuncCalls(int Line, int Column, string Name) { FunctionCall FuncCall(Line, Column, std::move(Name)); FuncCalls.push_back(FuncCall); return; } void FunctionCallTable::deleteFuncCalls(string Name) { for (auto fC = FuncCalls.begin(); fC != FuncCalls.end(); fC++) if (fC->Name == Name) { FuncCalls.erase(fC--); } } void ProgAST::Semantics0() { int Offset = 0; Semantics(Offset); Errors::ErrorsDisplay(); } void ProgAST::Semantics(int &Offset) { auto *Global = new SymbolsInAScope(); //全局变量的作用域符号表,记录外部变量、函数名 SymbolStack.Symbols.push_back(Global); GlobalSymbolTable = Global; //程序对象挂一个全局符号表 //预先设置缺省函数read和write auto *FuncDefPtr = new FuncSymbol(); FuncDefPtr->Name = string("read"); FuncDefPtr->Type = T_INT; FuncDefPtr->Kind = 'F'; FuncDefPtr->ParamNum = 0; FuncDefPtr->ARSize = 12; FuncDefPtr->Declaration = 0; SymbolStack.Symbols.back()->Symbols.push_back(FuncDefPtr); FuncDefPtr = new FuncSymbol(); FuncDefPtr->Name = string("write"); FuncDefPtr->Type = T_VOID; FuncDefPtr->Kind = 'F'; FuncDefPtr->ParamNum = 1; FuncDefPtr->ARSize = 4; FuncDefPtr->Declaration = 0; SymbolStack.Symbols.back()->Symbols.push_back(FuncDefPtr); auto *VarDefPtr = new VarSymbol(); VarDefPtr->Name = VarDefPtr->Alias = string("x"); VarDefPtr->Type = T_INT; VarDefPtr->Kind = 'P'; VarDefPtr->Offset = 4; SymbolStack.Symbols.back()->Symbols.push_back(VarDefPtr); for (auto a: ExtDefs) { a->Semantics(Offset); } if (!functionCallTable.FuncCalls.empty()) { for (auto fC: (functionCallTable.FuncCalls)) Errors::ErrorAdd(fC.Line, fC.Column, "调用的函数未定义"); } DisplaySymbolTable(&SymbolStack); } void ExtVarDefAST::Semantics(int &Offset) //外部定义对象的语义 { int GlobalOffset = 0; for (auto a: ExtVars) a->Semantics(Offset, GlobalOffset, Type); } void VarDecAST::Semantics(int &Offset, TypeAST *Type) { if (!SymbolStack.LocateNameCurrent(Name)) //当前作用域未定义,将变量加入符号表 { VarDefPtr = new VarSymbol(); VarDefPtr->Name = Name; VarDefPtr->Dims = Dims; VarDefPtr->isGolbal = 0; VarDefPtr->Alias = NewAlias(); if (typeid(*Type) == typeid(BasicTypeAST)) VarDefPtr->Type = ((BasicTypeAST *) Type)->Type; VarDefPtr->Offset = Offset; if (!Dims.size()) { VarDefPtr->Kind = 'V'; Offset += TypeWidth[VarDefPtr->Type]; } else { VarDefPtr->Kind = 'A'; int ans = 1; for (int i = 0; i < Dims.size(); i++) ans *= Dims[i]; Offset += ans * TypeWidth[VarDefPtr->Type]; } if (Exp) //有初值表达式时的处理 { Exp->Semantics(Offset); if (Dims.size()) Errors::ErrorAdd(Line, Column, "数组用表达式初始化"); } SymbolStack.Symbols.back()->Symbols.push_back(VarDefPtr); } else Errors::ErrorAdd(Line, Column, "变量 " + Name + " 重复定义"); } void VarDecAST::Semantics(int &Offset, int &GolbalOffset, TypeAST *Type) { if (!SymbolStack.LocateNameCurrent(Name)) //当前作用域未定义,将变量加入符号表 { VarDefPtr = new VarSymbol(); VarDefPtr->Name = Name; VarDefPtr->Dims = Dims; VarDefPtr->isGolbal = 1; VarDefPtr->Alias = NewAlias(); if (typeid(*Type) == typeid(BasicTypeAST)) VarDefPtr->Type = ((BasicTypeAST *) Type)->Type; VarDefPtr->Offset = GolbalOffset; if (!Dims.size()) { VarDefPtr->Kind = 'V'; GolbalOffset += TypeWidth[VarDefPtr->Type]; } else { VarDefPtr->Kind = 'A'; int ans = 1; for (int i = 0; i < Dims.size(); i++) ans *= Dims[i]; GolbalOffset += ans * TypeWidth[VarDefPtr->Type]; } SymbolStack.Symbols.back()->Symbols.push_back(VarDefPtr); } else Errors::ErrorAdd(Line, Column, "变量 " + Name + " 重复定义"); } void DefAST::Semantics(int &Offset) { //依次提取变量符号进行语义分析 for (auto a: LocVars) a->Semantics(Offset, Type); } void BasicTypeAST::Semantics(int &Offset) { } void FuncDefAST::Semantics(int &Offset) { if (!SymbolStack.LocateNameCurrent(Name)) //当前作用域未定义,将变量加入符号表 { int Offset = 12; //局部变量偏移量初始化,预留12个字节存放返回地址等信息,可根据实际情况修改 MaxVarSize = 12; //计算函数变量需要的最大容量 FuncDefPtr = new FuncSymbol(); FuncDefPtr->Name = Name; FuncDefPtr->Kind = 'F'; if (typeid(*Type) == typeid(BasicTypeAST)) //处理符号项的返回类型,目前仅基本类型T_CHAR,T_INT,T_FLOAT FuncDefPtr->Type = ((BasicTypeAST *) Type)->Type; FuncDefPtr->ParamNum = Params.size(); FuncDefPtr->Params = Params; if (Body) { SymbolsInAScope *Local = new SymbolsInAScope(); //生成函数体作用域变量表 FuncDefPtr->ParamPtr = Local; //函数符号表项,指向形参 SymbolStack.Symbols.back()->Symbols.push_back(FuncDefPtr);//填写函数符号到符号表 SymbolStack.Symbols.push_back(Local); //函数体符号表(含形参)进栈 for (auto a: Params) a->Semantics(Offset); //未考虑参数用寄存器,只是简单在AR中分配单元 Body->LocalSymbolTable = Local; int isReturn = 0; Body->Semantics(Offset, 0, 0, isReturn, ((BasicTypeAST *) Type)->Type); //对函数中的变量,在AR中接在参数后分配单元 if (isReturn == 0 && ((BasicTypeAST *) Type)->Type != T_VOID) Errors::ErrorAdd(Line, Column, "函数没有返回语句"); FuncDefPtr->ARSize = MaxVarSize; //函数变量需要空间大小(未考虑临时变量),后续再加临时变量单元得到AR大小 FuncDefPtr->Declaration = 0; } else { FuncDefPtr->Declaration = 1; FuncDefPtr->ARSize = MaxVarSize; SymbolStack.Symbols.back()->Symbols.push_back(FuncDefPtr);//填写函数符号到符号表 } } else if (((FuncSymbol *) SymbolStack.LocateNameCurrent(Name))->Declaration == 1 && Body) { int Offset = 12; //局部变量偏移量初始化,预留12个字节存放返回地址等信息,可根据实际情况修改 MaxVarSize = 12; //计算函数变量需要的最大容量 FuncDefPtr = ((FuncSymbol *) SymbolStack.LocateNameCurrent(Name)); if (((BasicTypeAST *) Type)->Type != FuncDefPtr->Type) Errors::ErrorAdd(Line, Column, "函数声明和定义的返回类型不同"); if (FuncDefPtr->ParamNum != Params.size()) Errors::ErrorAdd(Line, Column, "函数声明和定义的参数数目不同"); auto *Local = new SymbolsInAScope(); //生成函数体作用域变量表 FuncDefPtr->ParamPtr = Local; //函数符号表项,指向形参 SymbolStack.Symbols.push_back(Local); //函数体符号表(含形参)进栈 int i = 0; for (auto a: Params) { a->Semantics(Offset); //未考虑参数用寄存器,只是简单在AR中分配单元 auto *param = (ParamAST *) ((FuncDefPtr->Params).at(i++)); if (((BasicTypeAST *) (param->Type))->Type != ((BasicTypeAST *) (a->Type))->Type) { Errors::ErrorAdd(Line, Column, "函数声明和定义的形参类型不一致 "); break; } } Body->LocalSymbolTable = Local; int isReturn = 0; Body->Semantics(Offset, 0, 0, isReturn, ((BasicTypeAST *) Type)->Type); //对函数中的变量,在AR中接在参数后分配单元 if (isReturn == 0 && ((BasicTypeAST *) Type)->Type != T_VOID) Errors::ErrorAdd(Line, Column, "函数没有返回语句"); FuncDefPtr->ARSize = MaxVarSize; //函数变量需要空间大小(未考虑临时变量),后续再加临时变量单元得到AR大小 FuncDefPtr->Declaration = 0; functionCallTable.deleteFuncCalls(Name); } else Errors::ErrorAdd(Line, Column, "函数 " + Name + " 重复声明或定义"); } void FuncCallAST::Semantics(int &Offset) { if (FuncRef = (FuncSymbol *) SymbolStack.LocateNameGlobal(Name)) { if (FuncRef->Kind != 'F') Errors::ErrorAdd(Line, Column, "对非函数名采用函数调用形式 "); else if (FuncRef->ParamNum != Params.size()) Errors::ErrorAdd(Line, Column, "实参表达式个数和形参不一致 "); else { int i = 0; Type = FuncRef->Type; for (auto a: Params) { //未考虑参数用寄存器,只是简单在AR中分配单元 a->Semantics(Offset); if (Name != "write") { auto *param = (ParamAST *) ((FuncRef->Params).at(i++)); if (((BasicTypeAST *) (param->Type))->Type != a->Type) { Errors::ErrorAdd(Line, Column, "实参表达式类型和形参不一致 "); break; } } } if (FuncRef->Declaration == 1) functionCallTable.addFuncCalls(Line, Column, Name); } } else Errors::ErrorAdd(Line, Column, "引用未定义的函数 " + Name); } void ParamAST::Semantics(int &Offset) { if (!SymbolStack.LocateNameCurrent(ParamName->Name)) //当前作用域未重复定义,将形参名加入符号表 { auto *SymPtr = new VarSymbol(); SymPtr->Name = ParamName->Name; SymPtr->Kind = 'P'; SymPtr->Alias = NewAlias(); if (typeid(*Type) == typeid(BasicTypeAST)) SymPtr->Type = ((BasicTypeAST *) Type)->Type; SymPtr->Offset = Offset; Offset += TypeWidth[SymPtr->Type]; SymbolStack.Symbols.back()->Symbols.push_back(SymPtr); } else Errors::ErrorAdd(Line, Column, "形参名 " + ParamName->Name + " 重复定义"); } /**************语句显示******************************/ void CompStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { if (!LocalSymbolTable) //如果不是函数体的复合语句,需自行生成局部符号表 { auto *Local = new SymbolsInAScope(); //全局变量的作用域符号表,记录外部变量、函数名 SymbolStack.Symbols.push_back(Local); LocalSymbolTable = Local; //程序对象挂一个符号表 } for (auto a: Decls) a->Semantics(Offset); if (Offset > MaxVarSize) MaxVarSize = Offset; for (auto a: Stms) { int Offset_S = Offset; //前后并列语句可以使用同一片单元,所以取最大值,这里保存起始偏移量 a->Semantics(Offset, canBreak, canContinue, isReturn, returnType); if (Offset > MaxVarSize) MaxVarSize = Offset; Offset = Offset_S; } cout << "\n\n********************当前复合语句符号表状态**************************" << endl; DisplaySymbolTable(&SymbolStack); cout << endl << endl; SymbolStack.Symbols.pop_back(); //复合语句的符号表退栈 } void ExprStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { Exp->Semantics(Offset); } void IfStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { Cond->Semantics(Offset); ThenStm->Semantics(Offset, canBreak, canContinue, isReturn, returnType); } void IfElseStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { Cond->Semantics(Offset); ThenStm->Semantics(Offset, canBreak, canContinue, isReturn, returnType); ElseStm->Semantics(Offset, canBreak, canContinue, isReturn, returnType); } void WhileStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { Cond->Semantics(Offset); Body->Semantics(Offset, 1, 1, isReturn, returnType); } void ForStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { SinExp->Semantics(Offset); Cond->Semantics(Offset); EndExp->Semantics(Offset); Body->Semantics(Offset, 1, 1, isReturn, returnType); } void CaseStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { Cond->Semantics(Offset); if (!IsConstValue(Cond)) Errors::ErrorAdd(Line, Column, "case中不是常量"); for (auto a: Body) { int Offset_S = Offset; //前后并列语句可以使用同一片单元,所以取最大值,这里保存起始偏移量 a->Semantics(Offset, 1, canContinue, isReturn, returnType); if (Offset > MaxVarSize) MaxVarSize = Offset; Offset = Offset_S; } } void SwitchStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { Exp->Semantics(Offset); for (auto a: Cases) a->Semantics(Offset, 1, canContinue, isReturn, returnType); for (auto a: Cases) { int EqualNum = 0; for (auto b: Cases) { if (((ConstAST *) (a->Cond))->ConstVal.constCHAR == ((ConstAST *) (b->Cond))->ConstVal.constCHAR && ((ConstAST *) (a->Cond))->ConstVal.constFLOAT == ((ConstAST *) (b->Cond))->ConstVal.constFLOAT && ((ConstAST *) (a->Cond))->ConstVal.constINT == ((ConstAST *) (b->Cond))->ConstVal.constINT) EqualNum++; } if (EqualNum > 1) Errors::ErrorAdd(Line, Column, "switch语句的key值相等"); } for (auto a: Default) { int Offset_S = Offset; //前后并列语句可以使用同一片单元,所以取最大值,这里保存起始偏移量 a->Semantics(Offset, 1, canContinue, isReturn, returnType); if (Offset > MaxVarSize) MaxVarSize = Offset; Offset = Offset_S; } } void ReturnStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { if (Exp) Exp->Semantics(Offset); if ((returnType == T_VOID && Exp) || (returnType != T_VOID && !Exp) || (returnType != T_VOID && Exp && returnType != Exp->Type)) Errors::ErrorAdd(Line, Column, "函数返回值类型与函数定义的返回值类型不匹配"); isReturn = 1; } void BreakStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { if (canBreak == 0) Errors::ErrorAdd(Line, Column, "break语句不在循环语句或switch语句中"); } void ContinueStmAST::Semantics(int &Offset, int canBreak, int canContinue, int &isReturn, BasicTypes returnType) { if (canContinue == 0) Errors::ErrorAdd(Line, Column, "continue语句不在循环语句中"); } /**************表达式显示******************************/ void VarAST::Semantics(int &Offset) { if ((VarRef = (VarSymbol *) SymbolStack.LocateNameGlobal(Name))) //如果是函数名,报错, if (VarRef->Kind == 'F') Errors::ErrorAdd(Line, Column, "对函数名采用非函数调用形式访问 "); //简单变量则提取变量类型属性 else { Type = VarRef->Type; if (VarRef->Kind == 'V' && index.size() > 0) Errors::ErrorAdd(Line, Column, "对非数组变量采用下标变量的形式访问"); else if (VarRef->Kind == 'A') { if (index.size() != VarRef->Dims.size()) Errors::ErrorAdd(Line, Column, "数组维数不正确"); for (auto a: index) { a->Semantics(Offset); if (a->Type != T_INT) Errors::ErrorAdd(Line, Column, "数组变量的下标不是整型表达式"); } } } else Errors::ErrorAdd(Line, Column, "引用未定义的符号 " + Name); } void ConstAST::Semantics(int &Offset) { //提取类型属性 } void AssignAST::Semantics(int &Offset) { LeftValExp->Semantics(Offset); if (!IsLeftValue(LeftValExp)) Errors::ErrorAdd(Line, Column, "非左值表达式赋值"); RightValExp->Semantics(Offset); if (LeftValExp->Type == T_VOID || RightValExp->Type == T_VOID) Errors::ErrorAdd(Line, Column, "弱类型语言里void类型也不允许赋值"); Type = LeftValExp->Type; } void BinaryExprAST::Semantics(int &Offset) { LeftExp->Semantics(Offset); RightExp->Semantics(Offset); if (LeftExp->Type == T_VOID || RightExp->Type == T_VOID) Errors::ErrorAdd(Line, Column, "弱类型语言里void类型也不允许计算"); if (LeftExp->Type == T_FLOAT || RightExp->Type == T_FLOAT) Type = T_FLOAT; else if (LeftExp->Type == T_INT || RightExp->Type == T_INT) Type = T_INT; else if (LeftExp->Type == T_CHAR && RightExp->Type == T_CHAR) Type = T_CHAR; //根据左右值类型,判断是否能进行运算,并确定运算结果类型 } void UnaryExprAST::Semantics(int &Offset) { Exp->Semantics(Offset); if (!IsLeftValue(Exp) && (Op != UPLUS && Op != UMINUS && Op != NOT)) Errors::ErrorAdd(Line, Column, "非左值表达式自增、自减"); Type = Exp->Type; }