引用:https://blog.csdn.net/lhfl911/article/details/61206047
在编写后,与引用处的代码进行对比参考过,借鉴了一些地方,并进行了完善。
实现包含:
1、使用地址进行比较(地址隐含了名称符号信息),比较两个类型名是否相同。2、使用Set。递归序列中,对重复类型声明、重复函数声明的检测(重复变量声明是允许的,非递归序列下,重复类型和函数也是允许的)。函数参数声明中对相同参数名的检测。结构声明中对相同成员名的检测。
3、在E_enventry中添加变量是否能被赋值标志,对for语句循环控制量的不正确赋值进行检测。
4、更小的作用域变量可以覆盖更大作用域的相同变量名的变量声明,这是合法的。例子见test37.tig。
完成对testcases里所有的例程进行解析。如有未发现的错误,敬请指正。
“Semant.c”的代码如下:
=========================================================================
#include "util.h"
#include "symbol.h" /* symbol table data structures */#include "absyn.h" /* abstract syntax data structures */
#include "types.h"
#include "env.h"
#include "errormsg.h"
#include "Semant.h"
#include <string.h>
#include "set.h"
unsigned char break_enable =0;
//值传递的方式
struct expty expTy(Tr_exp exp, Ty_ty ty){
struct expty e;e.exp = exp; e.ty = ty;return e;
}
struct expty transExp(S_table v_env, S_table t_env, A_exp exp);
Ty_ty actual_ty(Ty_ty ty){
Ty_ty t = ty;
while(ty&&(ty->kind == Ty_name)){
ty = ty->u.name.ty;
assert(ty!=t);
}
return ty;
}
int ty_compare(Ty_ty ty1, Ty_ty ty2){
Ty_ty t1 = actual_ty(ty1);
Ty_ty t2 = actual_ty(ty2);
return ( ((t1->kind == t2->kind)&&(t1->kind != Ty_record)&&(t1->kind != Ty_array))\
||( ( (t1->kind == Ty_nil)&&(t2->kind ==Ty_record) )||((t1->kind == Ty_record)&&(t2->kind == Ty_nil) ))
||(t1 == t2));
}
Ty_ty transField(S_table v_env, S_table t_env, Ty_fieldList record, S_symbol sym){
for(;record;record=record->tail){
if(record->head->name == sym){
break;
}
}
if(record) return record->head->ty;
else return NULL;
}
struct expty transVar(S_table v_env, S_table t_env, A_var var){
assert(var);
switch(var->kind){
case A_simpleVar:{
E_enventry e = S_look(v_env, var->u.simple);
if(e && (e->kind == E_varEntry)){
return expTy(NULL,actual_ty(e->u.var.ty));
}
else {
EM_error(var->pos, "undefined variable %s", S_name(var->u.simple));
}
return expTy(NULL,Ty_Int());
}
case A_fieldVar:{
struct expty t1 = transVar(v_env,t_env,var->u.field.var);
if(t1.ty->kind != Ty_record){
EM_error(var->u.field.var->pos, "need a record type.");
}
else {
Ty_ty ty1 = transField(v_env, t_env, t1.ty->u.record, var->u.field.sym);
if(ty1){
return expTy(NULL,actual_ty(ty1));
}
else {
EM_error(var->pos, "undefined field %s", S_name(var->u.field.sym));
}
}
return expTy(NULL,Ty_Int());
}
case A_subscriptVar:{
struct expty t1 = transVar(v_env,t_env,var->u.subscript.var);
if(t1.ty->kind != Ty_array){
EM_error(var->u.subscript.var->pos, "need a array type.");
}
else {
struct expty t2 = transExp(v_env, t_env, var->u.subscript.exp);
if(t2.ty->kind != Ty_int) EM_error(var->u.subscript.exp->pos, "need int val.");
return expTy(NULL, t1.ty->u.array);
}
return expTy(NULL,Ty_Int());
}
default:
assert(0);
}
}
void transFormals(S_table v_env, S_table t_env, Ty_tyList tlist, A_exp exp){
A_expList elist;
assert(exp->kind == A_callExp);
elist = exp->u.call.args;
//tlist 和 elist 都有可能为空
if((tlist ==NULL) ^ (elist ==NULL)){
EM_error(exp->pos, "%s Parameter num inconsistency.",S_name(exp->u.call.func));
return;
}
if(tlist == NULL)return;
for(;tlist&&elist;tlist = tlist->tail, elist = elist->tail){
struct expty t = transExp(v_env, t_env, elist->head);
//t不会返回空
if(!ty_compare(t.ty, tlist->head)){
EM_error(elist->head->pos, "Type inconsistency.");
}
}
if((tlist !=NULL) || (elist !=NULL)){
EM_error(exp->pos, "%s Parameter num inconsistency.",S_name(exp->u.call.func));
return;
}
return;
}
void transEfields(S_table v_env, S_table t_env, Ty_fieldList tlist, A_efieldList slist){
if(slist == NULL)return;
for(;slist;slist = slist->tail){
Ty_ty t = transField(v_env, t_env, tlist, slist->head->name);
if(t){
struct expty e = transExp(v_env, t_env, slist->head->exp);
if (!ty_compare(e.ty, t)){
EM_error(slist->head->exp->pos, "Expression type inconsistency with %s.",S_name(slist->head->name));
}
}
else {
EM_error(slist->head->exp->pos, "undefined field %s", S_name(slist->head->name));
}
}
}
Ty_tyList makeFormalTyList(S_table t_env, A_fieldList ls, Set s){
if(ls){
//为保持跟之后参数变量调用时顺序一致,这里使用递归,并且设定从头的顺序排除后面重复名的变量
if(!Set_Push(s, ls->head->name)){
EM_error(ls->head->pos, "param name:%s is repeated.",S_name(ls->head->name));
return makeFormalTyList(t_env,ls->tail, s);
}
Ty_tyList tylist = makeFormalTyList(t_env,ls->tail, s);
Ty_ty t = S_look(t_env, ls->head->typ );
if(!t){
EM_error(ls->head->pos, "Type %s undefined.",S_name(ls->head->typ));
t = Ty_Int();
}
tylist = Ty_TyList(t, tylist);
return tylist;
}
else return NULL;
}
void transFunDecList(S_table v_env, S_table t_env, A_