目录
任务要求
开发环境
实验原理
词法分析
语法分析
语义分析+生成中间代码
生成目标代码
测试用例:
词法分析
语法分析
语义分析+四元式
生成目标代码
测试结果说明分析
词法分析
语法分析
语义分析
目标代码
总结及心得体会
参考文献
任务要求
- 整合、完善已完成的编译程序各阶段相关功能,并能可视化演示。
- 完成编译后端,生成汇编代码。
开发环境
操作系统:Windows10
开发工具::DEV-C++、VISUAL C++ 6.0
实验原理
编译过程分为词法分析、语法分析、语义分析、生成中间代码、代码优化、生成目标代码(这里没有涉及到代码优化功能的内容,只有五个功能版块)。
词法分析
词法分析中,实现的功能是分割每个单词,同时判断每个单词的类型,并二元组的形式将其输出。
【程序框架】:
【输入】:以txt格式保存的源码文本。
【输出】:存储在结构体中的单词信息。
【函数】:
char hexdigit(char buffer);//十六进制数 int digit3(char num[]);//八进制数 char Digit(char buffer);//其他数字常量 char cut1(char buffer);//注释处理 char charprocess(char buffer);//其他字符 char Alpha(char buffer);//字母 char stringprocess(char buffer);//字符串常量 int search(char searchchar[ ]);//关键字
【其他定义+数据结构】:
char key[35][20]= {"main","void","char","short","int","string","bool","long","float","double",
"sizeof","signed","unsigner","strcut","union","enum","typedef","auto","static",
"extern","register","const","volatile","if","else","for","while","do","break",
"goto","continue","return","switch","case","default"};
typedef struct
{
int typenum;//种别码
char type[10];//单词类型
char word[20];//单词
int wline;//单词在代码中的位置
}WordChart;
WordChart w[MAXSIZE];
char tree[MAXSIZE][MAXSIZE];//存储语法分析过程
int tlen=-1;
char E[MAXSIZE][MAXSIZE];//存储错误信息
int Elen=-1;
【程序关键处理部分】:
①注释处理:灵活运用文件指针,当识别到单行注释的标志‘//’,文件指针直接跳到当前位置的下一行开始的字符;若识别到多行注释标识‘';若‘/’只是一个运算符,则文件指针回退。
//处理代码注释
char cut1(char buffer)
{
buffer=fgetc(fp);//多行注释
if(buffer=='*')
{
buffer=fgetc(fp);
while(buffer!=EOF)
{
while(buffer!='*')
{
if(buffer=='n')line++;
buffer=fgetc(fp);
}
buffer=fgetc(fp);
if(buffer=='/')
{
buffer=fgetc(fp);
break;
}
else continue;
}
}
else if(buffer=='/')//单行注释
{
fgets(buf,sizeof buf,fp);//跳到下一行
}
else
{
fseek(fp,-2L,1);//若‘/’是运算符,则回退到‘/’的前一个字符
buffer=fgetc(fp);
return(Other(buffer));
}
return(buffer);
}
②数字处理:包括科学记数法、八进制、十六进制、小数、负数正数。根据状态转换图来编写程序。
char Digit(char buffer)//小数、整数、科学记数法
{
char ch[20];
int i;
int tag;
int flag=0;
int count1=0;
ch[0]=buffer;
ch[1]=' ';
if(buffer=='0')
{
buffer=fgetc(fp);
if(buffer=='X'||buffer=='x') return(hexdigit(buffer));
else if(isalpha(buffer)||buffer=='_')
{
ch[1]=buffer;
buffer=fgetc(fp);
i=2;
while(isalpha(buffer)||isdigit(buffer)||buffer=='_')
{
ch[i]=buffer;
i++;
buffer=fgetc(fp);
}
ch[i]=' ';
strncpy(str,ch+1,i);
fprintf(fp0,"%d:%s:[Error]invalid suffix '%s' on integer constantn",line,ch,str);
error++;
return(fgetc(fp));
}
else if((buffer>=32&&buffer<=34)||(buffer>=37&&buffer<=45)||(buffer==47)||(buffer>=58&&buffer<=63)||(buffer==93)||(buffer>=124&&buffer<=125)||buffer=='n')
{ if(buffer=='n')line++;
w[++len].typenum=34;
strcpy(w[len].word,ch);
strcpy(w[len].type,"常量");
fprintf(fp1,"(%s,34)n",ch);
return(buffer);
}
else if(buffer=='.')
{
ch[1]=buffer;
buffer=fgetc(fp);
i=2;
while(isdigit(buffer))
{
ch[i]=buffer;
i++;
buffer=fgetc(fp);
}
ch[i]=' ';
w[++len].typenum=35;
strcpy(w[len].word,ch);
strcpy(w[len].type,"常量");
fprintf(fp1,"(%s,35)n",ch);
return(buffer);
}
else
{
ch[1]=buffer;i=2;buffer=fgetc(fp);
}
}
else
{
buffer=fgetc(fp);
i=1;
}
while(isdigit(buffer)||buffer=='.')
{
if(buffer=='.')count1++;
ch[i]=buffer;
i++;
buffer=fgetc(fp);
}
ch[i]=' ';
if(count1>1)
{
fprintf(fp0,"%d:%s:[Error] too many decimal points in numbern",line,ch);
error++;return(buffer);
}
if(buffer=='e')
{
ch[i]=buffer;
i++;
ch[i]=' ';
buffer=fgetc(fp);
if(buffer=='+'||buffer=='-')
{
ch[i]=buffer;
i++;
ch[i]=' ';
buffer=fgetc(fp);
if(isdigit(buffer))
{
while(isdigit(buffer))
{
ch[i]=buffer;i++;
buffer=fgetc(fp);
}
ch[i]=' ';
w[++len].typenum=67;
strcpy(w[len].word,ch);
strcpy(w[len].type,"常量");
fprintf(fp1,"(%s,67)n",ch);
id=3;
}
else
{
fprintf(fp0,"%d:%s%c:[Error]n",line,ch,buffer);
error++;
}
}
else if(isdigit(buffer))
{
while(isdigit(buffer))
{
ch[i]=buffer;i++;
ch[i]=' ';
buffer=fgetc(fp);
}
id=3;
w[++len].typenum=67;
strcpy(w[len].word,ch);
strcpy(w[len].type,"常量");
fprintf(fp1,"(%s,67)n",ch);
}
else
{
fprintf(fp0,"%d:%s:[Error] invalid suffix '%c' on integer constantn",line,ch,ch[i-1]);
error++;
buffer=fgetc(fp);
}
}
else if(isalpha(buffer)||buffer=='_')
{
ch[i]=buffer;
buffer=fgetc(fp);
i++;
while(isalpha(buffer)||isdigit(buffer)||buffer=='_')
{
ch[i]=buffer;
i++;
buffer=fgetc(fp);
}
ch[i]=' ';
strncpy(str,ch+1,i);
error++;
fprintf(fp0,"%d:%s:[Error]invalid suffix '%s' on integer constantn",line,ch,str);
return(fgetc(fp));
}
else if(ch[0]!='0'&&((buffer>=32&&buffer<=34)||(buffer>=37&&buffer<=45)||(buffer==47)||(buffer>=58&&buffer<=63)||(buffer==93)||(buffer>=124&&buffer<=125)||buffer=='n'))
{ if(buffer=='n')line++;
id=3;
if(count1==1)
{
w[++len].typenum=35;
strcpy(w[len].word,ch);
strcpy(w[len].type,"常量");
fprintf(fp1,"(%s,35)n",ch);
}
else
{
w[++len].typenum=34;
strcpy(w[len].word,ch);
strcpy(w[len].type,"常量");
fprintf(fp1,"(%s,34)n",ch);
}
}
else if((buffer>='a'&&buffer<='z')||(buffer>='A'&&buffer<='Z')||buffer=='_')
{
fprintf(fp0,"%d:%s%c:[Error] invalid suffix '%c' on integer constantn",line,ch,buffer,buffer);
error++;
buffer=fgetc(fp);
}
else if(ch[0]=='0'||count1==0)
{
tag=digit3(ch);
if(tag==1)
{
w[++len].typenum=69;
strcpy(w[len].word,ch);
strcpy(w[len].type,"常量");
fprintf(fp1,"(%s,69)n",ch);
}
else
{error++;fprintf(fp0,"%d:%s:[Error]八进制格式错误n",line,ch);}
}
else
{
fprintf(fp0,"%d:%s%c:[Error] invalid suffix '%c' on integer constantn",line,ch,buffer,buffer);
error++;
}
return buffer;
}
语法分析
对给定的一个上下无关文法,分析任意一个源码的语法结构。采用的是递归下降语法分析。
【递归下降分析思想】:自顶向下分析就是从文法的开始符触发并寻找出这样一个推导序列:推导出的句子恰好为输入符号串;或者说,能否从根节点出发向下生长出一颗语法树,其叶节点组成的句子恰好为输入符号串。显然,语法树的每一步生长(每一步推导)都以能否与输入符号串匹配为准,如果最终句子得到识别,则证明输入符号串为该文发的一个句子;否则,输入符号串不是该文法的句子。
递归下降分析法是一种自顶向下的分析方法,文法的每个非终结符对应一个递归过程(函数)。分析过程就是从文法开始符触发执行一组递归过程(函数),这样向下推到直到推出句子;或者说从根节点出发,自顶向下为输入串寻找一个最左匹配序列,建立一颗语法树。
【程序框架】:
【输入】:存储在结构体WordChart中的词法分析结果。
【输出】:整个源码的语法分析过程。
【自定义文法】:
可分析的执行语句为主函数、定义变量、if-else、while循环、for循环、return、赋值语句、算式表达式、关系表达式、布尔表达式。
→ → main ( ) → { } → ; | empty → → , | empty → int |void → int |char|float|string|double|bool → 标识符 → | empty → = ; → if ( ) → else | empty → while ( ) → → return 数字;|return ; →for ( ) → ; ; → = |empty → |empty → |empty → ++ | - - → → → |empty → < | <= | > | >= | == | != → || | && → → | empty → → | empty → id | number | ( ) → + | - → * | / | %
【函数】:
表1 为所有非终结符函数:
| 函数定义、执行语句框架(‘{}’) | 变量定义 | 操作语句 | 比尔表达式、关系表达式 | 算式表达式 |
| Int Prog(); | Int Decls(); | Int STMTS(); | Int BOOL(); | Int Expr(); |
| Int Main(); | Int NameList(); | Int STMT(); | Int BOOL1(); | Int Expr1(); |
| Int Block(); | Int NameList1(); | Int STMT1(); | Int BOOL2() | Int Term(); |
| bool Type1(); | bool Type(); | Int Rep(); | bool RelOp(); | bool AddOp(); |
| bool Name(); | Int Rep2(); | bool RelOp1(); | int Num(); | |
| Int ForRep(); | bool MulOp(); | |||
| Int Rep1(); | Int Factor() | |||
| Int RelOp2() |
表1
语义分析+生成中间代码
在语法分析的基础上改写代码,使得程序对于输入的一个完整的源程序,在对其做递归下降分析的同时,生成等价的四元式序列,一遍完成。
【程序框架】:
(蓝色填充的部分流程是在语法分析上修改增加进去的语法分析和四元式生成)
【输入】:存储在结构体WordChart中的词法分析结果。
【输出】:符号表、四元式序列。
【自定义文法】:同语法分析。
【其他定义+数据结构】:
语义分析究竟在语法分析的基础上增加了哪些内容呢?语法分析只是单纯分析输入的源码是否符合文法规则,即整体源码的框架是否合法。语义分析要在判断源码框架合法的基础上对源码中的细节进行判断,例如生成符号表,判断使用的变量是否定义、变量是否重复定义等等;
typedef struct//符号表
{
char word[20];
char type[10];
int numValue;
char rel[20];
}ID;
int nlen=-1;//记录定义的变量个数(位置)
ID IDs[MAXSIZE];
除了这些功能,还需要能正确返回算式表达式、关系表达式、布尔表达式的值。将语法分析中所有非终结符函数的返回值都改写成LInfo,这样就可以再各个语法分析阶段中传递所需要的继承文法。
struct LInfo//用来存储L属性文法需要传递的信息
{
int addr;//条件跳转
ID Id;
};
LInfo info;
中间代码(四元式)也是伴随语义分析而生成的,主要是就算式表达式、关系表达式、布尔表达式、条件跳转等。
四元式格式如下:
1.声明语句,不需要四元式
2.赋值语句:
(=, value, _, id)
3.条件语句:
(jnz, BOOL, _, E.false) E.true: ... (jmp, _, _, S.next) E.false: ... S.next: ...
其中布尔表达式BOOL的四元式:
(op, arg1, arg2, result) result=1表示true,result=0表示false
4.循环语句:
s: (jnz, BOOL, _, E.false) ... (jmp, _, _, s) E.false: ...
存储四元式结构体:
typedef struct//四元式
{
char op[10];
char arg1[20];
char arg2[20];
char result[20];
}Quaternion;
Quaternion Q[MAXSIZE];
int qlen=-1;
【函数】:
表2为所有非终结符函数:
| 函数定义、执行语句框架(‘{}’) | 变量定义 | 操作语句 | 比尔表达式、关系表达式 | 算式表达式 |
| LInfo Prog (LInfo info) | LInfo Decls (LInfo info) | LInfo STMTS (LInfo info) | LInfo BOOL (LInfo info) | LInfo Expr (LInfo info) |
| LInfo Main (LInfo info) | LInfo NameList(LInfo info) | LInfo STMT (LInfo info) | LInfo BOOL1(LInfo info) | LInfo Expr1(LInfo info) |
| LInfo Block (LInfo info) | LInfo NameList1 (LInfo info) | LInfo STMT1 (LInfo info) | LInfo BOOL2 (LInfo info) | LInfo Term(LInfo info) |
| bool Type1() | bool Type() | LInfo Rep (LInfo info) | bool RelOp(LInfo info) | bool AddOp() |
| bool Name() | LInfo Rep2 (LInfo info) | bool RelOp1() | Int Num() | |
| LInfo ForRep(LInfo info) | bool MulOp() | |||
| LInfo Rep1 (LInfo info) | LInfo Factor (LInfo info) | |||
| bool RelOp2() |
表2
【程序关键部分】:
LInfo Prog(LInfo info) {
if (flag)
{
strcpy(tree[++tlen],"→");
LInfo info1;
info1=Main(info);
if (!flag) return info;
return info;
}
return info;
}
LInfo Main(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→main()");
if (Type1()) {
index++;
if (strcmp(w[index].word, "main") == 0) {
index++;
if (strcmp(w[index].word, "(") == 0) {
index++;
if (strcmp(w[index].word, ")") == 0) {
index++;
LInfo info1;
info1=Block(info);
if (!flag) return info;
return info;
}
else{
fprintf(fp2,"%s之前缺少 )rn",w[index].word);
error++;
flag = false;
return info;
}
}
else{
fprintf(fp2,"%s之前缺少 (n",w[index].word);
error++;
flag = false;
return info;
}
}
else{
fprintf(fp2,"没有主函数rn");error++;
flag = false;
return info;
}
}
else {
fprintf(fp2,"没有函数类型rn");error++;
flag = false;
return info;
}
}
return info;
}
LInfo Block(LInfo info) {
if (flag){
strcpy(tree[++tlen],"→{}");
if (strcmp(w[index].word, "{") == 0) {
index++;
LInfo info1;
info1=Decls(info);
if (!flag) return info;
LInfo info2;
info2=STMTS(info);
if (!flag) return info;
if (strcmp(w[index].word, "}") == 0) {
index++;
return info;
}
else{
fprintf(fp2,"%s之前缺少 }rn",w[index].word);error++;
flag = false;
return info;
}
}
else{
fprintf(fp2,"%s之前缺少 {rn",w[index].word);error++;
flag = false;
return info;
}
}
return info;
}
LInfo Decls(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (Type()) {
strcat(tree[tlen],"");
strcat(tree[tlen],";");
strcpy(tree[++tlen],"→");strcat(tree[tlen],w[index].word);
strcpy(info.Id.type,w[index].word);
index++;
LInfo info1;
info1=NameList(info);
if (!flag) return info;
if (strcmp(w[index].word, ";") == 0) {
index++;
LInfo info2;
info2=Decls(info);
if (!flag) return info;
return info;
}
else{
fprintf(fp2,"%s之前缺少 ;rn",w[index].word);error++;
flag = false;
return info;
}
}
else{
strcat(tree[tlen],"empty");
return info;
}
}
return info;
}
LInfo NameList(LInfo info)
{
if(flag) {
strcpy(tree[++tlen],"→");
if (Name()) {
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
if(findId(w[index].word)!=-1){
fprintf(fp2,"%s标识符重复!rn",w[index].word);error++;
flag=false;return info;
}
else
{
strcpy(IDs[++nlen].word,w[index].word);
strcpy(IDs[nlen].type,info.Id.type);
index++;
}
info.Id=IDs[nlen];
LInfo info1;
info1=NameList1(info);
if (!flag) return info;
return info;
}
else{
fprintf(fp2,"%s后缺少变量rn",w[index].word);error++;
flag = false;
return info;
}
}
return info;
}
LInfo NameList1(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (strcmp(w[index].word, ",") == 0) {
strcat(tree[tlen],",");
index++;
if (Name()) {
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
if(findId(w[index].word)!=-1){
fprintf(fp2,"%s标识符重复!rn",w[index].word);error++;
flag=false;
return info;
}
else{
strcpy(IDs[++nlen].word,w[index].word);
strcpy(IDs[nlen].type,info.Id.type);
index++;
}
LInfo info1;
info1=NameList1(info);
if (!flag) return info;
return info;
}
else{
fprintf(fp2,"%s后缺少变量rn",w[index].word);error++;
flag = false;
return info;
}
}
if(strcmp(w[index].word,"=")==0)
{
strcat(tree[tlen],"=");
index++;
if (Name()||w[index].typenum==34) {
if(w[index].typenum==33){
if(findId(w[index].word)!=-1){
fprintf(fp2,"%s标识符重复!rn",w[index].word);error++;
flag=false;
return info;
}
else{
strcpy(IDs[++nlen].word,w[index].word);
strcpy(IDs[nlen].type,info.Id.type);
index++;
}
}
LInfo info1=Expr(info);
info.Id.numValue=info1.Id.numValue;
//printf("(=,%d,_,%s)",info.Id.numValue,info.Id.word);
LInfo info2;
info2=NameList1(info);
if (!flag) return info;
return info;
}
else{
fprintf(fp2,"%s前缺少变量rn",w[index].word);error++;
flag = false;
return info;
}
}
else{
strcat(tree[tlen],"empty");
return info;
}
}
return info;
}
bool Type1() {
if (strcmp(w[index].word, "int") == 0||strcmp(w[index].word, "void") == 0)
{strcpy(tree[++tlen],"→");strcat(tree[tlen],w[index].word);return true;}
else return false;
}
bool Type() {
if (strcmp(w[index].word, "int") == 0||strcmp(w[index].word, "char") == 0||strcmp(w[index].word, "float") == 0||strcmp(w[index].word, "string") == 0||strcmp(w[index].word, "double") == 0||strcmp(w[index].word, "bool") == 0)
{
return true;}
else return false;
}
bool Name() {
if (w[index].typenum==33) {
return true;
}
else return false;
}
LInfo STMTS(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (w[index].typenum==33||strcmp(w[index].word,"for")==0||strcmp(w[index].word, "if") == 0 || strcmp(w[index].word, "while") == 0 ||strcmp(w[index].word, "return") == 0 || strcmp(w[index].word, "{") == 0) {
strcat(tree[tlen],"");
LInfo info1;info1=STMT(info);
if (!flag) return info;
LInfo info2;info2=STMTS(info);
if (!flag) return info;
return info;
}
else{
strcat(tree[tlen],"empty");return info;
}
}
return info;
}
LInfo STMT(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (Name()) {//赋值语句
strcat(tree[tlen],"=;");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
int nowIdAddr=findId(w[index].word);
if(nowIdAddr==-1){
flag=false;
fprintf(fp2,"%s该标识符未定义rn",w[index].word);error++;
return info;
}
//info.Id=IDs[nowIdAddr];
index++;
if (strcmp(w[index].word, "=") == 0) {
index++;
LInfo info1=Expr(info);
if (!flag) return info;
IDs[nowIdAddr].numValue=info1.Id.numValue;
strcpy(Q[++qlen].op,"=");
strcpy(Q[qlen].arg1,itoa(IDs[nowIdAddr].numValue,str,10));
strcpy(Q[qlen].arg2,"_");
strcpy(Q[qlen].result,IDs[nowIdAddr].word);
info.addr=qlen;
if (strcmp(w[index].word, ";") == 0) {
index++;return info;
}
else{
fprintf(fp2,"%s前缺少 ;n",w[index].word);error++;
flag = false;
return info;
}
}
else {
fprintf(fp2,"%s前缺少 =n",w[index].word);error++;
flag = false;
return info;
}
}
else if (strcmp(w[index].word, "if") == 0){//if-else语句
strcat(tree[tlen],"if()");
index++;
if (strcmp(w[index].word, "(") == 0) {
//printf("( ");
index++;
LInfo info1;
info1=BOOLL(info);
if (!flag) return info;
if(strcmp(info1.Id.rel,"0")==0)
{
strcpy(Q[++qlen].op,"jz");
strcpy(Q[qlen].arg1,info1.Id.rel);
strcpy(Q[qlen].arg2,"_");
}
else if(strcmp(info1.Id.rel,"1")==0)
{
strcpy(Q[++qlen].op,"jnz");
strcpy(Q[qlen].arg1,info1.Id.rel);
strcpy(Q[qlen].arg2,"_");
}
info.addr=qlen;
if (strcmp(w[index].word, ")") == 0){
index++;
LInfo info2;
info2=STMT(info);
if (!flag) return info;
int q=info2.addr;
LInfo info3;
info3=STMT1(info);
if (!flag) return info;
int q1=info3.addr;
char result[10];
if(strcmp(info1.Id.rel,"0")==0)
{strcpy(result,itoa(q1,str,10));}
else if(strcmp(info1.Id.rel,"1")==0)
{strcpy(result,itoa(q,str,10));}
strcpy(Q[info.addr].result,result);
return info;
}
else{
fprintf(fp2,"%s前缺少 )n",w[index].word);error++;
flag = false;
return info;
}
}
else{
fprintf(fp2,"10:%s前缺少 (n",w[index].word);error++;
flag = false;
return info;
}
}
else if (strcmp(w[index].word, "while") == 0) {//while循环
strcat(tree[tlen],"while()");
index++;
if (strcmp(w[index].word, "(") == 0) {
index++;
LInfo info1;
info1=BOOLL(info);
if (!flag) return info;
if(strcmp(info1.Id.rel,"0")==0)
{
strcpy(Q[++qlen].op,"jz");
strcpy(Q[qlen].arg1,info1.Id.rel);
strcpy(Q[qlen].arg2,"_");
}
else if(strcmp(info1.Id.rel,"1")==0)
{
strcpy(Q[++qlen].op,"jnz");
strcpy(Q[qlen].arg1,info1.Id.rel);
strcpy(Q[qlen].arg2,"_");
}
info.addr=qlen;
if (strcmp(w[index].word, ")") == 0) {
index++;
LInfo info2;
info2=STMT(info);
if (!flag) return info;
if(strcmp(info1.Id.rel,"1")==0)
{strcpy(Q[info.addr].result,itoa(info2.addr,str,10));}
else
{strcpy(Q[info.addr].result,itoa(info.addr,str,10));}
return info;
}
else{
fprintf(fp2,"%s前缺少 )n",w[index].word);error++;
flag = false;
return info;
}
}
else {
fprintf(fp2,"%s前缺少 (n",w[index].word);error++;
flag = false;
return info;
}
}
else if(strcmp(w[index].word,"for")==0){ //for循环
strcat(tree[tlen],"for()");
index++;
if(strcmp(w[index].word,"(")==0){
//printf("( ");
index++;
LInfo info1;
info1=ForRep(info);
if(!flag) return info;
if(strcmp(w[index].word,")")==0){
//printf(") ");
index++;
LInfo info2;
info2=STMT(info);
if(!flag) return info;
return info;
}
else{
fprintf(fp2,"%s前缺少 )n",w[index].word);error++;
flag = false;
return info;
}
}
else {
fprintf(fp2,"%s前缺少 (n",w[index].word);error++;
flag = false;
return info;
}
}
else if (strcmp(w[index].word, "{") == 0){
//printf("{ ");
strcat(tree[tlen],"");
//index++;
LInfo info1;
info1=Block(info);
if (!flag) return info;
return info;
}
else if (strcmp(w[index].word, "return") == 0){//return语句
strcat(tree[tlen],"return");
index++;
int tag;
tag=Num();
if (tag!=-1)
{
strcat(tree[tlen],";");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
index++;
if (strcmp(w[index].word, ";") == 0) {
//printf("; ");
index++;
return info;
}
else {
fprintf(fp2,"%s前缺少 ;n",w[index].word);error++;
flag = false;
return info;
}
}
else if(Name())
{ strcat(tree[tlen],";");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
int nowIdAddr=findId(w[index].word);
if(nowIdAddr==-1)
{
fprintf(fp2,"%s该标识符未定义",w[index].word);error++;
flag=false;return info;
}
else
{
index++;
if (strcmp(w[index].word, ";") == 0) {
printf("; ");
index++;
return info;
}
else {
fprintf(fp2,"%s前缺少 ;n",w[index].word);error++;
flag = false;
return info;
}
}
}
else {
fprintf(fp2,"%s后缺少返回值n",w[index].word);error++;
flag = false;
return info;
}
}
else {
fprintf(fp2,"%s后缺少变量n",w[index].word);error++;
flag = false;
return info;
}
}
return info;
}
LInfo STMT1(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (strcmp(w[index].word, "else") == 0) {
strcat(tree[tlen],"else");
index++;
LInfo info1;
info1=STMT(info);
if (!flag) return info;
return info;
}
else{
strcat(tree[tlen],"empty");return info;
}
}
return info;
}
LInfo ForRep(LInfo info)
{
if(flag){
strcpy(tree[++tlen],"→;;");
LInfo info3;
info3=Rep(info);
if(!flag) return info;
if(strcmp(w[index].word,";")==0){
index++;
LInfo info1;
info1=Rep2(info);
if(!flag) return info;
if(strcmp(w[index].word,";")==0){
index++;
LInfo info2;
info2=Rep1(info);
if(!flag) return info;
}
else{
fprintf(fp2,"%s后缺少 ;",w[index].word);error++;flag=false;return info;
}
}
else{
fprintf(fp2,"%s后缺少 ;",w[index].word);error++;flag=false;return info;
}
}
return info;
}
LInfo Rep(LInfo info)
{
if(flag)
{
strcpy(tree[++tlen],"→");
if(Name())
{
strcat(tree[tlen],"=");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
if(findId(w[index].word)==-1){
flag=false;
fprintf(fp2,"%s该标识符未定义rn",w[index].word);error++;
return info;
}
else
index++;
if(strcmp(w[index].word,"=")==0){
//printf("= ");
index++;
LInfo info1;
info1=Expr(info);
if(!flag) return info;
}
}
else{
strcat(tree[tlen],"empty");return info;
}
}
return info;
}
LInfo Rep1(LInfo info)
{
if(flag)
{
strcpy(tree[++tlen],"→");
if(Name())
{
strcat(tree[tlen],"");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
if(findId(w[index].word)==-1){
flag=false;
fprintf(fp2,"%s该标识符未定义rn",w[index].word);error++;
return info;
}
else
index++;
if(RelOp2()){
char nowOp[20];
strcpy(nowOp,w[index].word);
index++;
return info;
}
else{
fprintf(fp2,"%s后缺少运算符rn",w[index].word);error++;
}
}
else{
strcat(tree[tlen],"empty");return info;
}
return info;
}
return info;
}
LInfo Rep2(LInfo info)
{
if(flag)
{
strcpy(tree[++tlen],"→");
if(w[index].typenum==33||w[index].typenum==39||w[index].typenum==34||w[index].typenum==35)
{
strcat(tree[tlen],"");
LInfo info1;
info1=BOOLL(info);
if(!flag) return info;
return info;
}
else
{
strcat(tree[tlen],"empty");return info;
}
}
return info;
}
bool RelOp2()
{
if(strcmp(w[index].word,"++")==0||strcmp(w[index].word,"--")==0)
{strcpy(tree[++tlen],"→");strcat(tree[tlen],w[index].word);
return true;}
return false;
}
LInfo BOOL1(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
LInfo info1;
info1=Expr(info);
if (!flag) return info;
if (RelOp()) { //若是关系运算符
char nowOp[20];
strcpy(nowOp,w[index].word);
index++;
LInfo info2;
info2=Expr(info);
if (!flag) return info;
bool result;
strcpy(Q[++qlen].op,nowOp);
strcpy(Q[qlen].arg1,itoa(info1.Id.numValue,str,10));
strcpy(Q[qlen].arg2,itoa(info2.Id.numValue,str,10));
if(strcmp(nowOp,"<")==0){
result=info1.Id.numValue")==0){
result=info1.Id.numValue>info2.Id.numValue;
if(result==false)
{
strcpy(Q[qlen].result,"0");
strcpy(info.Id.rel,"0");
}
else
{
strcpy(Q[qlen].result,"1");
strcpy(info.Id.rel,"1");
}
}
else if(strcmp(nowOp,">=")==0){
result=info1.Id.numValue>=info2.Id.numValue;
if(result==false)
{
strcpy(Q[qlen].result,"0");
strcpy(info.Id.rel,"0");
}
else
{
strcpy(Q[qlen].result,"1");
strcpy(info.Id.rel,"1");
}
}
else if(strcmp(nowOp,"==")==0){
result=info1.Id.numValue==info2.Id.numValue;
if(result==false)
{
strcpy(Q[qlen].result,"0");
strcpy(info.Id.rel,"0");
}
else
{
strcpy(Q[qlen].result,"1");
strcpy(info.Id.rel,"1");
}
}
else if(strcmp(nowOp,"!=")==0){
result=info1.Id.numValue!=info2.Id.numValue;
if(result==false)
{
strcpy(Q[qlen].result,"0");
strcpy(info.Id.rel,"0");
}
else
{
strcpy(Q[qlen].result,"1");
strcpy(info.Id.rel,"1");
}
}
return info;
}
else {
fprintf(fp2,"%s后缺少运算符rn",w[index].word);error++;
flag = false;
return info;
}
return info;
}
return info;
}
LInfo BOOL2(LInfo info)
{
if(flag){
strcpy(tree[++tlen],"→");
if(RelOp1()){
char nowOp[20];
strcpy(nowOp,w[index].word);
strcat(tree[tlen],"");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
index++;
LInfo info1;
info1=BOOL1(info);
if(!flag) return info;
bool result;
strcpy(Q[++qlen].op,nowOp);
strcpy(Q[qlen].arg1,info.Id.rel);
strcpy(Q[qlen].arg2,info1.Id.rel);
if(strcmp(nowOp,"||")==0)
{
result=info.Id.rel==info1.Id.rel;
if(result==true)
{
strcpy(Q[qlen].result,info1.Id.rel);
strcpy(info.Id.rel,info1.Id.rel);
}
else
{
strcpy(Q[qlen].result,"1");
strcpy(info.Id.rel,"1");
}
}
else//&&
{
result=info.Id.rel==info1.Id.rel;
if(result==false)
{
strcpy(Q[qlen].result,info1.Id.rel);
strcpy(info.Id.rel,info1.Id.rel);
}
else
{
strcpy(Q[qlen].result,"0");
strcpy(info.Id.rel,"0");
}
}
return info;
}
else
{
strcat(tree[tlen],"empty");return info;
}
return info;
}
return info;
}
bool RelOp1()
{
if(strcmp(w[index].word,"||")==0||strcmp(w[index].word,"&&")==0)
{
return true;}
else return false;
}
LInfo BOOLL(LInfo info)
{
if(flag){
strcpy(tree[++tlen],"→");
LInfo info1;
info1=BOOL1(info);
if(!flag) return info;
info.Id=info1.Id;
LInfo info2;
info2=BOOL2(info);
if(!flag) return info;
info.Id=info2.Id;
return info;
}
return info;
}
bool RelOp() {
if (strcmp(w[index].word, "<") == 0 || strcmp(w[index].word, "<=") == 0 || strcmp(w[index].word, ">") == 0 ||strcmp(w[index].word, ">=") == 0 || strcmp(w[index].word, "==") == 0 || strcmp(w[index].word, "!=") == 0) {
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
return true;
}
return false;
}
LInfo Expr(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
LInfo info1 = Term(info);
if (!flag) return info;
info.Id = info1.Id;
LInfo info2 = Expr1(info);
if (!flag) return info;
info.Id = info2.Id;
return info;
}
return info;
}
LInfo Expr1(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (AddOp()) {
strcat(tree[tlen],"");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
char nowOp[20];
strcpy(nowOp,w[index].word); //若字符为+或-
index++;
LInfo info1=Term(info);
if (!flag) return info;
int result;
if(strcmp(nowOp,"-")==0){
result=info.Id.numValue-info1.Id.numValue;
strcpy(Q[++qlen].op,"-");
strcpy(Q[qlen].arg1,itoa(info.Id.numValue,str,10));
strcpy(Q[qlen].arg2,itoa(info1.Id.numValue,str,10));
strcpy(Q[qlen].result,itoa(result,str,10));
info.Id.numValue=result;
}
else if(strcmp(nowOp,"+")==0){
result=info.Id.numValue+info1.Id.numValue;
strcpy(Q[++qlen].op,"+");
strcpy(Q[qlen].arg1,itoa(info.Id.numValue,str,10));
strcpy(Q[qlen].arg2,itoa(info1.Id.numValue,str,10));
strcpy(Q[qlen].result,itoa(result,str,10));
info.Id.numValue=result;
}
LInfo info2=Expr1(info);
if (!flag) return info;
info.Id=info2.Id;
return info;
}
else
{
strcat(tree[tlen],"empty");return info;
}
return info;
}
return info;
}
LInfo Term(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
LInfo info1=Factor(info);
if (!flag) return info;
info.Id=info1.Id;
LInfo info2=Term1(info);
if (!flag) return info;
info.Id=info2.Id;
return info;
}
return info;
}
LInfo Term1(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (MulOp()) { //若字符为*或/
strcat(tree[tlen],"");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
char nowOp[20];
strcpy(nowOp,w[index].word);
index++;
LInfo info1=Factor(info);
if(!flag) return info;
int result;
if(strcmp(nowOp,"*")==0){
result=info.Id.numValue*info1.Id.numValue;
strcpy(Q[++qlen].op,"*");
strcpy(Q[qlen].arg1,itoa(info.Id.numValue,str,10));
strcpy(Q[qlen].arg2,itoa(info1.Id.numValue,str,10));
strcpy(Q[qlen].result,itoa(result,str,10));
info.Id.numValue=result;
}
else if(strcmp(nowOp,"/")==0){
result=info.Id.numValue/info1.Id.numValue;
strcpy(Q[++qlen].op,"/");
strcpy(Q[qlen].arg1,itoa(info.Id.numValue,str,10));
strcpy(Q[qlen].arg2,itoa(info1.Id.numValue,str,10));
strcpy(Q[qlen].result,itoa(result,str,10));
info.Id.numValue=result;
}
else if(strcmp(nowOp,"%")==0){
result=info.Id.numValue%info1.Id.numValue;
strcpy(Q[++qlen].op,"%");
strcpy(Q[qlen].arg1,itoa(info.Id.numValue,str,10));
strcpy(Q[qlen].arg2,itoa(info1.Id.numValue,str,10));
strcpy(Q[qlen].result,itoa(result,str,10));
info.Id.numValue=result;
}
LInfo info2=Term1(info);
if (!flag) return info;
info.Id=info2.Id;
return info;
}
else
{
strcat(tree[tlen],"empty");return info;
}
}
return info;
}
LInfo Factor(LInfo info) {
if (flag) {
strcpy(tree[++tlen],"→");
if (Name()) {
strcat(tree[tlen],"");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
int nowIdAddr=findId(w[index].word);
if(nowIdAddr==-1){
flag=false;
fprintf(fp2,"%s该标识符未定义rn",w[index].word);error++;
return info;
}
info.Id.numValue=IDs[nowIdAddr].numValue;
strcpy(info.Id.word,IDs[nowIdAddr].word);
strcpy(info.Id.type,IDs[nowIdAddr].type);
index++;return info;
}
else if(Num()!=-1)
{ strcat(tree[tlen],"");
strcpy(tree[++tlen],"→");
strcat(tree[tlen],w[index].word);
LInfo info1;
info1.Id.numValue=atoi(w[index].word);
info.Id=info1.Id;
index++;return info;
}
else if (strcmp(w[index].word, "(") == 0) {
strcat(tree[tlen],"()");
index++;
LInfo info1=Expr(info);
if (!flag) return info;
if (strcmp(w[index].word, ")") == 0) {
info.Id=info1.Id;
index++;
return info;
}
else{ //若一直没有),则说明该算术表达式错误
fprintf(fp2,"%后缺少 )rn",w[index].word);error++;
flag = false;
return info;
}
}
else {
fprintf(fp2,"%s后缺少变量rn",w[index].word);error++;
flag = false;
return info;
}
return info;
}
return info;
}
int Num()
{
if((w[index].typenum>=34&&w[index].typenum<=36)||(w[index].typenum>=67&&w[index].typenum<=69))
{
return w[index].typenum;
}
return -1;
}
bool AddOp() {
if (strcmp(w[index].word, "+") == 0 || strcmp(w[index].word, "-") == 0)
{
return true;}
return false;
}
bool MulOp() {
if (strcmp(w[index].word, "*") == 0 || strcmp(w[index].word, "/") == 0 || strcmp(w[index].word, "%") == 0)
{
return true;}
return false;
}
生成目标代码
根据四元式,将中间代码转换成汇编语言。
【程序关键部分】:
void CMainFrame::Onhuibian()
{
// TODO: Add your command handler code here
int i;
CMainFrame *pMainFrame = (CMainFrame *)AfxGetMainWnd();
CString strout,strtmp;
for(i=0;i<=qlen;i++)
{
if(strcmp(Q[i].op,"+")==0)
{
strtmp.Format("MOV AX,%srnADD AX,%srnMOV %s,AXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"-")==0)
{
strtmp.Format("MOV AX,%srnSUB AX,%srnMOV %s,AXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"*")==0)
{
strtmp.Format("MOV AX,%srnMOV BX,%srnMUL BXrnMOV %s,AXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"/")==0)
{
strtmp.Format("MOV AX,%srnMOV DX,0rnMOV BX,%srnDIV BXrnMOV %s,AXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"%")==0)
{
strtmp.Format("MOV AX,%srnMOV DX,0rnMOV BX,%srnDIV BXrnMOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"<")==0)
{
strtmp.Format("MOV DX,1rnMOV AX,%srnCMP AX,%srnJB _LTrnMOV DX,0rn _LT:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,">=")==0)
{
strtmp.Format("MOV DX,1rnMOV AX,%srnCMP AX,%srnJNB _GErnMOV DX,0rn _GE:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,">")==0)
{
strtmp.Format("MOV DX,1rnMOV AX,%srnCMP AX,%srnJA _GTrnMOV DX,0rn _GT:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"<=")==0)
{
strtmp.Format("MOV DX,1rnMOV AX,%srnCMP AX,%srnJNA _LErnMOV DX,0rn _LE:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"==")==0)
{
strtmp.Format("MOV DX,1rnMOV AX,%srnCMP AX,%srnJE _EQrnMOV DX,0rn _EQ:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"!=")==0)
{
strtmp.Format("MOV DX,1rnMOV AX,%srnCMP AX,%srnJNE _NErnMOV DX,0rn _NE:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"&&")==0)
{
strtmp.Format("MOV DX,0rnMOV AX,%srnCMP AX,0rnJE _ANDrnMOV AX %srn CMP AX 0rnJE _ANDrnMOV DX,1rn_AND:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"||")==0)
{
strtmp.Format("MOV DX,1rnMOV AX,%srnCMP AX,0rnJNE _ORrnMOV AX %srn CMP AX 0rnJNE _ORrnMOV DX,0rn_OR:MOV %s,DXrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].arg2,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"jz")==0)
{
strtmp.Format("MOV AX,%srnCMP AX,0rnJNE _NErnJMP far ptr %srn_NE:NOPrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
else if(strcmp(Q[i].op,"jnz")==0)
{
strtmp.Format("MOV AX,%srnCMP AX,0rnJE _EZrnJMP far ptr %srn_NE:NOPrn---------------------------------------rn",(LPCTSTR)Q[i].arg1,(LPCTSTR)Q[i].result);
strout.Insert(strout.GetLength(),strtmp);
}
}
CErrorView *pErrorView = (CErrorView *)pMainFrame->m_wndSplitter2.GetPane(1,0);
pErrorView->SetWindowText(strout);
}
测试
MFC界面设计如图所示:
所有测试将在该界面运行。
词法分析菜单下按钮:词法分析器。响应函数void CMainFrame::OnLexAnalyer()
语法分析菜单下按钮:递归下降语法分析。响应函数void CMainFrame::OnGraAnalyer()
语义分析菜单下按钮:生成中间代码。响应函数void CMainFrame::OnyuyiAnalyer()
生成汇编语言。响应函数void CMainFrame::Onhuibian()
词法分析【测试用例】:
#include //测试字符
abc _ab //测试标识符
12 //测试正常十进制整数
12a //测试异常十进制整数
1.2 //测试浮点数
1.2.3 //测试异常浮点数
1.2e2+3 //测试正常浮点数
05.234e3 //测试异常浮点数
0.12 //测试正常浮点数
00.12e+4 //测试浮点数
0x34 //测试正常16进制数
0x3g //测试异常16进制数
0912 //测试异常8进制数
0712 //测试8进制数
0020 //测试异常8进制数
+ ++ += >==1 //测试双运算符
& && &= >>=2 //测试双运算符
| || |= <<=3 //测试双运算符
- -- -= <==4 //测试双运算符
char a='x'; //测试异常字符常量
b = 'b'; //测试异常字符常量
string d="12"; //测试异常字符串常量
c = "acc; //测试正常字符串常量
bool d = true;
void main()
{
int sum=1, b[3={1,2,3}; //测试括号配对,词法阶段可以不报错
scanf("%d",&sum);
for(int t=0;t<4;t++ //测试括号配对,词法阶段可以不报错
if(t>1)
sum*=t;
else if (t==2)
sum-=t;
else
sum++;
printf("t%dn",sum);
//测试注释不闭合
}
【测试结果】:
语法分析【测试用例1】:
int main(){
int result,N,M;
int i,factor;
int x,y,z,n,m;
i=0;n=2;factor=1;
x=1;y=2;n=3;m=4;
z=n+(x+y)*(m-x*y);
return z;
while(i= N) result = M ;
else result = N ;
for(i=0;i<10;i++)
{
result=N+M ;
}
}
【测试结果1】:
【测试用例2(错误测试用例)】:
//{}匹配
int main
{
int i,factor,n;
if(i>n){factor=1;
else factor=2;
}
【测试结果2】:
语义分析+四元式
【测试用例1】:(同语法分析测试用例1)
【测试结果1】:
【测试用例2(错误测试用例)】:
//未定义标识符错误
int main()
{
int i,factor,n;
a=0;
}
【测试结果2:】
生成目标代码
【测试用例1】: (同语法分析测试用例1)
【测试结果】:
测试结果说明分析
1、词法分析
可以识别正确的关键字、标识符、小数、整数、科学记数法、八进制、十六进制、字符常量、字符串常量、界限符、运算符,也可以处理掉注释(多行注释必须有下界);对于错误处理,可以识别错误的八进制、十六进制、错误的十进制、非法字符、非法字符、非法字符串,非法标识符,但没有下界的多行注释程序会停止运行。
2、语法分析
经过测试,主函数定义、变量定义、赋值语句、算术表达式、布尔表达式、关系表达式、赋值语句、if-else、while循环、for循环可以成功分析!但关于头文件、函数调用、以及其他执行语句文法里没有涉及到,所以无法分析。在错误处理这部分,当检测到错误时,语法分析就无法继续下去,会停留在错误点,除非将错误改正,因此每次语法分析的错误只能输出一个,效率有些低。
3、语义分析
经过测试,变量赋值、算术表达式、关系表达式、布尔表达式、if-else、while循环可以进行语义分析且生成对应的四元式!变量赋值、算术表达式、关系表达式生成的四元式,不论是计算结果,还是出现序列都是没有问题的,但我这里没有写关于寄存器的内容;布尔表达式没有区分‘&&’和‘||’的优先级,只能按顺序连接计算。if-else循环,语句跳转这里有一些问题,jnz可以成功跳转到执行语句的地址,jz就只能滞留在当前四元式这里。While循环只能跟if一样执行一次,不能循环运行。
4、目标代码
经过测试,可以生成变量赋值、算术表达式、关系表达式、布尔表达式、条件跳转这几类四元式的汇编语言。
总结及心得体会
在本次课设中,我完成了词法分析、语法分析、语义分析、目标代码生成的编写。四个功能整合到MFC中,实现了可视化,做成了一个简易的类C语言的编译器。
经过这次课设,感觉把之前在课堂学的有些一知半解的知识都给掌握了。我在整个课设期间,不仅学习了编译原理的知识,因为用c语言完成的整个课设,也对数据结构有了更熟练的运用,且还对MFC有了一定的掌握。
开发编译器是Dev-C和Visual C++ 6.0,功能源码是在Dev上写的,然后整合到Visual C++ 6.0,结合MFC改写代码实现可视化。
对于项目的缺陷,作为一个类c语言,由于文法定义不是特别全面,只能定义主函数,其他函数定义、函数调用不能编译,执行语句只有变量定义、赋值、算术表达式、布尔表达式、关系表达式、if-else、for、while可以进行编译。编译后端这部分功能比较薄弱。
参考文献
[1]黄贤英,曹琼,王柯柯等.编译原理及实践教程,北京:清华大学出版社,2019
完整MFC项目:
重庆理工大学2019级编译原理课程设计(c语言版)-C文档类资源-CSDN下载



