1、北邮大三上-编译原理-词法分析实验报告 编译原理 第三章 词法分析 班级:311 学号: 姓名:schnee 20 / 21 目 录 1. 实验题目和要求 3 2. 检测代码分析 3 3.源代码…………………………………………………………………….. 4 1. 实验题目和要求 题目:词法分析程序的设计及实现。 实验内容:设计并实现C语言的词法分析程序,要求如下。 (1)、可以识别出用C语言编写的源程序中的每个单词符号,并以记号的形式输出每个单词符
2、号。 (2)、可以识别并读取源程序中的注释。 (3)、可以统计源程序汇总的语句行数、单词个数和字符个数,其中标点和空格不计算为单词,并输出统计结果 (4)、检查源程序中存在的错误,并可以报告错误所在的行列位置。 (5)、发现源程序中存在的错误后,进行适当的恢复,使词法分析可以继续进行,通过一次词法分析处理,可以检查并报告源程序中存在的所有错误。 实验要求: 方法1:采用C/C++作为实现语言,手工编写词法分析程序。 方法2:通过编写LEX源程序,利用LEX软件工具自动生成词法分析程序。 2. 检测代码分析 1、 Hello World简单程序输入: 2、 较复杂程序输入
3、
3. 异常程序输入检测
三, 源代码
#include
4、L_END=40;
const int R_END=81;
const int START=0; //开始指针
vector
5、终点,前进指针,
bool l_has, r_has; //辅助标记位,表示是否已经填充过缓冲区
vector
6、放入C中,forward指向下一个 void get_nbc(); //检查当前字符是否为空字符,反复调用直到非空 void retract(); //向前指针后退一位 void initial(); //初始化要词法分析的文件 void fillBuffer(int pos); //填充缓冲区,0表示左,1表示右 void analyzer(); //词法分析 void token_table(); //以记号的
7、形式输出每个单词符号 void note_print(); //识别并读取源程序中的注释 void count_number(); //统计源程序汇总的语句行数、单词个数和字符个数 void error_report(); //检查并报告源程序中存在的所有错误 void solve(char* file); //主调用函数 }; void welcome() { printf("\n******************************************************
8、\n"); printf( "** Welcome to use LexicalAnalyzer **\n"); printf( "** By schnee @BUPT Date: 2011/20/10 **\n"); printf( "*********************************************************\n\n\n"); } void initKey() { Key.clear(); Key.push_back("auto");
9、 Key.push_back("break"); Key.push_back("case"); Key.push_back("char"); Key.push_back("const"); Key.push_back("continue");Key.push_back("default"); Key.push_back("do"); Key.push_back("double"); Key.push_back("else"); Key.push_back("enum"); Key.push_back("extern"); Key.p
10、ush_back("float"); Key.push_back("for"); Key.push_back("goto"); Key.push_back("if"); Key.push_back("int"); Key.push_back("long"); Key.push_back("register");Key.push_back("return"); Key.push_back("short"); Key.push_back("signed"); Key.push_back("static"); Key.push_back("
11、sizeof"); Key.push_back("struct"); Key.push_back("switch"); Key.push_back("typedef"); Key.push_back("union"); Key.push_back("unsigned");Key.push_back("void"); Key.push_back("volatile");Key.push_back("while"); } void funtion::get_char() { C=buffer[forward]; if(C==EOF)return
12、 //结束 if(C=='\n')linenum++; //统计行数和字符数 else if(isalnum(C)) charnum++; forward++; if(buffer[forward]==EOF) { if(forward==l_end) { fillBuffer(1); forward++; } else if(forward==r_end) { fillBuffer(0); forward=START; } } } voi
13、d funtion::get_nbc() { while(C==' ' || C=='\n' || C=='\t' || C=='\0') get_char(); } void funtion::initial(char* file) { Id.clear(); //清空标识符表 l_end=L_END;r_end=R_END; //初始化缓冲区 forward=0; l_has=r_has=false; buffer[l_end]=buffer[r_end]=EOF; fillBuffer
14、0); linenum=wordnum=charnum=0; //初始化行数,单词数,字符数 } void funtion::fillBuffer(int pos) { if(pos==0)//填充缓冲区的左半边 { if(l_has==false) { fin.read(buffer, l_end); if(fin.gcount()!=l_end) buffer[fin.gcount()]=EOF; } else l_has=false; } else //填充缓冲区的右半边 {
15、 if(r_has==false) { fin.read(buffer+l_end+1, l_end); if(fin.gcount()!=l_end) buffer[fin.gcount()+l_end+1]=EOF; } else r_has=false; } } void funtion::retract() { if(forward==0) { l_has=true; //表示已经读取过文件,避免下次再次读取 forward=l_end-1; } else { forward--;
16、 if(forward==l_end) { r_add=true; forward--; } } } void funtion::analyzer() { FILE *token_file, *note_file, *count_file, *error_file; token_("token_", "w"); note_("note_", "w"); count_("count_", "w"); error_("error_", "w"); int i; curword.clear(); get_char();
17、
get_nbc();
if(C==EOF)return false;
if(isalpha(C) || C=='_')//关键字和标识符的处理,以字母或下划线开头
{
curword.clear();
while(isalnum(C) || C=='_')
{
curword.push_back(C);
get_char();
}
retract();
wordnum++;
Id.push_back(curword);
for(i=0; i 18、curword)
break;
//输出每一个单词的标识符
if(i 19、sdigit(C))
{
curword.push_back(C);
get_char();
}
if(C=='.' || C=='E' || C=='e')//处理小数和指数形式
{
curword.push_back(C);
get_char();
while(isdigit())
{
curword.push_back(C);
get_char();
}
}
retract();
wordnum++;
Id.push_back(curword);
fpri 20、ntf(token_file, "%8d----%20s %s\n", wordnum, "Unsigned Number", curword);
}
else if(C=='#')//过滤掉以#开头的预处理
{
fprintf(note_file, "preproccess Line %d : ", linenum);
get_char();
fprintf(note_file, "%c", C);
while(C!='\n')
{
get_char();
fprintf(note_file, "%c", C);
21、
}
fprintf(note_file, "%c", C);
}
else if(C=='"')//""内的句子当成整个串保存起来
{
curword.clear();
get_char();
while(C!='"')
{
curword.push_back(C);
get_char();
}
fprintf(token_file, "*****string in ""----%s\n", curword);
}
else if(C=='/')
{
get_char();
if(C=='/') 22、//过滤掉//开头的行注释
{
fprintf(note_file, "single-line note Line %d : ", linenum);
get_char();
curword.clear();
while(C!='\n')
{
curword.push_back(C);
get_char();
}
fprintf(note_file, "%s\n", curword);
}
else if(C=='*')//过滤掉/**/之间的段注释
{
fprintf(note_f 23、ile, "paragraph note Line %d : ", linenum);
get_char();
while(true)
{
while(C!='/')
{
fprintf(note_file, "%c", C);
get_char();
}
get_char();
if(C=='*')
{
fprintf(note_file, "\nto Line %d\n", linenum);
break;
}
fpri 24、ntf(note_file, "%c", C);
}
}
else if(C=='=')fprintf(token_file, "*****ASSIGN-OP, DIV\n");
else
{
fprintf(token_file, "*****CAL-OP, DIV\n");
retract();
}
} //处理各种比较,赋值,运算符号
else if(C=='<')
{
get_char();
if(C=='=')fprintf(token_file, "*****RELOP, LE\n");
else
25、
{
fprintf(token_file, "*****RELOP, LT\n");
retract();
}
}
else if(C=='>')
{
get_char();
if(C=='=')fprintf(token_file, "*****RELOP, GE\n");
else
{
fprintf(token_file, "*****RELOP, GT\n");
retract();
}
}
else if(C=='=')
{
get_char();
if(C=='=')fpr 26、intf(token_file, "*****RELOP, EQ\n");
else
{
fprintf(token_file, "*****ASSIGN-OP, EASY\n");
retract();
}
}
else if(C=='+')
{
get_char();
if(C=='=')fprintf(token_file, "*****ASSIGN-OP, ADD\n");
else
{
fprintf(token_file, "*****CAL-OP, ADD\n");
retract();
27、}
}
else if(C=='-')
{
get_char();
if(C=='=')fprintf(token_file, "*****ASSIGN-OP, SUB\n");
else
{
fprintf(token_file, "*****CAL-OP, SUB\n");
retract();
}
}
else if(C=='*')
{
get_char();
if(C=='=')fprintf(token_file, "*****ASSIGN-OP, MUL\n");
else
{
f 28、printf(token_file, "*****CAL-OP, MUL\n");
retract();
}
}
else if(C=='!')
{
get_char();
if(C=='=')fprintf(token_file, "*****RELOP, UE\n");
else if(!isalpha(C) && C!='_')
{
fprintf(error_file, "Line %d: error: '!' was illegal char \n", linenum);
}
}
else if(C== 29、':' || C=='(' || C==')' || C==';' || C=='{' || C=='}' || C==',')
fprintf(token_file, "*****Other char----%c\n", C);
else
fprintf(error_file, "Line %d: error: '%c' was illegal char \n", linenum, C);
fprintf(count_file, "The Line number is %d\n", linenum);
fprintf(count_file, "The 30、word number is %d\n", wordnum);
fprintf(count_file, "The char number is %d\n", charnum);
fclose(token_file);
fclose(note_file);
fclose(count_file);
fclose(error_file);
}
void funtion::token_table()
{
fin.open("token_");
printf("The token_table is as following:\n");
char str[1];
31、
while(1)
{
fin.read(str, 1);
if(str[0]!=EOF)printf("%c", str[0]);
}
}
void funtion::note_print()
{
fin.open("note_");
printf("The note is as following:\n");
char str[1];
while(1)
{
fin.read(str, 1);
if(str[0]!=EOF)printf("%c", str[0]);
}
}
void funtion::count_numbe 32、r()
{
fin.open("count_");
printf("The count result is as following:\n");
char str[1];
while(1)
{
fin.read(str, 1);
if(str[0]!=EOF)printf("%c", str[0]);
}
}
void funtion::error_report()
{
fin.open("error_");
printf("The error report is as following:\n");
char str[1];
whi 33、le(1)
{
fin.read(str, 1);
if(str[0]!=EOF)printf("%c", str[0]);
}
}
void funtion::solve(char* file)
{
;
fin.open();
intitial();
analyzer();
int choice;
printf("**** We have analyzed %s \n");
printf("**0: To end\n");
printf("**1: To get the token table\n");
printf("** 34、2: To get the note part of file\n");
printf("**4: To report all the error of the file\n");
printf("**3: To get the line num, word num and charter num\n\n");
while(1)
{
printf("****please input your choice: ");
scanf("%d", &choice);
if(choice==0)break;
if(choice==1)token_table 35、);
else if(choice==2)note_print();
else if(choice==3)count_number();
else error_report();
printf("\n");
}
}
void LexicalAnaylzer(char* file)
{
funtion test;
test.solve(file);
}
int main()
{
welcome();
initKey();
char ];
while(1)
{
printf("\nDo you want to continue? ("YES" or "NO"): ");
scanf("%s", file);
if(strcmp(file, "NO")==0)
{
printf("Thanks for your use! GoodBye next time!\n\n");
break;
}
printf("Please type your C (for example: a.cpp): ");
scanf("%s", file);
LexicalAnalyzer(file);
}
return 0;
}






