logo资料库

实验一 词法分析.doc

第1页 / 共10页
第2页 / 共10页
第3页 / 共10页
第4页 / 共10页
第5页 / 共10页
第6页 / 共10页
第7页 / 共10页
第8页 / 共10页
资料共10页,剩余部分请下载后查看
实验一 词法分析 1.实验要求 (1)从源程序文件中读取有效字符流并将其分析识别单词符号,转换成二元组内部表示形 式输出。 (2)可视化方式展示词法分析识别过程或者词法分析器工作原理(选做)。 (3)实验时间 4 学时。 (4)实验完成后,要提交实验报告(包括源程序清单)。 2.实验内容 2.1 主程序设计考虑: 主程序的说明部分为各种表格和变量安排空间(关键字和特殊符号表)。 id 和 ci 数组分别存放标识符和常数;还有一些为造表填表设置的变量。 主程序的工作部分建议设计成便于调试的循环结构。每个循环处理一个单词;调用词法 分析过程;输出每个单词的内部码(种别编码,属性值)。建议从文件中读取要分析的符号 串。 2.2 词法分析过程考虑 该过程根据输入单词的第一个有效字符(有时还需读第二个字符),判断单词种别,产 生种别编码。对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表 中已有该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组 id 中,将 常数存入数组中 ci 中,并记录其在表中的位置。 注:所有识别出的单词都用二元组表示。第一个表示单词的种别编码。例如:关键字 的 t=1;标识符的 t=2;常数 t=3;运算符 t=4;界符 t=5。第二个为该单词在各自表中的 指针或内部码值(常数表和标识符表是在编译过程中建立起来的。其 i 值是根据它们在源 程序中出现的顺序确定的)。 关键字和特殊符号如下(表中数字只是标记,不代表种别编码,种别编码自己定义): 编号 1 名字 int 编号 11 名字 printf 编号 21 名字 = = 编号 31 名字 ( 2 char 12 return 22 > 32 ) 3 float 13 main 23 < 33 { 4 void 14 read 24 != 34 } 5 const 15 + 25 >= 35 ; 7 6 else if 16 17 – * 26 27 <= && 36 37 , “ 8 do 18 / 28 || 38 ‘ 9 while 19 % 29 ! 39 ++ 10 scanf 20 = 30 <> 40 --
将词法分析程序设计成独立一遍扫描源程序的结构。参考设计流程图如下: 图 1 词法分析程序流程图 源代码:#define _CRT_SECURE_NO_WARNINGS #include"iostream" #include #include using namespace std; int i = 0; char character[1000000];//字,扫描用 int constNum = 0;//常数的个数 int biaoshifuNum = 0; //标识符的个数 char key[32][20] = { "int","char","float","void","const","if", "else","do","while","scanf","printf","return","main","read" };//关键字 t=1
char biaoshifubiao[100][30];//标识符 t=2 int consts[100];//常数 t=3 char operators[22][10] = { ":","++.","#",".","+","-","*","/","%","=","==",">", "<","!=",">=","<=","&&","||","!","<>","++","--" };//运算符 t=4 //界符 t=5 char border[10][5] = { "(",")","{","}",";",",","[","]","\"","\'" }; //------------------------查找关键字 int Key(char c[]) { for (i = 0; i < 15; i++) { if (strcmp(key[i], c) == 0)//如果查找成功,返回该关键字在关键字表中的位置 return i; } return -1; } //------------------------查找运算符 int YunSuanFu(char c[]) { for (i = 0; i < 16; i++) { if (strcmp(operators[i], c) == 0)//如果查找成功,返回该运算符在运算符表中的位置 { return i; } } return -1; } //-------------------------查找界符 int JieFu(char c[]) { for (i = 0; i < 10; i++) { if (strcmp(border[i], c) == 0)//如果查找成功,返回该界符在界符表中的位置 { return i; } } return -1;
} //------------------------查找常数 int ChangShu(int c) { for (i = 0; i < constNum; i++) { if (consts[i] == c)//如果查找成功,返回该界符在界符表中的位置 { return i; } } return -1; } //------------------------查找标识符 int BiaoShiFu(char c[]) { for (i = 0; i < biaoshifuNum; i++) { if (strcmp(biaoshifubiao[i], c) == 0)//如果查找成功,返回该界符在界符表中的位置 { return i; } } return -1; } //------------------------判断是不是关键字 bool IsKey(char c[]) { for (i = 0; i < 16; i++) { if (strcmp(key[i], c) == 0)//如果查找成功,返回该运算符在运算符表中的位置 { return true; } } return false; } //------------------------判断是不是字母 bool IsLetter(char c) { if (c >= 'a'&&c <= 'z' || c >= 'A'&&c <= 'Z' || c == '_') return true; return false;
} //------------------------判断是不是数字 bool Iscount(char c) { if (c >= '0'&&c <= '9') return true; return false; } //------------------------判断是不是界符 bool IsJieFu(char c) { if (c == '(' || c == ')' || c == '{' || c == '}' || c == ',' || c == ';' || c == '[' || c == ']' || c == '\'' || c == '\"') return true; return false; } //------------------------判断是不是运算符 bool IsYunSuanFu(char c) { //{"+","-","*","/","%","=","==",">","<","!=",">=","<=","&&","||","!","<>","++","--"}; if (c == ':' || c == '.' || c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '=' || c == '!' || c == '>' || c == '<' || c == '&' || c == '#' || c == '|') return true; return false; } //------------------------预处理(去掉注释) void YuChuLi(char c[], int n) { char NewCharacter[1000000]; int count = 0; for (i = 0; i < n; i++) { if (c[i] == '/'&&c[i + 1] == '/')//---------说明遇到了单行注释 { while (c[i] != '\n')//如果没有遇到回车,就继续向后扫描 i++; } if (c[i] == '/'&&c[i + 1] == '*')//说明遇到了多行注释 { i = i + 2; while (c[i] != '*'&&c[i + 1] != '/') {
i++; } i = i + 2; } if (c[i] != '\n'&&c[i] != '\r') { NewCharacter[count++] = c[i]; } } NewCharacter[count] = '\0'; strcpy(c, NewCharacter);//得到与处理后的程序 } int SaoMiao(char character[], int &p)//扫描程序 { int id = 0; char t[20]; int count = 0; char c = character[p]; while (c == ' ')//跳过空格 { p++; c = character[p]; } if (IsLetter(c))//如果单词开头为字母 { t[count++] = character[p]; p++; while (IsLetter(character[p]) || Iscount(character[p]))//如果单词后跟字母或数字 { t[count++] = character[p]; p++; } t[count] = '\0'; if (Key(t) != -1) { cout << "(关键字,"; for (i = 0; i < count; i++) cout << t[i]; cout << "," << Key(t) << ")"; cout << endl; return p;
} else //不是关键字,是标识符 { cout << "(标识符,"; if (BiaoShiFu(t) == -1)//如果不在标识符表中,将其添加进去 { for (i = 0; i < count; i++) { biaoshifubiao[biaoshifuNum][i] = t[i]; } biaoshifuNum++; for (i = 0; i < count; i++) { cout << t[i]; } cout << "," << biaoshifuNum - 1 << ")"; cout << endl; return p; for (i = 0; i < count; i++) cout << t[i]; cout << "," << BiaoShiFu(t) << ")"; cout << endl; return p; } else { } } } if (Iscount(character[p]))//如果首字符为数字 { t[count++] = character[p]; p++; while (Iscount(character[p]))//且后面还是数字 { t[count++] = character[p]; p++; }
t[count] = '\0'; int x = 0; for (i = 0; i < count; i++) { x = x * 10 + (t[i] - '0');//字符串中数字变成 int } cout << "(常量,"; if (ChangShu(x) == -1)//如果不在常量表中,将其添加进去 { consts[constNum++] = x; cout << x; cout << "," << constNum - 1 << ")"; cout << endl; return p; } else { } cout << x; cout << "," << ChangShu(x) << ")"; cout << endl; return p; } if (IsJieFu(character[p]))//如果为界符 { t[count++] = character[p]; p++; t[count] = '\0'; cout << "(界符,"; for (i = 0; i < count; i++) cout << t[i]; cout << ","; cout << JieFu(t) << ")"; cout << endl; return p; } if (IsYunSuanFu(character[p]))//如果为运算符 { t[count++] = character[p]; p++; if (IsYunSuanFu(character[p])) {
分享到:
收藏