lcc 源码读书笔记之c语言的语义检测
来源:互联网 发布:java音乐网站源码 编辑:程序博客网 时间:2024/06/04 08:14
LCC在语法分析过程中进行了不少的语义检测,基本集中在一元及二元操作符这里.C语言的语义检查主要包括隐式转换,类型检测和计算顺序。那就让我们从LCC编译器的角度研究C语言的语义规则
转换:
c语言在进行二元计算的时候常常包括返回类型及操作数的类型转换,下面贴出常规算术转换的代码
Type binary(Type ty1,Type ty2)
{
if(isdouble(ty1)||isdouble(ty2))
return doubletype;
if(ty1==floattype||ty2==floattype)
return floattype;
if(isunsigned(ty1)||isunsinged(ty2))
return unsignedtype;
return inttype;
}
根据上述代码可以看出来字符类型的算术操作都是返回INT类型
在处理例如char* p for(p)这种语句时。LCC要将这种不是布尔表达式的式子转换为布尔表达式,代码如下
Tree cond(Tree p)
{
int op=gernic(rightkid(p)->op);
if(op==AND||op==布尔操作符..)
return p;
p=pointer(p);
p=cast(p,promote(p->type)); //这个是将P转换为具有目标类型的树,用CV操作符
return (*optree[NEQ])(NE,p,constree(0,inttype));
}
运算符&处理类型为T的操作数,并返回他的地址(类型为(POINTER T))。
if(isarray(p->type)||isfunc(p->type))
return retype(p,ptr(p->type)); //数组或者函数,返回指向数组元素或者函数的指针
else
p=lvalue(p); //返回指向本类型的指针,既左值
if(isaddrop(p->op)&&p->u.sym->sclass==REGISTER)
error();
else if(isaddrop(p->op))
p->u.sym->addressed=1; //取址运算的操作数不能只保留在寄存器中
运算符*的语义检测如下
p=pointer(p);
if (isptr(p->type)&&isfunc(p->type->type))
return retype(p,p->type->type); //函数的取值类型就是函数原来的类型
else{
p=rvalue(p); } //一般指针的取值操作符是INDIR,类型为所指类型
为了方便大家更好的理解LCC各个模块的协作,从软件工程的角度看这个系统,我贴出一张UML顺序图
从软件工程的角度上看,LCC有高内聚,低耦合的特点。各个模块比较易于理解,可重用性也强,而且创建类的职责分配的也不错,有点疑问的是VISITOR直接由解析器创建好了,还是引入一个抽象类。从这图上看C跟C++的差役也没那么大,重构成C++的看起来还是很容易的
扯远了,呵呵。下面看看c语言的[ ]操作。标准C规定e[i]等价于*(e+i);语义函数如下:
Tree q;
t=gettok();
q=expr(]);
p=(*optree['+'])(ADD,pointer(p),pointer(q));
if(isptr(p->type)&&isarray(p->type->type)
p=retype(p,p->type->type)
else
return p=rvalue(p); //取右操作数
其中执行加法操作的关键处为:
if(isptr(r->type)&&isint(l->type)
&&!isfunc(r->type->type)
{
int n;
ty=unqual(r->type);
n=type->size; //取出指针所指类型的大小
if(n==0)
error();
l=cast(l,promote(l->type)); //短整数类型要提升
if(n>1)
l=multree(MUL,consttree(n,inttype),1); //要加的数位指针所指类型的大小×n
return simplify(ADD+P,ty,l,r); //返回的类型仍是指针
}
下面再看看->操作符的语义检测,相关的语义检测动作主要包含在field(Tree p,char* name)函数中,放在设计模式中,相当于是一个语义检测Visitor
Tree field(Tree p,char *name)
{
Field q;
Type ty1,ty=p->type;
ty1=ty;
ty=unqual(ty);
if((q=fieldref(name,ty)))!=Null){ //保证是结构的域,否则出错
if(!isarray(q->type)){
ty=q->type;
ty=ptr(ty);
}
p=simply(ADD+P,ty,p,consttree(q->offset,inttype)); //加上偏移量
if (q->lsb) {
p = tree(FIELD, ty->type, rvalue(p), NULL);
p->u.field = q;
} else if (!isarray(q->type))
p = rvalue(p);} //返回右值
else
error("unknow field");
}
c语言的语义检测暂时介绍到这儿,关于函数调用,常量折叠等比较复杂,下一次继续,呵呵
- lcc 源码读书笔记之c语言的语义检测
- lcc读书笔记之C语言语义检测2
- lcc 源码读书笔记1之操作符的宏定义
- lcc 源码读书笔记1之表达式解析
- lcc 源码读书笔记2之类型系统
- c语言中static的语义
- 六. C语言预处理器LCC-CPP之include.c代码分析
- C源码:可以检测10 种C语言编译环境的程序
- lcc源代码解析之sym.c
- lcc源代码解析之string.c
- lcc源代码解析之types.c
- lcc源代码解析之alloc.c
- lcc源代码解析之input.c
- lcc源代码解析之lex.c
- lcc源代码解析之expr.c
- lcc源代码解析之stat.c
- lcc源代码解析之tree.c
- lcc源代码解析之dag.c
- strlen函数与多字节编码的字符串字节长度
- fjnu 1827 Palindrom Numbers
- fjnu 1900 DNA Sorting
- fjnu 1189 Recurrence Relations
- 关于默认构造函数的几个错误认识
- lcc 源码读书笔记之c语言的语义检测
- Visual Basic 基础要点
- fjnu 1655 Crazy tea party
- fjnu 1604 The Hardest Problem Ever
- Microsoft Visual Studio Team System 2008 初步印象
- fjnu 1269 Fuzzy Time
- fjnu 1235 Palindromes
- 中文自动分词学习小结
- 常用的数论算法(C++描述)