网站集约化平台建设分析专业网站优化
目 录
任务书 I
1引言 2
1.1课题背景与意义 2
1.2国内外研究现状 2
1.3课程设计的主要研究工作 2
2系统需求分析与总体设计 3
2.1系统需求分析 3
2.2系统总体设计 3
3系统详细设计 5
3.1有关常量、全局变量、数据类型以及数据结构的定义 5
3.2主要算法设计 6
4系统实现与测试 16
4.1系统实现 16
4.2系统测试 17
5总结与展望 24
5.1全文总结 24
5.2工作展望 24
6 体会 25
参考文献 26
附录 27
2系统需求分析与总体设计
2.1系统需求分析
本次课程设计要求将源代码的语法结构以树的形式表示,并能够先序遍历以缩进编排的格式输出该抽象语法树。搭建抽象语法树过程包括预处理源码并生成中间文件,以排除头文件、预处理、注释等附加的错误干扰;准确识别语言全部单词及出现的词法错误,并按种类编码进行单词与错误项显示;准确分析语法结构,并以函数调用、递归等方式进行抽象语法树的构建;选择合适的数据结构, 方便抽象语法树的遍历输出;进行串行调试,在各节点设置报错功能,优化交互便利性;以风格统一的格式化缩进编排,生成输出文件。
2.2系统总体设计
系统包含四个主功能:文件选择、词法分析、语法分析以及缩进编排。
(1)文件选择功能:系统的输入功能,通过外部输入设备输入待处理 C 语言源程序文件名,从而实现对指定文件的处理。并可以更换处理文件,方便多文件处理。
(2)词法分析功能:包含两个过程:预编译过程和词法分析过程。考虑到源程序内头文件、宏定义以及注释对词法分析带来困难,故将词法分析模块分解为两个子问题,分别通过函数调用实现。在预编译过程中,调用 pre_process 函数,主要准确识别头文件、宏定义以及注释,如头文件、宏定义以及注释出现编写错误,则输出预编译失败,并退出程序;如正确则生成中间文件 C_mid_file, 存放除去头文件、宏定义以及注释外的源程序。而词法分析过程中,调用
gettoken 函数识别中间文件中源程序单词,并输出单词类型、对应单词值和错误对应行数。
(3)语法分析功能:包含三个过程:预编译过程、生成抽象语法树和遍历语法树过程。同样调用 pre_process 函数处理头文件、宏定义及注释后生成
C_mid_file 文件。若预处理成功,则通过调用 program 函数生成抽象语法树, 如果出现语法错误,则退出函数,输出错误所在行;生成抽象语法树成功,则调用 TraverseTree 遍历树函数,显示抽象语法树。
(4)缩进编排功能:包含三个过程:预编译过程、生成抽象语法树和缩进编排过程。在经过预编译过程和生成抽象语法树后,调用 PrintFile 函数,生成
C_print_file 文件。
由于预编译操作分离与词法分析,故四个主功能可独立完成所选操作。除了彼此独立性外,阶段查错功能也为 C 语言源程序词法语法错误查找以及程序调试带来便利。为使界面更简洁明了,每个操作完成后使用 system(“cls”)清楚界面内容。
系统模块流程图如图 2-1 所示。
图 2-1 系统模块流程图
#include"lexer.h"
#include"parser.h"
#include"profuction.h"
#include"preprocess.h"
#include"printfile.h"int main() {char filename[30];int ch = 1;int w;CTree T;FILE* fp,*mid_fp;extern define_data data_Def[10];//用于储存define宏定义的内容extern int data_Def_num;extern int line_num;extern char token_text[100];int error_line[100];//记录错误行数int error_line_num=0;//记录错误总个数int i;//用于循环
Choosefile:system("cls");printf("输入文件名:");scanf("%s", filename);if (!(fp = fopen(filename, "r"))){printf("...选择文件错误,请重新选择...\n");getchar(); getchar();goto Choosefile;}else fclose(fp);while (ch){system("cls");printf("基于高级语言源程序格式处理工具菜单\n1. 词法分析\n2. 语法分析\n3. 缩进编排\n4. 选择文件\n0. 退出程序\n请选择:");scanf("%d", &ch);system("cls");switch (ch){case 1:error_line_num = 1;line_num = 1; //行数初始化为1if (!(fp = fopen(filename, "r"))) { printf("...选择文件错误,请重新选择...\n"); getchar(); getchar(); break; }printf("...正在预编译文件...\n");if (pre_process(fp)){printf("预编译成功!按任意键继续...\n");getchar(); getchar();}else{printf("预编译失败!退出系统!请检查错误!\n");getchar(); getchar();return 0;}mid_fp = fopen("C_mid_file.txt", "r");line_num = 1; //行数初始化为1system("cls");printf("\n");printf(" 单词类别 单词值\n");while (!feof(mid_fp)){w = gettoken(mid_fp);if (w >= AUTO && w <= DEFINE){printf(" 关键字 %s\n", token_text);}switch (w){case POUND:printf(" 井号 %s\n", token_text);break;case IDENT:printf(" 标识符 %s\n", token_text);break;case INT_CONST:printf(" 整型常量 %s\n", token_text);break;case UNSIGNED_CONST:printf(" 无符号整型常量 %s\n", token_text);break;case LONG_CONST:printf(" 长整型常量 %s\n", token_text);break;case UNSIGNED_LONG_CONST:printf(" 无符号长整型常量 %s\n", token_text);break;case DOUBLE_CONST:printf(" 双精度浮点型常量 %s\n", token_text);break;case FLOAT_CONST:printf(" 浮点型常量 %s\n", token_text);break;case LONG_DOUBLE_CONST:printf(" 长双精度浮点型常量 %s\n", token_text);break;case CHAR_CONST:printf(" 字符型常量 %s\n", token_text);break;case STRING_CONST:printf(" 字符串常量 %s\n", token_text);break;case EQUAL_TO:printf(" 赋值运算符 =\n");break;case PLUS:printf(" 加法运算符 +\n");break;case MINUS:printf(" 减法运算符 -\n");break;case MULTIPLY:printf(" 乘法运算符 *\n");break;case DIVIDE:printf(" 除法运算符 /\n");break;case MOD:printf(" 取模运算符 %%\n");break;case MORE:printf(" 关系运算符 >\n");break;case LESS:printf(" 关系运算符 <\n");break;case EQUAL:printf(" 关系运算符 ==\n");break;case UNEQUAL:printf(" 关系运算符 !=\n");break;case MORE_EQUAL:printf(" 关系运算符 >=\n");break;case LESS_EQUAL:printf(" 关系运算符 <=\n");break;case AND:printf(" 逻辑与 &&\n");break;case OR:printf(" 逻辑或 ||\n");break;case LS:printf(" 左小括号 (\n");break;case RS:printf(" 右小括号 )\n");break;case LM:printf(" 左中括号 [\n");break;case RM:printf(" 右中括号 ]\n");break;case LL:printf(" 左大括号 {\n");break;case RL:printf(" 右大括号 }\n");break;case SEMI:printf(" 分号 ;\n");break;case COMMA:printf(" 逗号 ,\n");break;case ERROR_TOKEN:error_line[error_line_num] = line_num;error_line_num++;break;}}printf("\n");printf("错误列表 错误总数%d\n", error_line_num);if (error_line_num){printf("\n");printf("序号 行数\n");for (i = 0; i < error_line_num; i++) {printf(" %d %d\n", i+1, error_line[i]);}}fclose(fp);fclose(mid_fp);printf("\n按任意键继续...");getchar();break;case 2:printf("...正在预编译文件...\n");line_num = 1; //行数初始化为1fp = fopen(filename, "r");if (pre_process(fp)){printf("预编译成功!按任意键继续...\n");getchar(); getchar();}else{printf("预编译失败!退出系统!请检查错误!\n");getchar(); getchar();return 0;}mid_fp = fopen("C_mid_file.txt", "r");line_num = 1; //行数初始化为1system("cls");if (!program(mid_fp, T)){printf("发生生成错误!错误行号:%d\n", line_num);printf("按任意键继续...\n");getchar(); break;}TraverseTree(T, PrintTree);printf("\n按任意键继续...\n");fclose(fp);fclose(mid_fp);getchar();break;case 3:line_num = 1; //行数初始化为1fp = fopen(filename, "r");if (!pre_process(fp)){printf("预编译失败!退出系统!请检查错误!\n");getchar(); getchar();return 0;}line_num = 1;mid_fp = fopen("C_mid_file.txt", "r");if (!program(mid_fp, T)){printf("程序存在语法错误!无法缩进打印!\n");getchar(); getchar();break;}else { printf("程序语法正确!\n"); }fclose(fp);fp = fopen(filename, "r");PrintFile(fp);printf("缩进编排文件生成成功!\n");getchar(); getchar();fclose(fp);fclose(mid_fp);break;case 4:goto Choosefile;default:return 0;}}return 1;}