输入:
int gtkings(int a,int a2){}
int main() {
gtkings(gtkings(1,2),gtkings(1)) + 1;
int a = 0x;
int aa
}
说明:该代码中有一个词法错误,一个语法错误,跟一个语义错误。编译器输出结果如下图。
"0x” 十六进制数写法错误(词法错误)。
"int aa” 变量定义缺少分号(语法错误)。
"gtkings(1)" 函数调用缺少一个参数(语义错误)。
输入:
int main() {
if(1)
int a;
a;
}
说明:变量 a 的越界访问是一个很常见的语义级错误,这种错误的判定如果在语法分析阶段处理是很容易的,因为当语法分析器遍历到分析树某个节点时,与该节点相关的语义规则是可以确定的。但在司马中并没有这样去实现,让语法分析器去关心那些语义方面的问题会增加它的复杂度,维护起来很费劲,虽然就时间性能来说会好一些。不依赖分析树完成语义分析需要下点功夫设计算法,该算法能模拟语法分析器遍历分析树时产生的语义信息,比如作用域,作用域在语义分析阶段非常重要,如下图中变量a的作用域是"1111"。编译器输出如下图。
输入:
void gtkings(){}
int main() {
gtkings() + 1;
}
说明:把一个没有返回值的函数当做操作数是一个语义错误。编译器输出如下图。
输入:
void gtkings(){}
int main() {
int a;
int b;
int c;
a + 1 + 22 * b;
}
说明:这是一个建立表达式树的例子,该表达式树在司马中的实现是一颗二叉树,编译器后端中使用。
司马编译器:
开发:
资源地址:
http://gforge.osdn.net.cn/projects/unixtok/
源代码以及完整设计文档我们会在近期上传到开源大本营,多谢你的关注。