四川大学Cminus语法分析器纯代码
- 格式:doc
- 大小:55.93 KB
- 文档页数:26
编译原理课程设计报告课题名称:C- Minus词法分析和语法分析设计1.课程设计目标实验建立C-编译器。
只含有扫描程序(scanner)和语法分析(parser)部分。
2.分析与设计C-编译器设计的整体框架,本实验实现扫描处理和语法分析程序(图中粗黑部分)。
打开源代码文件source.txt扫描处理(词法分析)记号语法分析程序语法树语义分析程序错误处理器注释树记号表源代码优化程序文字表中间代码代码生成器目标代码目标代码优化程序目标代码2.1 、扫描程序scanner部分2.1.1系统设计思想设计思想:根据DFA图用switch-case结构实现状态转换。
惯用词法:① 语言的关键字:else if int return void while② 专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */③ 其他标记是ID和NUM,通过下列正则表达式定义:ID = letter letter* NUM = digit digit*letter = a|..|z|A|..|Z digit = 0|..|9大写和小写字母是有区别的④ 空格由空白、换行符和制表符组成。
空格通常被忽略,除了它必须分开ID、NUM关键字。
⑤ 注释用通常的C语言符号/ * . . . * /围起来。
注释可以放在任何空白出现的位置(即注释不能放在标记内)上,且可以超过一行。
注释不能嵌套scanner的DFA/+ - * <= >= == != ; , ( ) [] { }INASSIGNWhite space >,<,=,!=digit\t \n[other]NUMdigit[other]STARTDONEletter[other]letterINID[other]ZHU*/[other]INCOMMENT*[other]ZZHU*说明:当输入的字符使DFA到达接受状态的时候,则可以确定一个单词了。
语法分析器源代码#include<stdio.h>#include<stdlib.h>#include<string.h>#define HIGHER 1#define LOWER -1#define EQUAL 0#define TRUE 1#define FALSE 0#define OPER_NUM 50 //默认算符数目 #define VN_NUM 50 //默认非终结符数目 #define MAX_BUFFER 128 //每行输入行最大长度#define MAX_GRA_NUM 20 //最大文法数目 #define EMPTY -2 //算符优先表初始值,表示这对算符没有优先关系fine STACK_SIZE 64 #detypedef struct{char c; //非终极符符号int firstvt[OPER_NUM]; //firstvt集,保存算符在oper_list中的下标int fir_n,last_n;int lastvt[OPER_NUM];}vn_t;int prior_table[OPER_NUM][OPER_NUM]; char oper_list[OPER_NUM];int oper_num = 0;vn_t vn_list[VN_NUM];int vn_num = 0;char *grammar[MAX_GRA_NUM][2]; int gra_num = 0;char start_vn;char stack[STACK_SIZE];int top = 0;void get_input(char *buf);int buf_deal(char* buf); void get_FIRVT_LASTVT(int vn_n);int create_table(); void init_table();int analyze(char *sentence); void display_table();void display_fir_lastvt(); int get_oper(char c); //得到算符c的数组下标没有返回-1int get_vn(char c); //得到非终结符c的数组下标,没有返回-1int is_vn(char a){return (('A'<=a&&a<='Z')?1:0); }int get_oper(char c){int i;for(i = 0; i < oper_num; ++i)if(oper_list[i] == c)return i;return -1;}int get_vn(char c){int i;for(i = 0; i < vn_num; ++i)if(vn_list[i].c == c)return i;return -1;}char reduce(int start, int end, int size) //规约{char *tar, *g, t1, t2, left;int i, j =0, gi, ti, cn = 0;int same;tar = (char *)malloc(sizeof(char)*MAX_BUFFER);if(!tar){printf("Allocation fails.\n");exit(-1);}for(i = start; i <= end; ++i) //将此最左素短语的终结符存入tar字符串{if(!is_vn(stack[i]))tar[j++] = stack[i];}tar[j++] = '\0';for(i = 0; i < gra_num; ++i) {g = grammar[i][1];gi = 0;ti = 0;same = FALSE;t1 = g[gi];t2 = tar[ti];while (t1 != '\0'){if(t2 == '\0' && !is_vn(t1)) {same = FALSE;break;}if(!is_vn(t1)){if(t1 != t2){same = FALSE;break;}t2 = tar[++ti];same = TRUE;}t1= g[++gi];}if(same && t2 == '\0')break;}if(i == gra_num){printf("无法找到相应文法~\n");return FALSE;}left = grammar[i][0][0];return vn_list[get_vn(left)].c; }int analyze(char *sentence) {char r, c,new_vn;int i = 0, k = 0, j, pi, printi = 1, cou = 1; //i是sentence[]和stack[]的索引int r_index, s_index, pre_index;printf("\n\n规约过程如下表所示:\n");printf("--------------------------------------\n");stack[top++] = '#';printf("序号\t符号栈\t最左素短语\t规约\t\n");do{r = sentence[i++];if((r_index = get_oper(r)) == -1){printf("Error : 您输入的字符不在文法定义中~\n"); flushall();c = getchar();flushall();return FALSE;}if(!is_vn(stack[k])){j = k;s_index = get_oper(stack[j]);}else{j = k - 1;s_index = get_oper(stack[j]);}while(prior_table[s_index][r_index] == HIGHER) {do{pre_index = s_index;if(!is_vn(stack[j-1])){j--;s_index = get_oper(stack[j]);}else{j -= 2;s_index = get_oper(stack[j]);}}while(prior_table[s_index][pre_index] != LOWER); printf(" %d\t", cou++);for(pi = 0; pi < top; ++pi){printf("%c",stack[pi]);}printf(" \t");for(pi = j + 1; pi <= k; ++pi){if (pi == j+1)printf(" %c",stack[pi]);elseprintf("%c",stack[pi]);}if((new_vn = reduce(j + 1, k, k - j)) == 0){return FALSE;}printf("\t\t %c\n",new_vn);k = j + 1; //规约最左素短语stack[k] = new_vn;top = k + 1;}if(prior_table[s_index][r_index] == LOWER ||prior_table[s_index][r_index] ==EQUAL){stack[++k] = r;top++;}else{printf("Error : 您输入的句型有错误~\n");return FALSE;}}while(r != '#');printf("--------------------------------------\n");return TRUE;}int buf_deal(char *buf){int i = 2,count = 0;char pre = buf[0], now;char *left_g, *right_g, *new_buf;left_g = (char *)malloc(sizeof(char)*2);right_g = (char *)malloc(sizeof(char)*(MAX_BUFFER-2)); if(!left_g || !right_g){printf("Allocation fails.\n");exit(-2);}if(is_vn(pre)){if(get_vn(pre) == -1){vn_list[vn_num].c = pre;vn_list[vn_num].fir_n = 0;vn_list[vn_num].last_n = 0;vn_num++;}left_g[count] = pre;count++;left_g[count] = '\0';}elsereturn FALSE;if(buf[1] != '-' || buf[2] != '>') return FALSE;pre = buf[2];count = 0;while((now = buf[++i]) != '\0') {if(now != '|'){right_g[count] = now;count++;if(is_vn(now) && is_vn(pre))return FALSE;if(is_vn(now)){if(get_vn(now) == -1){vn_list[vn_num].c = now;vn_list[vn_num].fir_n = 0;vn_list[vn_num].last_n = 0;vn_num++;}elsecontinue;}else{if(get_oper(now) == -1){oper_list[oper_num] = now; oper_num++;}elsecontinue;}pre = now;}else{right_g[count] = '\0'; grammar[gra_num][0] = left_g; grammar[gra_num][1] = right_g; gra_num++;break;}}if(buf[i] == '\0'){right_g[count] = '\0';grammar[gra_num][0] = left_g;grammar[gra_num][1] = right_g;gra_num++;}else{new_buf = (char *)malloc(sizeof(char)*MAX_BUFFER); new_buf[0] = left_g[0];new_buf[1] = '-';new_buf[2] = '>';strcpy(&new_buf[3],&buf[++i]);return buf_deal(new_buf);}return TRUE;}int create_table(){int gi = 0, ti, ni, fi, li, i;char *ng, t,next, next1;int t_index,n_index, n_index1, n_vn, t_vn;vn_t temp;for(gi = 0; gi < gra_num; ++gi ){ng = grammar[gi][1];t = ng[0];ti = 0;t_index = get_oper(t);next = ng[1];ni = 1;n_index = get_oper(next);while(next != '\0'){if(t_index != -1 && n_index != -1){if (prior_table[t_index][n_index] == EMPTY)prior_table[t_index][n_index] = EQUAL;else{printf("%c与%c有多种优先关系~\n",oper_list[t_index],oper_list[n_index]);return FALSE;}}else if(t_index != -1 && n_index == -1 && ng[ni+1] != '\0'){next1 = ng[ni+1];n_index1 = get_oper(next1);if(prior_table[t_index][n_index1] == EMPTY)prior_table[t_index][n_index1] = EQUAL;else{printf("%c与%c有多种优先关系~\n",oper_list[t_index],oper_list[n_index1]);return FALSE;}prior_table[t_index][oper_num - 1] = -3;prior_table[oper_num - 1][n_index1] = -3;}if (t_index != -1 && n_index == -1){n_vn = get_vn(next);temp = vn_list[n_vn];for(fi = 0; fi < temp.fir_n; fi++){if(prior_table[t_index][temp.firstvt[fi]] == EMPTY) prior_table[t_index][temp.firstvt[fi]] = LOWER; else{printf("%c与%c有多种优先关系~\n",oper_list[t_index],oper_list[temp.firstvt[fi]]); return FALSE;}}}else if(t_index == -1 && n_index != -1){n_vn = get_vn(t);temp = vn_list[n_vn];for(fi = 0; fi < st_n; fi++){if(prior_table[stvt[fi]][n_index] == EMPTY) prior_table[stvt[fi]][n_index] = HIGHER;else{printf("%c与%c有多种优先关系~\n",oper_list[fi],oper_list[n_index]);return FALSE;}}}t = ng[++ti];next = ng[++ni];t_index = get_oper(t);n_index = get_oper(next);}}for(i = 0; i < oper_num - 1; ++i){if(prior_table[oper_num - 1][i] != -3)prior_table[oper_num - 1][i] = LOWER;}for(i = 0; i < oper_num - 1; ++i){if(prior_table[i][oper_num - 1] != -3)prior_table[i][oper_num - 1] = HIGHER;}prior_table[oper_num - 1][oper_num - 1] = EQUAL; return TRUE;}void display_fir_lastvt(){int i, j;for (i = 0; i < vn_num; ++i){printf("FIRSTVT\(%c\) = { ", vn_list[i].c);for(j = 0; j < vn_list[i].fir_n; ++j){if (j == vn_list[i].fir_n - 1)printf(" %c ",oper_list[vn_list[i].firstvt[j]]); elseprintf(" %c ,",oper_list[vn_list[i].firstvt[j]]); }printf("}\n");printf("LASTVT\(%c\) = { ", vn_list[i].c);for(j = 0; j < vn_list[i].last_n; ++j){if (j == vn_list[i].last_n - 1)printf(" %c ",oper_list[vn_list[i].lastvt[j]]); elseprintf(" %c ,",oper_list[vn_list[i].lastvt[j]]); }printf("}\n\n");}}void display_table(){int i,j;printf("\n\t算符");for(i = 0; i < oper_num; ++i)printf("\t%c",oper_list[i]);printf("\n");for(i = 0; i < oper_num; ++i){printf("\t%c",oper_list[i]);for(j = 0; j <oper_num; ++j){if(prior_table[i][j] == 1)printf("\t>");else if(prior_table[i][j] == -1)printf("\t<");else if(prior_table[i][j] == 0)printf("\t=");elseprintf("\tNO");}printf("\n");}}void firstvt(int vn){int i, j, t, c_index, v_i, orin, pre = -1; char *ng, c;for(i = 0; i < gra_num; ++i){if (grammar[i][0][0] == vn_list[vn].c){ng = grammar[i][1];c = ng[0];if((c_index = get_oper(c)) != -1){vn_list[vn].firstvt[vn_list[vn].fir_n++] = c_index; continue;}else{v_i = get_vn(c);if(v_i != vn && v_i != pre){if(vn_list[v_i].fir_n == 0 )firstvt(v_i);orin = vn_list[vn].fir_n;vn_list[vn].fir_n += vn_list[v_i].fir_n;t = 0;for(j = orin; j < vn_list[vn].fir_n; ++j ){vn_list[vn].firstvt[j] = vn_list[v_i].firstvt[t++]; }}pre = v_i;if(ng[1] != '\0'){vn_list[vn].firstvt[vn_list[vn].fir_n++] = get_oper(ng[1]); }}}}}void lastvt(int vn){int i, j, t, c_index, v_i, orin, ni = 0, pre = -1;char *ng, c;for(i = 0; i < gra_num; ++i){if (grammar[i][0][0] == vn_list[vn].c){ng = grammar[i][1];ni = 0; //每次对新语法搜索时初始化位置。
语法分析程序的源代码#include<stdio.h>#include<string.h>char prog[80],token[6];char ch;int syn,p,m,n,sum,kk=0;char * rwtab[6]={"begin","if","then","while","do","end"};main(){p=0;printf("\nplease intput string:");do{ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();getch();}/*词法扫描程序:*/scaner(){for(n=0;n<8;n++)token[n]=NULL;m=0;ch=prog[p++];while(ch==' ')ch=prog[p++];if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')){while((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0')) {token[m++]=ch;ch=prog[p++];}token[m++]='\0';ch=prog[--p];syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}elseif((ch<='9'&&ch>='0')){sum=0;while((ch<='9'&&ch>='0')){sum=sum*10+ch-'0';ch=prog[p++];}ch=prog[--p];syn=11;}elseswitch(ch){case '<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}elseif(ch=='='){syn=22;token[m++]=ch;}else{syn=20;ch=prog[--p];}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=23;ch=prog[--p];}break;case ':':token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;ch=prog[--p];}break;case '+':syn=13;token[0]=ch;break;case '-':syn=14;token[0]=ch;break;case '*':syn=15;token[0]=ch;break;case '/':syn=16;token[0]=ch;break;case ':=':syn=18;token[0]=ch;break;case '<>':syn=21;token[0]=ch;break;case '<=':syn=22;token[0]=ch;break;case '>=':syn=24;token[0]=ch;break;case '=':syn=25;token[0]=ch;break;case ';':syn=26;token[0]=ch;break;case '(':syn=27;token[0]=ch;break;case ')':syn=28;token[0]=ch;break;case '#':syn=0;token[0]=ch;break;default:syn=-1;}}lrparser(){if(syn==1){scaner();if(syn==6){scaner();if((syn==0)&&(kk==0))printf("sucess");}else{if(kk!=1) printf("lost end error!");kk=1;}}else{printf("output of begin is error!");kk=1;}return;}yucu(){statement();while(syn==26){scaner();statement();}return;}statement(){if(syn==10){scaner();if(syn==18){scaner();expression();}{printf("output of equal is error!");kk=1;}}else{printf("input of sentence is error!");kk=1;}return;}expression(){term();while(syn==13||syn==14){scaner();term();}return;}term(){factor();while(syn==15||syn==16){scaner();factor();}return;}factor(){if(syn==10||syn==11)scaner();elseif(syn==27){scaner();expression();if(syn==28)scaner();else{printf("output ')' is error!");kk=1;}}else{printf("output expression is error!");kk=1;}return;}。
实验一:词法分析程序的设计与实现姓名:专业班级:学号:一、实验目的设计一个简单的词法分析器,从而进一步加深对词法分析器工作原理的理解。
二.、实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。
三、实验要求根据PL/0语言文法,编制词法分析程序GETSYM完成以下功能:1)从键盘读入数据,分析出一个单词。
2)返回单词种别(用整数表示),3)返回单词属性(不同的属性可以放在不同的全局变量中)。
四.、实验步骤1. 采用C语言,设计GETSYM ,实现该算法2. 编制测试程序(主函数main)。
3. 调试程序:输入一组单词,检查输出结果。
五.、实验设计分析1.词法的正规式描述S=aA|aA=(aA|dA)}(a|d)2.变换后的正规文法S→aAS→aA→aAA→dAA→aA→d3.词法分析程序的程序代码#include "stdafx.h"#include <iostream>#include<string>using namespace std;#define MAX 17char ch =' ';stringkey[17]={"const","long","float","double","void","main","if","else","then","break","int","char","in clude","for","while","printf","scanf"};int Iskey(string c){ //关键字判断int i;for(i=0;i<MAX;i++){if(key[i].compare(c)==0) return 1;}return 0;}int IsLetter(char c){ //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;else return 0;}int IsLetter1(char c){ //判断是否为a~f字母if(((c<='f')&&(c>='a'))||((c<='F')&&(c>='A'))) return 1;else return 0;}int IsDigit(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}void scan(FILE *fpin){string arr="";while((ch=fgetc(fpin))!=EOF){arr="";if(ch==' '||ch=='\t'||ch=='\n'){}else if(IsLetter(ch)||ch=='_'){arr=arr+ch;ch=fgetc(fpin);while(IsLetter(ch)||IsDigit(ch)){if((ch<='Z')&&(ch>='A')) ch=ch+32;arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);if (Iskey(arr)){cout<<arr<<"\t关键字"<<endl;}else cout<<arr<<"\t普通标识符"<<endl;}else if(IsDigit(ch)){int flag=0;if(ch=='0'){arr=arr+ch;ch=fgetc(fpin);if(ch>='0'&&ch<='7'){while(ch>='0'&&ch<='7'){flag=1;arr=arr+ch;ch=fgetc(fpin);}}else if(ch=='x'||ch=='X'){flag=2;arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)||IsLetter1(ch)){arr=arr+ch;ch=fgetc(fpin);}}else if(ch==' '||ch==','||ch==';' ){cout<<arr<<"\t整数0"<<endl;}fseek(fpin,-1L,SEEK_CUR);if(flag==1) cout<<arr<<"\t八进制整数"<<endl;else if(flag==2) cout<<arr<<"\t十六进制整数"<<endl;}else{arr=arr+ch;ch=fgetc(fpin);while(IsDigit(ch)){arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t十进制整数"<<endl;}}else switch(ch){case'+':case'-' :case'*' :case'=' :case'|' :case'/' :cout<<ch<<"\t运算符"<<endl;break;case'(' :case')' :case'[' :case']' :case';' :case'.' :case',' :case'{' :case'}' :cout<<ch<<"\t界符"<<endl;break;case':' :{ch=fgetc(fpin);if(ch=='=') cout<<":="<<"\t运算符"<<endl;else{cout<<"::"<<"\t界符"<<endl;;fseek(fpin,-1L,SEEK_CUR);}}break;case'>' :{ch=fgetc(fpin);if(ch=='=') cout<<">="<<"\t运算符"<<endl;if(ch=='>')cout<<">>"<<"\t输入控制符"<<endl;else {cout<<">"<<"\t运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;case'<' :{ch=fgetc(fpin);if(ch=='=')cout<<"<="<<"\t运算符"<<endl;else if(ch=='<')cout<<"<<"<<"\t输出控制符"<<endl;else if(ch=='>') cout<<"<>"<<"\t运算符"<<endl;else{cout<<"<"<<"\t运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;default : cout<<ch<<"\t无法识别字符"<<endl;}}}void main(){char in_fn[30];FILE * fpin;cout<<"请输入源文件名(包括路径和后缀名):";for(;;){cin>>in_fn;if((fpin=fopen(in_fn,"r"))!=NULL) break;else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";}cout<<"\n分析如下:\n"<<endl;scan(fpin);fclose(fpin);}七.实验测试:输入数据及运行结果:int a=3;double b=4;int c;if(a>b)c=a;elsec=b;。
1.实验目的及要求本次实验通过用C语言设计、编制、调试一个词法分析子程序,识别单词,实现一个C 语言词法分析器,经过此过程可以加深对编译器解析单词流的过程的了解。
运行环境:硬件:windowsxp软件:visual c++6。
02.实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4。
测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确.通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
3.实验内容本实验中将c语言单词符号分成了四类:关键字key(特别的将main说明为主函数)、普通标示符、常数和界符。
将关键字初始化在一个字符型指针数组*key[]中,将界符分别由程序中的case列出。
在词法分析过程中,关键字表和case列出的界符的内容是固定不变的(由程序中的初始化确定),因此,从源文件字符串中识别出现的关键字,界符只能从其中选取。
标识符、常数是在分析过程中不断形成的。
对于一个具体源程序而言,在扫描字符串时识别出一个单词,若这个单词的类型是关键字、普通标示符、常数或界符中之一,那么就将此单词以文字说明的形式输出.每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直到整个源程序全部扫描完毕,从而形成相应的单词串。
输出形式例如:void$关键字流程图、程序流程图:程序:#include〈string。
h〉#include〈stdio。
h〉#include〈stdlib。
h>#include<ctype。
h>//定义关键字char *Key[10]={”main”,”void”,"int","char",”printf",”scanf”,"else”,"if”,"return”};char Word[20],ch; // 存储识别出的单词流int IsAlpha(char c) { //判断是否为字母if(((c<='z’)&&(c〉=’a'))||((c〈='Z’)&&(c〉=’A'))) return 1; ﻩelse return 0;}int IsNum(char c){ //判断是否为数字ﻩif(c>='0’&&c<='9’) return 1;ﻩelse return0;}int IsKey(char *Word){//识别关键字函数ﻩintm,i;ﻩfor(i=0;i〈9;i++){ﻩif((m=strcmp(Word,Key[i]))==0){ﻩﻩif(i==0)ﻩﻩreturn 2;return 1;}}ﻩ return 0;}void scanner(FILE *fp){ //扫描函数ﻩcharWord[20]={'\0’};char ch;ﻩint i,c;ﻩch=fgetc(fp); //获取字符,指针fp并自动指向下一个字符if(IsAlpha(ch)){ //判断该字符是否是字母Word[0]=ch;ﻩch=fgetc(fp);i=1;ﻩwhile(IsNum(ch)||IsAlpha(ch)){ //判断该字符是否是字母或数字ﻩWord[i]=ch;ﻩﻩi++;ﻩch=fgetc(fp);ﻩ}ﻩWord[i]='\0'; //’\0' 代表字符结束(空格)ﻩfseek(fp,—1,1); //回退一个字符c=IsKey(Word); //判断是否是关键字ﻩﻩif(c==0) printf("%s\t$普通标识符\n\n",Word);//不是关键字ﻩelseif(c==2) printf(”%s\t$主函数\n\n”,Word);ﻩelse printf(”%s\t$关键字\n\n",Word); //输出关键字}else //开始判断的字符不是字母ﻩ if(IsNum(ch)){ //判断是否是数字ﻩWord[0]=ch;ﻩﻩ ch=fgetc(fp);ﻩﻩﻩ i=1;ﻩﻩ while(IsNum(ch)){ﻩﻩWord[i]=ch;ﻩﻩﻩﻩi++;ﻩﻩﻩﻩﻩch=fgetc(fp);ﻩﻩﻩ}ﻩﻩWord[i]='\0';ﻩﻩﻩfseek(fp,—1,1); //回退ﻩﻩprintf("%s\t$无符号实数\n\n”,Word);ﻩ }ﻩ else //开始判断的字符不是字母也不是数字ﻩ {ﻩﻩ Word[0]=ch;ﻩﻩ switch(ch){ﻩﻩ case'[’:ﻩcase’]’:ﻩﻩcase’(’:ﻩﻩﻩcase’)’:ﻩﻩcase’{':ﻩﻩcase’}':ﻩﻩcase’,’:case’"’:ﻩ case’;’:printf(”%s\t$界符\n\n",Word); break;ﻩcase'+’:ch=fgetc(fp);ﻩﻩﻩﻩWord[1]=ch;ﻩif(ch=='='){ﻩﻩﻩ printf("%s\t$运算符\n\n",Word);//运算符“+=”ﻩﻩ}ﻩﻩ elseif(ch=='+’){ﻩprintf("%s\t$运算符\n\n”,Word); //判断结果为“++"ﻩﻩﻩ}ﻩﻩelse {fseek(fp,-1,1);printf(”%s\t$运算符\n\n",Word); //判断结果为“+”ﻩﻩﻩ }ﻩﻩ break;ﻩﻩ case'-':ch=fgetc(fp);Word[1]=ch;ﻩﻩﻩ if(ch=='='){ﻩﻩﻩprintf(”%s\t$运算符\n\n",Word); ﻩﻩ}ﻩ else if(ch=='-’){ﻩprintf(”%s\t$运算符\n\n",Word); //判断结果为“-—" ﻩﻩﻩﻩ}ﻩﻩﻩelse{ﻩﻩfseek(fp,-1,1);printf("%s\t$运算符\n\n",Word); //判断结果为“-”ﻩ}ﻩﻩﻩ break;ﻩcase'*’:ﻩﻩcase’/':case'!':ﻩﻩcase’=':ch=fgetc(fp);ﻩﻩ if(ch=='=’){ﻩﻩ printf("%s\t$运算符\n\n",Word);ﻩﻩﻩﻩ }ﻩﻩﻩ else {ﻩﻩﻩ fseek(fp,—1,1);ﻩﻩﻩﻩﻩ printf(”%s\t$运算符\n\n”,Word);ﻩﻩﻩ }ﻩﻩﻩﻩ break;ﻩcase'〈’:ch=fgetc(fp);ﻩﻩWord[1]=ch;ﻩﻩﻩﻩ if(ch==’=’){ﻩﻩﻩﻩﻩprintf("%s\t$运算符\n\n",Word);//判断结果为运算符“<=”ﻩﻩ }ﻩﻩﻩﻩ else if(ch==’<'){ﻩﻩﻩprintf(”%s\t$运算符\n\n”,Word); //判断结果为“〈〈"ﻩﻩﻩ}ﻩﻩﻩ else{ﻩﻩ fseek(fp,-1,1);ﻩﻩ printf(”%s\t$运算符\n\n”,Word); //判断结果为“<”ﻩﻩﻩﻩﻩ}ﻩﻩﻩ break;case’〉’:ch=fgetc(fp);ﻩ Word[1]=ch;ﻩif(ch==’=’) printf("%s\t$运算符\n\n”,Word);ﻩelse {ﻩﻩﻩfseek(fp,-1,1);ﻩprintf(”%s\t$运算符\n\n",Word);ﻩﻩﻩ }ﻩﻩ break;ﻩﻩ case’%':ch=fgetc(fp);ﻩﻩﻩﻩWord[1]=ch;ﻩﻩif(ch==’=’){printf("%s\t$运算符\n\n”,Word);} ﻩﻩ if(IsAlpha(ch))printf(”%s\t$类型标识符\n\n”,Word);ﻩﻩelse {ﻩﻩﻩfseek(fp,-1,1);ﻩﻩﻩﻩﻩ printf(”%s\t$取余运算符\n\n”,Word);ﻩﻩﻩ}break;default:printf(”无法识别字符!\n\n");break;ﻩﻩ }ﻩ}}main(){ﻩchar in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):”);while(1){gets(in_fn);ﻩ//scanf("%s”,in_fn);if((fp=fopen(in_fn,"r”))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:”);ﻩ}printf("\n*******************词法分析结果如下*******************\n");do{ﻩ ch=fgetc(fp);if(ch==’#’) break; //文件以#结尾,作为扫描结束条件ﻩ else if(ch==’ '||ch==’\t'||ch==’\n’){} //忽略空格,空白,和换行ﻩelse{ﻩﻩ fseek(fp,—1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!=’#’);return(0);}4.实验结果解析源文件:void main(){int a=3;a+=b;printf("%d",a);return;}#解析结果:5.实验总结分析通过本次实验,让再次浏览了有关c语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。
, 睡河心孕IIIIII 编译原理实验报告IIII! 题目: Cminus语言词法分析器I装订线I 学院计算机科学与技术II 专业xxxxxxxxxxxxxxxxI| 学号xxxxxxxxxxxxI 姓名xxxxI ---------------------------- ! 指导教师xxxxIIII20xx年xx月xx日C_minus语言词法分析器一、 实验目的1. 理解词法分析器的设计方法:利用DFA 编写相应的程序。
2. 掌握手工编写词法分析程序的方法。
3. 复习熟悉以前学过的编程语言4. 通过实验了解编译器词法分析的工作原理 二、 实验原理1. 文法的概念,DFA 的表示方法。
2. 词法分析程序的输出和输入:词法分析程序的功能是读入源程序, 输出单词符号。
单 词符号是程序设计语言的比本语法符号, 程序设计语言的单词符号一般分为如下几种: 关键 字,标示符,常数,运算符,界符,单词的输出是二元式的形式,需要知道二元式的表示方法,把得到的二元式写入输出文件。
转化图如下:3.熟悉单词的描述工具, 及他们之间的互相转化。
熟悉把正规文法转化为正规式,把正规式转化为 转为相应的DFA 最后再把DFA 简化, 器4.C 语言的基本语法。
、实验要求1、该个词法分析器要求至少能够识别以下几类单词:关键字: else if int return void while 共 6 个, 是小写;标识符:识别与 C 语言词法规定相一致的标识符,通过下列正则表达式定义:ID = letter (letter | digit)* 常数:NUM= digitletter = a|..|z|A|..|Z| 学计数法表示的常数,如专用符号:+-如正规文法,正规式,以及知道正规文法和正规式的等价性以NFA 以及把NFADFA 的状态转化为相应的子程序,最后得到词法分析 鸟式kr NFA 正规文法尸 DFA 状态最小 DFA ► 词法 分析器 所有的关键字都是保留字,并且必须 digit*(.digit digit* | & )(e(+ | - | & ) digit digit* | & ), ,digit =0|..|9 ,包括整数,如123等;小数,如123.45等;科 1.23e3 , 2.3e-9 等;*/<<=>>===!==,()[]{}/* */ ;2、分析器的输入为由上述几类单词构成的程序,输出为该段程序的机内表示形式,即关键字、运算符、界限符变为其对应的机内符,常数使用二进制形式,标识符使用相应的标识符表指针表示。
四川大学计算机学院、软件学院实验报告学号姓名:专业:DFA数据类型数据结构设计//定义数据类型TokenTypetypedef enum{ENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE,ID,NUM,ASSIGN,EQ,LT,LE,GT,GE,NEQ,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,LBRACKET,RBRACKET,LBRACE,RBRACE,COMMA,SEMI} TokenType;//定义状态类型typedef enum{ START,LBUFFER,RBUFFER,INCOMMENT,INNUM,INID,INEQ,INLE,INGE,INNEQ,DO NE }StateType;//结构定义实验结果截图总结词法分析程序的输出和输入:词法分析程序的功能是读入源程序,输出单词符号。
单词符号是程序设计语言的本语法符号,程序设计语言的单词符号一般分为如下几种:关键字,标示符,常数,运算符,界符,单词的输出是二元式的形式,需要知道二元式的表示方法,把得到的二元式写入输出文件。
实验注意事项:1.试验中在设计注释部分的解析时,因为C-Minus的注释符是四个字符组成,设计DFA时设计了两个中间态,用来判断状态转换;在代码中,如果由中间态转换为INCOMMENT状态,注意字符回退和save置false2.在判断运算符<,<=,>,>=,!=时,第二字符是’=’可成功识别出运算符,第二字符是其他字符时也可能是合法符号,注意字符回退与token判断。
参考资料:《编译原理及实践/编译器设计方案》。
编译原理课程设计报告课题名称: C-词法扫描器及语法分析器实现提交文档学生姓名: XXX提交文档学生学号: 0943041XXX同组成员名单:无指导教师姓名:张兵指导教师评阅成绩:指导教师评阅意见:..提交报告时间:2012年 6月 2日目录1 课程设计目标 (2)2 分析与设计 (2)2.1 程序结构 (2)2.2 程序流程 (3)3 词法分析 (4)3.1 代码结构分析 (4)3.2 Token定义 (4)3.2.1 Token的定义和类型 (4)3.2.2 Token的种别码 (5)3.3 DAF分析 (5)3.3.1 删除注释DFA (5)3.3.2 词法分析DFA (7)4 语法分析 (10)4.1 代码结构分析 (10)4.2 节点定义 (11)4.2.1 节点定义和类型 (11)4.2.2 各类型节点的描述 (11)4.3 递归向下语法分析 (12)4.3.1 C-文法 (12)4.3.2 递归向下分析过程 (13)5 测试结果 (30)5.1 流程 (30)5.2 词法分析结果 (31)5.3 词法分析出错 (34)5.4 语法分析结果 (34)5.5 语法分析出错 (36)6 总结 (36)6.1 词法分析编写过程 (36)6.2 语法分析编写过程 (36)6.3 成果和收获 (37)7 附录 (37)7.1 scanner.h源文件 (37)7.2 scanner.cpp源文件 (38)7.3 parser.h源文件 (47)7.4 parser.cpp源文件 (49)1 课程设计目标学生在学习《编译原理》课程过程中,结合各章节的构造编译程序的基本理论,要求用C或C++语言描述及上机调试,实现一个C-Minus 小编译程序(包括词法分析,语法分析等重要子程序),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。
要求:(1)设计词法分析器设计各单词的状态转换图,并为不同的单词设计种别码。
using System;using System.IO;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace WindowsFormsApplication3{public partial class Form1 : Form{public Form1(){InitializeComponent();}struct pronode{public char leftch;public string midch;public string rightch;public string select;}struct unnifo{public char ch;public string first;public string follow;}unnifo[] firstfollow = new unnifo[20];//放first 和follow;pronode[] proNode = new pronode[30];//产生式pronode[,] table1 = new pronode[15, 15];//分析表string vnstr;//非终结符string vtstr;//终结符string kong;//含有空的终结符int lenvn;//定义非终结符的个数int lenwenfa;//定义产生式的数目public void getvnstr()//取非终结符函数{int i;int len = proNode.Length;for (i = 0; i < len; i++){if (vnstr == null){vnstr += proNode[i].leftch;}else{int lenth = vnstr.Length;int j;for (j = 0; j < lenth; j++){if (proNode[i].leftch == vnstr[j]){break;}}if (j == lenth){vnstr += proNode[i].leftch;}}}}public void getvtstr()//取终结符函数{bool flag;int i;int len = proNode.Length;for (i = 0; i < lenwenfa; i++){int lenth = proNode[i].rightch.Length;int j;for (j = 0; j < lenth; j++){flag = true;if (isvn(proNode[i].rightch[j])){flag = false;}else{if (proNode[i].rightch[j] == '?'){flag = false;if (kong == null){kong += proNode[i].leftch;}else{int k;int leng = kong.Length;for (k = 0; k < leng; k++){if (proNode[i].rightch[j] == kong[k]){break;}}if (k == leng + 1){kong += proNode[i].leftch;}}}else{if (flag){if (vtstr == null){vtstr += proNode[i].rightch[j];}else{int h;int lenvt = vtstr.Length;for (h = 0; h < lenvt; h++){if (proNode[i].rightch[j] == vtstr[h]){break;}}if (h == lenvt){vtstr += proNode[i].rightch[j];}}}}}}}}public void createfirf()//定义first和follow 集函数{int i;int len = vnstr.Length;for (i = 0; i < len; i++){firstfollow[i].ch = vnstr[i];firstfollow[i].first = "";firstfollow[i].follow = "";}}public void getlenvn()//取终结符个数函数{lenvn = vnstr.Length;}public Boolean isvn(char ch)//比较是非终结符{int i;string vn;vn = textBox1.Text;for (i = 0; i < vn.Length; i++){if (vn[i] == ch){return true;}}return false;}public Boolean isvt(char ch)//比较是终结符函数{int i;string vt;vt = textBox2.Text;for (i = 0; i < vt.Length; i++){if (vt[i] == ch){return true;}}return false;}public string addchar(string vtstrch, char ch)//在字符串中加字符{bool flag = true;int temlen = vtstrch.Length;for (int i = 0; i < temlen; i++){if (vtstrch[0] == ch){flag = false;break;}}if (flag){vtstrch = vtstrch + ch;}return vtstrch;}public Boolean iskongch(char ch)//判断字符为能推出空集的非终结符;{int i;string temkong;temkong = textBox3.Text;for (i = 0; i < temkong.Length; i++){if (ch == temkong[i]){return true;}}return false;}public string addchtoch(string chstr, string otherarr)//在字符串终结字符串函数{int otherlen = otherarr.Length;for (int j = 0; j < otherlen; j++){bool flag = true;int tmlen = chstr.Length;for (int i = 0; i < tmlen; i++){if (chstr[i] == otherarr[j]){flag = false;break;}}if (flag){if (otherarr[j] != '?'){chstr = chstr + otherarr[j].ToString();}}}return chstr;}public void first1()//求first集的第一步骤{int i;for (i = 0; i < lenvn; i++){for (int j = 0; j < lenwenfa; j++){if (firstfollow[i].ch == proNode[j].leftch){int lenth = firstfollow[i].first.Length;int k;for (k = 0; k < lenth; k++){if (firstfollow[i].first[k] == proNode[j].rightch[0]){break;}}if (k == lenth){firstfollow[i].first += proNode[j].rightch[0].ToString();}}}}}public void first2()//求first集的第二步骤{int i;for (i = 0; i < lenvn; i++){int j;char ch;int lenth = firstfollow[i].first.Length;for (j = 0; j <= lenth - 1; j++){if (isvn(firstfollow[i].first[j]) == true)//判断first集中是否有非终结符;{ch = firstfollow[i].first[j];for (int h = 0; h < lenvn; h++){if (firstfollow[h].ch == ch){firstfollow[i].first = firstfollow[i].first.Remove(j, 1);firstfollow[i].first = addchtoch(firstfollow[i].first, firstfollow[h].first);}}lenth = firstfollow[i].first.Length;j = 0;}}}}public void follow1()//求follow 集的第一步{int i;firstfollow[0].follow = addchar(firstfollow[0].follow, '#');//开始符要先加‘#’;for (i = 0; i < lenvn; i++){for (int j = 0; j < lenwenfa; j++){int k;for (k = 0; k < proNode[j].rightch.Length; k++){if (proNode[j].rightch[k] == firstfollow[i].ch)//判断右边的字符串中的非终结符有等于等于要求follow集的非终结符;{if (k + 1 == proNode[j].rightch.Length)//判断要求follow集的非终结符为右边字符串的最后一个字符;{int lenth2 = firstfollow[i].follow.Length;if (lenth2 == 0){firstfollow[i].follow = firstfollow[i].follow + proNode[j].leftch;//将该文法产生式的左边字符加到follow集中}else{for (int m = 0; m < lenth2; m++){if (firstfollow[i].follow[m] != proNode[j].leftch){firstfollow[i].follow = firstfollow[i].follow + proNode[j].leftch;}}}}if (k + 1 < proNode[j].rightch.Length)//判断要求follow集的非终结符的在右边字符串中出现且不是在最后一个字符{char ch = proNode[j].rightch[k + 1];if (isvt(ch))//判断是终结符{int lenth1 = firstfollow[i].follow.Length;if (lenth1 == 0){firstfollow[i].follow = firstfollow[i].follow + ch;}else{firstfollow[i].follow = addchar(firstfollow[i].follow, ch);}}if (isvn(ch))//判断为非终结符{if (!iskongch(ch))//该非终结不能推出空集;{for (int n = 0; n < lenvn; n++){if (firstfollow[n].ch == ch){addchtoch(firstfollow[i].follow, firstfollow[n].first);}}}else{for (int w = 0; w < lenvn; w++){if (firstfollow[w].ch == ch){addchtoch(firstfollow[i].follow, firstfollow[w].first);}int lenth3 = firstfollow[i].follow.Length;for (int l = 0; l < lenth3; l++){if (firstfollow[i].follow[l] != proNode[j].leftch){firstfollow[i].follow += proNode[j].leftch;}}}}}}}}}}}public void follow2()//求follow集的第二步{int i;for (i = 0; i < lenvn; i++){char ch;int lenth = firstfollow[i].follow.Length;int j;for (j = 0; j < lenth; j++){if (isvn(firstfollow[i].follow[j]))//判断follow集中是否有非终结符;{ch = firstfollow[i].follow[j];for (int k = 0; k < lenvn; k++){if (firstfollow[k].ch == ch){firstfollow[i].follow = firstfollow[i].follow.Remove(j, 1);firstfollow[i].follow = addchtoch(firstfollow[i].follow, firstfollow[k].follow);}}lenth = firstfollow[i].follow.Length;j = 0;}}}}public void select()//求select集{int i;for (i = 0; i < lenwenfa; i++){if (isvt(proNode[i].rightch[0])){int lenth = proNode[i].select.Length;int j;for (j = 0; j < lenth; j++){if (proNode[i].select[j] == proNode[i].rightch[0]){break;}}if (j == lenth){proNode[i].select += proNode[i].rightch[0];}}if (proNode[i].rightch[0] == '?')//集中'?'来表示空集;{int k;for (k = 0; k < lenvn; k++){if (firstfollow[k].ch == proNode[i].leftch){proNode[i].select = addchtoch(proNode[i].select, firstfollow[k].follow);}}}if (isvn(proNode[i].rightch[0])){int h;for (h = 0; h < lenvn; h++){if (firstfollow[h].ch == proNode[i].rightch[0]){int len = firstfollow[h].first.Length;int m;proNode[i].select = addchtoch(proNode[i].select, firstfollow[h].first);for (m = 0; m < len; m++){if (firstfollow[h].first[m] == '?')//集中'?'来表示空集;{int n;for (n = 0; n < lenvn; n++){if (firstfollow[n].ch == proNode[i].leftch){proNode[i].select = addchtoch(proNode[i].select, firstfollow[n].follow);}}}}}}}}}public int getvn(char ch)//求字符在非终结中的位置{int i;string vn;vn = textBox1.Text;for (i = 0; i < vn.Length; i++){if (vn[i] == ch){return i;}}return -1;}public int getvt(char ch)//求字符在终结符中的位置{int j;string vt;vt = textBox2.Text;for (j = 0; j < vt.Length; j++){if (vt[j] == ch){return j;}}return -1;}public void create_table()//建立分析表{int row;int col;int k;for (k = 0; k < lenwenfa; k++){int m;int lensel = proNode[k].select.Length;for (m = 0; m < lensel; m++){row = getvn(proNode[k].leftch);col = getvt(proNode[k].select[m]);table1[row, col] = proNode[k];}}}public void prtable(int m, int n)//输出表中每个元素{if (m != -1 && n != -1){richTextBox1.AppendText(table1[m, n].leftch + table1[m, n].midch + table1[m, n].rightch);}}public void shtabel()//显示表的内容{richTextBox1.AppendText("\t");int i;string vt;vt = textBox2.Text;for (i = 0; i < vt.Length; i++){richTextBox1.AppendText(vt[i] + "\t");}int k;for (k = 0; k < vt.Length; k++){if (vt[k] == '#'){richTextBox1.AppendText("\n");break;}}if (k == vt.Length)richTextBox1.AppendText("#" + "\n");}int j;string vn;vn = textBox1.Text;for (j = 0; j < vn.Length; j++){richTextBox1.AppendText(vn[j] + "\t");for (int n = 0; n < lenvn; n++){prtable(j, n);richTextBox1.AppendText("\t");}richTextBox1.AppendText("\n");}}public char getfirst(string str)//取第一个字符{char ch;int len;len = str.Length;if (len == 0){return (' ');}else{ch = str[0];return ch;}}public string remfirst(string str1)//删除第一个字符{int len = str1.Length;if (len == 0){return ("");}else{str1 = str1.Remove(0, 1);return str1;}public char getlast(string str)//取最后一个字符{char ch;int len;len = str.Length;if (len == 0){return (' ');}else{ch = str[len - 1];return ch;}}public string remlast(string str1)//删除最后一个字符{int len = str1.Length;if (len == 0){return ("");}else{str1 = str1.Remove(len - 1, 1);return str1;}}public void error(){richTextBox1.AppendText("分析错误!" + "\n"); }public void success(){richTextBox1.AppendText("Successful!" + "\n"); }public void scan()//分析过程{string prstr;int step = 1;int left;int right;char ch;char ch1;bool flag = true;string temstr = "#S";prstr = textBoxch.Text;richTextBox1.AppendText("步骤" + "\t" + "符号栈" + "\t" + "读入符号" + "\t" + "剩余符号串" + "\t" + "使用产生式" + "\n");richTextBox1.AppendText(step + "\t" + temstr + "\t");step++;ch = getfirst(prstr);prstr = remfirst(prstr);richTextBox1.AppendText(ch + "\t" + "\t");while (flag){richTextBox1.AppendText(prstr + "\t" + "\t");ch1 = getlast(temstr);temstr = remlast(temstr);left = getvn(ch1);right = getvt(ch);prtable(left, right);if (isvt(ch1)){if (ch1 == ch){richTextBox1.AppendText(ch1 + "匹配" + "\n");ch = getfirst(prstr);prstr = remfirst(prstr);richTextBox1.AppendText(step + "\t" + temstr + "\t" + ch + "\t" + "\t");step++;}else{flag = false;error();}}else{if (ch1 == '#'){if (ch == ch1){richTextBox1.AppendText("分析成功!" + "\n");success();flag = false;}else{flag = false;error();}}else{left = getvn(ch1);right = getvt(ch);if (right != -1){if (table1[left, right].leftch != '\0'){if (table1[left, right].rightch[0] != '?')//集中'?'来表示空集;{richTextBox1.AppendText("\n");int lenrigth = table1[left, right].rightch.Length;int len1;for (len1 = lenrigth - 1; len1 >= 0; len1--){temstr += table1[left, right].rightch[len1];}richTextBox1.AppendText(step + "\t" + temstr + "\t" + ch + "\t" + "\t");step++;}else{richTextBox1.AppendText("\n");richTextBox1.AppendText(step + "\t" + temstr + "\t" + ch + "\t" + "\t");step++;}}else{flag = false;error();}}else{flag = false;error();}}}}}public void getwenfa()//初始化文法数组{string[] s = richTextBox2.Text.Split('\n');int i;lenwenfa = s.Length - 1;for (i = 0; i < lenwenfa; i++){int j;proNode[i].leftch = s[i][0];proNode[i].midch += s[i][1];proNode[i].midch += s[i][2];for (j = 3; j < s[i].Length; j++){proNode[i].rightch += s[i][j];}proNode[i].select = "";}}private void Form1_Load(object sender, EventArgs e){for (int i = 0; i < lenwenfa; i++){richTextBox2.AppendText(proNode[i].leftch + proNode[i].midch + proNode[i].rightch + "\n");}}private void button2_Click(object sender, EventArgs e)//求字符按钮{getwenfa();getvnstr();textBox1.Text = vnstr;getvtstr();textBox2.Text = vtstr;textBox3.Text = kong;createfirf();getlenvn();}private void butn_Click_1(object sender, EventArgs e)//分析按钮{string temstr;first1();first2();follow1();follow2();richTextBox1.AppendText("非终结符" + "\t" + "FIRST集" + "\t" + "\t" + "FOLLOW 集" + "\n");for (int i = 0; i < lenvn; i++){richTextBox1.AppendText(firstfollow[i].ch + "\t" + "\t" + firstfollow[i].first + "\t" + "\t" + firstfollow[i].follow + "\n");}richTextBox1.AppendText("\n");select();richTextBox1.AppendText("文法产生式" + "\t" + "SELECT集" + "\n");for (int j = 0; j < lenwenfa; j++){richTextBox1.AppendText(proNode[j].leftch + proNode[j].midch + proNode[j].rightch + "\t" + "\t" + proNode[j].select + "\n");}richTextBox1.AppendText("\n");create_table();richTextBox1.AppendText("**************欢迎你使用该语法分析器**************" + "\n");richTextBox1.AppendText("\n");richTextBox1.AppendText("预测分析表:" + "\n");shtabel();richTextBox1.AppendText("\n");temstr = textBoxch.Text;if (temstr != "")//要求输入一个句子{int lenth = temstr.Length;if (temstr[lenth - 1] == '#')//要求输入的句子以‘#’结束;{scan();}else{MessageBox.Show("请以“#“结尾!");richTextBox1.Text = "";}}else{MessageBox.Show("请输入句子!");textBoxch.Text = "";richTextBox1.Text = "";}}private void button1_Click(object sender, EventArgs e)//清除按钮{textBoxch.Text = "";richTextBox1.Text = "";}private void 清除ToolStripMenuItem_Click_1(object sender, EventArgs e) {textBoxch.Text = "";richTextBox1.Text = "";}private void 说明ToolStripMenuItem_Click_1(object sender, EventArgs e) {MessageBox.Show("本程序所有权属于本程序的开发者!");}private void button3_Click(object sender, EventArgs e)//打开文件按钮{if (openFileDialog1.ShowDialog() == DialogResult.OK){FileStream fs = new FileStream(openFileDialog1.FileName, FileMode.Open);StreamReader sw = new StreamReader(fs);while (!sw.EndOfStream){richTextBox2.AppendText(sw.ReadLine() + "\n");}sw.Close();}}}}。
#include<string>#include<vector>using namespace std;void scaner(); //扫Α?描âvoid checkIDF(); //检ì查ã是?否?是?保馈?留?字?void checkNum(); //检ì查ã是?否?是?数簓字?void retract(); //回?退?char getChar(); //获?取?下?一?个?字?符?void concatenation(); //连?接ó字?符?int reserve(); //检ì查ã是?否?是?保馈?留?字?void buildlist1(); //建¨立ⅰ?标括?识?符?表括?void buildlist2(); //建¨立ⅰ?数簓字?表括?void error(); //报馈?错洙?bool letter(); //字?母?bool digit(); //数簓字?char character[80],token[8],ch,tk[4]; //character数簓组哩?保馈?存?输?入?的?所õ有瓺字?符? token当獭?前°要癮检ì查ã的?字?符?int sy,syn,pt,pc,pL1=0,pL2=0,p5,p6; //syn 种?别纄编括?码? pt token数簓组哩?下?标括? pc character数簓组哩?下?标括? pL1 标括?志?符?表括?下?标括? pL2 数簓字?表括?下?标括?vector<string> list1; //标括?志?符?表括?vector<int> list2; //数簓字?表括?void scaner(){pt=0;for(int i=0;i<8;i++){token[i]=NULL;}char s=getChar();while((s==' ')||(s=='\n')){s=getChar();}if(((s<='z')&&(s>='a'))||((s<='Z')&&(s>='A'))){checkIDF();}else if((s>='0')&&(s<='9')){syn=7;checkNum();}else switch(s){case'=':s=getChar();if(s=='='){sy=1;syn=14;strcpy(token,"relop");strcpy(tk,"EQ");}else{syn=8;retract();token[pt]='=';}break;case'+':token[pt]='+';syn=9;break;case'*':s=getChar();if(s=='*'){syn=11;strcpy(token,"**");}else{retract();token[pt]='*';syn=10;}break;case'-':token[pt]='-';syn=12;break;case'/':token[pt]='/';syn=13;break;case'>':syn=14;s=getChar();if(s=='='){sy=3;strcpy(token,"relop");strcpy(tk,"ME");}else{sy=2;retract();strcpy(token,"relop");strcpy(tk,"MT");}break;case'<':syn=14;s=getChar();if(s=='='){sy=5;strcpy(token,"relop");strcpy(tk,"LE");}else{sy=4;retract();strcpy(token,"relop");strcpy(tk,"LT");}break;case'!':s=getChar();if(s=='='){syn=14;strcpy(token,"relop");strcpy(tk,"UEQ");}else{retract();cout<<"第台?<<p5<<"句?"<<"第台?<<p6<<"个?字?符?!=";error();}break;case';':syn=15;token[pt]=';';break;case',':syn=16;token[pt]=',';break;case'(':syn=17;token[pt]='(';break;case')':syn=17;token[pt]=')';break;case'&':s=getChar();if(s=='&'){syn=18;strcpy(token,"&&");}else{retract();cout<<"第台?<<p5<<"句?"<<"第台?<<p6<<"个?字?符?&&";error();}break;case'|':s=getChar();if(s=='|'){syn=19;strcpy(token,"||");}else{retract();cout<<"第台?<<p5<<"句?"<<"第台?<<p6<<"个?字?符?&&";error();}break;default:{cout<<"第台?<<p5<<"句?"<<"第台?<<p6<<"个?字?符?不?能÷识?别纄,";error();}}}void checkIDF(){while(letter()||digit()){concatenation();getChar();}retract();int c=reserve();if(c==0){buildlist1();syn=6;}else{syn=c;}}void checkNum(){while(digit()){concatenation();getChar();}retract();buildlist2();strcpy(token,"num");}void retract(){pc--;p6--;}char getChar(){char cc=character[pc++];p6++;if(cc==';'){p5++;p6=0;}return cc;}void concatenation(){token[pt++]=character[pc-1];}int reserve(){if(strcmp(token,"while")==0)return 1;else if(strcmp(token,"if")==0)return 2;else if(strcmp(token,"else")==0)return 3;else if(strcmp(token,"switch")==0)return 4;else if(strcmp(token,"case")==0)return 5;elsereturn 0;}void buildlist1()//建¨立ⅰ?标括?识?符?表括?{char *c=new char[8];strcpy(c,token);list1.push_back(c);pL1++;}//建¨立ⅰ?标括?识?符?表括?void buildlist2() //建¨立ⅰ?数簓字?表括?{int i;int n = 0;for (i = 0; token[i] >= '0' && token[i] <= '9'; ++i) {n = 10 * n + (token[i] - '0');}list2.push_back(n);pL2++;}void error(){cout<<"出?现?错洙?误ó----------------"<<endl;}bool letter(){char s=character[pc-1];if(((s<='z')&&(s>='a'))||((s<='Z')&&(s>='A'))){return true;}elsereturn false;}bool digit(){char s=character[pc-1];if((s>='0')&&(s<='9'))return true;elsereturn false;}#include<iostream>using namespace std;int lookahead; //当獭?前°种?别纄编括?码?int a1,v,p7,p8; //a1 pa数簓组哩?下?标括? v=0表括?示? (辍? v=1 表括?示? )?int pa[100][2]; //第台?一?维?保馈?存?单蹋?词洙?的?种?别纄编括?码? 第台?二t维?用?来ぁ?区?分?种?别纄编括?码?相à同?的?单蹋?词洙?int nexttoken(); //下?一?个?单蹋?词洙?的?种?别纄编括?码?void match();void S();void A();void Op();void B();void relop();void E();void E1();void T();void T1();void F();void p();void error1();int nexttoken(){v=pa[++a1][1];int paa=pa[a1][0];p8++;if(paa==15){p7++;p8=0;}return pa[a1][0];}void match(int t){if(lookahead==t){lookahead=nexttoken();}else{error1();}}void S(){if(lookahead==1){cout<<"S-> while(A) S"<<endl;match(1);if(lookahead==17&&v==0){match(17);A();}else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?左哩?括ぁ?号?";error1();}if(lookahead==17&&v==1){match(17);S();}else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?右 ?括ぁ?号?";error1();}}else if(lookahead==6||lookahead==7){cout<<"S-> i=E;"<<endl;match(lookahead);if(lookahead==8){match(8);E();else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?= 号?";error1();}if(lookahead==15)match(15);else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?; 号?";error1();}}else if(lookahead==2){cout<<"S->if (A) S else S"<<endl;match(2);if(lookahead==17&&v==0){match(17);A();}else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?左哩?括ぁ?号?";error1();}if(lookahead==17&&v==1){match(17);S();}else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?右 ?括ぁ?号?";error1();}cout<<lookahead<<endl;if(lookahead==3){match(3);S();}else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?if缺ø?少Θ?相à应畖的?else";error1();}}{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?不?匹¥配?文?法ぁ?;error1();}}void A(){cout<<"A->B Op B | B"<<endl;B();while(lookahead==18||lookahead==19){Op();B();}}void Op(){if(lookahead==18||lookahead==19){if(lookahead==18)cout<<"Op->&&"<<endl;elsecout<<"Op->||"<<endl;match(lookahead);}else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?逻?辑-运?算?符?不?匹¥配?";error1();}}void B(){cout<<"B->E relop E"<<endl;E();relop();E();}void relop(){if(v==1)cout<<"relop-> =="<<endl;else if(v==2)cout<<"relop-> >"<<endl;else if(v==3)cout<<"relop-> >="<<endl;else if(v==4)cout<<"relop-> <"<<endl;else if(v==5)cout<<"relop-> <="<<endl;if(lookahead==14)match(14);else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?逻?辑-运?算?符?不?匹¥配?";error1();}}void E(){cout<<"E->T E1"<<endl;T();E1();}void E1(){cout<<"E1->+T E1"<<endl;if(lookahead==9){match(9);T();E1();}}void T(){cout<<"T->F T1"<<endl;F();T1();}void T1(){cout<<"T1->*F T1"<<endl;if(lookahead==10){match(10);F();T1();}}void F(){cout<<"F-> P**F|P"<<endl;p();while(lookahead==11){match(11);p();}}void p(){if(lookahead==6||lookahead==7){cout<<"P->i"<<endl;match(lookahead);}else if(lookahead==17&&v==0){cout<<"P->(E)"<<endl;match(17);E();if(lookahead==17&&v==1)match(17);else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?右 ?括ぁ?号?";error1();}}else{cout<<"第台?<<p7<<"句?"<<"第台?<<p8<<"个?字?符?缺ø?少Θ?左哩?括ぁ?号?或ò文?法ぁ?不?匹¥配?";error1();}}void error1(){cout<<"------------语?法ぁ?分?析?错洙?误ó---------"<<endl;exit(0);}#include<iostream>#include"cf.h"#include"yf.h"using namespace std;int a,b,c,d,vv,nxq; //a pa数簓组哩?词洙?法ぁ?分?析?时骸?的?下?标括? b 保馈?存?pa当獭?前°下?标括?值μ c pa数簓组哩?语?义?分?析?时骸?的?下?标括? d 中D间?变?量?的?下?标括? vv=0 表括?示? (辍? vv=1 表括?示? )?int lookahead1; //pa数簓组哩?当獭?前°下?标括? nxq 下?一?条?将?要癮产ö生Θ?的?四?元a式?的?地?址·int e[20][4]; //4元a式? 数簓组哩?int s; //4元a式?数簓组哩?下?标括?void S1();int A1();void Op1();int B1();int relop1();int E2();int T2();int F1();int P1();void error2();void scaner1();int emit(int a,int b,int c,int d); //保馈?存?当獭?前°4元a式?int newtemp();void backpatch(int p,int t);void show();int merge(int p1,int p2);void main(){cout<<"*************************词洙?法ぁ?分?析?器ô****************************"<<endl;cout<<"**********************单蹋?词洙?符?号?种?别纄编括?码?*************************"<<endl;cout<<"(while ,1) (if ,2) (else , 3) (switch ,?4) (case ,5) "<<endl;cout<<"(标括?志?符?, 6) (常£数簓, 7) ( = ,8) ( + , 9) ( * , 10)"<<endl;cout<<"( ** ,11) ( - ,12) (/ ,13) ( > ,14) ( >= ,14)"<<endl;cout<<"( < ,14) ( <= ,14) (== ,14) ( != ,14) ( ; ,15)"<<endl;cout<<"( , ,16) ( ( ,17) ( ) ,17) (辍?& ,? 18)? (辍?|| ,?19)? "<<endl;cout<<"请?输?入?一?串?字?符?,?以?#号?键÷结á束?:";pc=0;do//读á入?字?符?{scanf("%c",&ch);character[pc++]=ch;}while(ch!='#');pt=0;pc=0;a=0,b=0,c=0,d=0,a1=0,v=0,vv=0,s=0,p5=1,p6=0,p7=1,p8=1;cout<<"--------------词洙?法ぁ?分?析?开a始?--------------------"<<endl;do//词洙?法ぁ?分?析?{if(character[pc]=='#')break;syn=0;scaner();if((syn>=1&&syn<=5)||(syn>=8&&syn<=13)||(syn>=15&&syn<=16)||syn==18||syn==19) {cout<<"("<<token<<" ,"<<syn<<")"<<endl;pa[a++][0]=syn;}else if(syn==6)//标括?示?符?{cout<<"("<<"id"<<" ,"<<(pL1-1)<<")"<<endl;b=a++;pa[b][0]=syn;pa[b][1]=pL1-1;}else if(syn==7)//常£数簓{cout<<"("<<"num"<<" ,"<<(pL2-1)<<")"<<endl;b=a++;pa[b][0]=syn;pa[b][1]=pL2-1;}else if(syn==14){cout<<"("<<token<<" ,"<<syn<<")"<<endl;b=a++;pa[b][0]=syn;pa[b][1]=sy;//内ö码?值μ}else if(syn==17){cout<<"("<<token<<" ,"<<syn<<")"<<endl;b=a++;if(strcmp(token,"(")==0){pa[b][0]=syn;pa[b][1]=0;}else{pa[b][0]=syn;pa[b][1]=1;}}else{syn=30;cout<<"------------"<<endl;}}while(syn!=0);cout<<endl;cout<<"------------语?法ぁ?分?析?开a始?------------"<<endl;lookahead=pa[0][0];//种?别纄编括?码? 区?分?相à同?S(); //语?法ぁ?分?析?cout<<"语?法ぁ?分?析?成ã功|"<<endl;cout<<endl;cout<<"------------语?义?分?析?开a始?-------------"<<endl;nxq=200;lookahead1=pa[c][0];S1(); //语?义?分?析?show();cout<<"语?义?分?析?成ã功|"<<endl;}void S1(){if(lookahead1==1){int t;scaner1();if(lookahead1==17&&vv==0){scaner1();t=A1();}else{cout<<"1:阰while后ó左哩?括ぁ?号?非?法ぁ?!?"<<endl;error2();}if(lookahead1==17&&vv==1){scaner1();S1();int tt=e[t-1][3]-2;emit(20,-1,-1,tt);backpatch(t,nxq);}else{cout<<"2:阰while后ó右 ?括ぁ?号?非?法ぁ?!?"<<endl;error2();}}else if(lookahead1==6||lookahead1==7){int t,v3;if(lookahead1==6)//标括?示?符?{v3=pa[c][1]*10+1;}else//常£熟酣?v3=pa[c][1]*10+2;scaner1();if(lookahead1==8){scaner1();t=E2();emit(8,t,-1,v3);}else{cout<<"3"<<endl;error2();}if(lookahead1==15)scaner1();elseerror1();}else if(lookahead1==2){scaner1();int t3,t4;if(lookahead1==17&&vv==0){scaner1();t3=A1();}elseerror2();if(lookahead1==17&&vv==1){scaner1();S1();t4=emit(20,-1,-1,0);backpatch(t3,nxq);}else{error2();}if(lookahead1==3){scaner1();S1();backpatch(t4,nxq);}else{error2();}}else{error2();}}int A1(){int t1=B1();int t2;int i=0;while(lookahead1==18||lookahead1==19){i=1;Op1();t2=B1();t1=merge(t2,t1);}return t1;}void Op1(){if(lookahead1==18||lookahead1==19){scaner1();}else{error2();}}int B1(){int t1=E2();int o=relop1();int t2=E2();emit(o,t1,t2,nxq+2);t1=emit(20,-1,-1,0);return t1;}int relop1(){int v1=vv;if(lookahead1==14)scaner1();elseerror1();if(v1==1){return 14*10+1;}else if(v1==2){return 14*10+2;}else if(v1==3){return 14*10+3;}else if(v1==4){return 14*10+4;}else if(v1==5){return 14*10+5;}}int E2(){int e1=T2();int t=e1; //中D间?变?量?的?下?标括?while(lookahead1==9){scaner1();int e2=T2();t=newtemp();emit(9,e1,e2,t*10+3);e1=t*10+3;t=t*10+3;}return t;}int T2()//乘?{int t1=F1();int t=t1; //中D间?变?量?的?下?标括?while(lookahead1==10){scaner1();int t2=F1();t=newtemp();emit(10,t1,t2,t*10+3);t1=t*10+3;t=t*10+3;}return t;}int F1()// 乘?方?{int f1=P1();int t=f1; //中D间?变?量?的?下?标括?while(lookahead1==11){scaner1();int f2=P1();t=newtemp();emit(11,f1,f2,t*10+3);f1=t*10+3;t=t*10+3;}return t;}int P1(){if(lookahead1==6){scaner1();return pa[c-1][1]*10+1;}else if(lookahead1==7){scaner1();return pa[c-1][1]*10+2;}else if(lookahead1==17&&vv==0){scaner1();int pp=E2();if(lookahead1==17&&vv==1){scaner1();return pp;}else error2();}else error2();}void error2(){cout<<"语?义?出?错洙?<<endl;exit(0);}void scaner1(){vv=pa[++c][1];lookahead1=pa[c][0];}int emit(int a,int b,int c,int d){e[s][0]=a;e[s][1]=b;e[s][2]=c;e[s][3]=d;s++;nxq++;return s-1;}int newtemp(){return ++d;}int merge(int p1,int p2){if(p2==0)return p1;else{e[p2][3]=p1;return p2;}}void backpatch(int p,int t)//四?元a式?第台?四?区?段?改?写′为at {int Q=p;int q;while(Q!=0){q=e[Q][3];e[Q][3]=t;Q=q;}}void show(){int e1,e2,e3,e4,j=200;for(int i=0;i<s;i++){e1=e[i][0];e2=e[i][1];e3=e[i][2];e4=e[i][3];switch(e1){case 8:cout<<j<<"( = ,";break;case 9:cout<<j<<"( + ,";break;case 10:cout<<j<<"( * ,";break;case 11:cout<<j<<"( ** ,";break;case 12:cout<<j<<"( - ,";break;case 13:cout<<j<<"( / ,";break;case 20:cout<<j<<"( j ,";break;default:;}if(e1/10==14){switch(e1%10){case 1:cout<<j<<"( j== ,";break;case 2:cout<<j<<"( j> ,";break;case 3:cout<<j<<"( j>= ,";break;case 4:cout<<j<<"( j< ,";break;case 5:cout<<j<<"( j<= ,";break;}}if(e2<0)cout<<" _";else if(e2%10==1)cout<<list1[e2/10]; //标括?识?符? else if(e2%10==2)cout<<list2[e2/10]; //数簓字?else if(e2%10==3)cout<<"T"<<e2/10; //中D间?变?量?cout<<" , ";if(e3<0)cout<<" _";else if(e3%10==1)cout<<list1[e3/10];else if(e3%10==2)cout<<list2[e3/10];else if(e3%10==3)cout<<"T"<<e3/10;cout<<" , ";if(e4>=200)cout<<e4;else if(e4%10==1)cout<<list1[e4/10];else if(e4%10==2)cout<<list2[e4/10];else if(e4%10==3)cout<<"T"<<e4/10;cout<<" )"<<endl;j++;}}。
四川大学计算机学院 C-语言编译器编译原理课程设计报告内附源码递归下降 c minus编译原理课程设计报告课题名称: C-词法扫描器及语法分析器实现提交文档学生姓名: XXX 提交文档学生学号: 0943041XXX 同组成员名单: 无指导教师姓名: 张兵指导教师评阅成绩: 指导教师评阅意见: . .提交报告时间:2012年 6月 2日《编译原理课程设计报告》计算机学院计科x班 xxx 094304xxxx目录1 课程设计目标 ..................................................................... ..... 3 2 分析与设计 ..................................................................... . (4)2.1 程序结构 ..................................................................... (4)2.2 程序流程 ..................................................................... ... 5 3 词法分析 ..................................................................... (6)3.1 代码结构分析 ....................................................................63.2 Token定义......................................................................73.2.1 Token的定义和类型 (7)3.2.2 Token的种别码 (7)3.3 DAF分析 ..................................................................... (8)3.3.1 删除注释DFA (8)3.3.2 词法分析DFA ............................................................. 10 4 语法分析 ..................................................................... .. (14)4.1 代码结构分析 ...................................................................144.2 节点定义 ..................................................................... .. 154.2.1 节点定义和类型 (15)4.2.2 各类型节点的描述 (16)4.3 递归向下语法分析 (16)4.3.1 C-文法 ...................................................................164.3.2 递归向下分析过程 .......................................................... 17 5 测试结果 ..................................................................... .. (34)5.1 流程 ..................................................................... (34)5.2 词法分析结果 ...................................................................345.3 词法分析出错 ...................................................................385.4 语法分析结果 ...................................................................395.5 语法分析出错 ...................................................................41 6 总结...................................................................... .. (42)6.1 词法分析编写过程 (42)6.2 语法分析编写过程 (43)6.3 成果和收获 .....................................................................43 7 附录...................................................................... .. (44)7.1 scanner.h源文件 (44)7.2 scanner.cpp源文件 (45)7.3 parser.h源文件 (54)7.4 parser.cpp源文件 (56)指导老师:张兵老师 2《编译原理课程设计报告》计算机学院计科x班 xxx 094304xxxx1 课程设计目标学生在学习《编译原理》课程过程中,结合各章节的构造编译程序的基本理论,要求用C或C++语言描述及上机调试,实现一个 C-Minus 小编译程序(包括词法分析,语法分析等重要子程序),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。
计算机学院 编译原理实验报告实验项目 C_minus 语言词法分析器的设计 实验日期 实验报告要求: 一、实验目的设计编写并调试一个词法分析程序,能够完成读入源程序,输出单词符号的 功能。
加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程 中将其分解为各类单词的词法分析方法。
编写一个读单词的过程,从输入的源程序 中识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符和界符五大 类单词,并依次输出各个单词的内部编码及单词符号自身的值。
二、实验原理词法分析是编译的第一个阶段,他的主要任务是从左至右逐个字符地对源程 序进行扫描,产生一个个单词序列用以语法分析,执行词法分析的程序即为词法分 析程序,在程序中先判断这个语句中的每个单元为关键字、常数、运算符、界符, 对不同的单词符号给出不同编码形式的编码用以区分之,识别出源程序中的单词并 以二元式的形式输出。
三、实验要求1、该个词法分析器要求至少能够识别以下几类单词:a . 关键字: else if int return void while 共 6 个,所有的关键字年级 2008 级 学号 姓名 成绩专业实验地点 指导教师都是保留字,并且必须是小写;形式,即关键字、运算符、界限符变为其对应的机内符,常数使用二进制形式,标 识符使用相应的标识符表指针表示。
3、词法分析器应当能够指出源程序中的词法错误,如不可识别的符号、错误 的词法等。
四、实验结果(程序)及分析#include "stdio.h" #include "conio.h"#include "ctype.h" #include "string.h" char area[80]={'\0'}, wordchar[8];char ch;b . 标识符:识别与 C 语言词法规定相一致的标识符,通过下列正则表达式 定义: ID = letter (letter | digit)* ;常数: NUM = digit digit*(.digit digit* | ε )(e(+| - | ε) digitε),letter = a|..|z|A|..|Z|,digit = 0|..|9 ,包括整数,如 123专用符号: + - * / < <= > >= == != = ; , ( ) [ ] { } /* */ ;c .digit* |等。
计算机学院编译原理实验报告年级2008级学号姓名成绩专业实验地点指导教师实验项目C_minus语言词法分析器的设计实验日期实验报告要求:一、实验目的设计编写并调试一个词法分析程序,能够完成读入源程序,输出单词符号的功能。
加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编写一个读单词的过程,从输入的源程序中识别出各个具有独立意义的单词,即关键字、标识符、常数、运算符和界符五大类单词,并依次输出各个单词的内部编码及单词符号自身的值。
二、实验原理词法分析是编译的第一个阶段,他的主要任务是从左至右逐个字符地对源程序进行扫描,产生一个个单词序列用以语法分析,执行词法分析的程序即为词法分析程序,在程序中先判断这个语句中的每个单元为关键字、常数、运算符、界符,对不同的单词符号给出不同编码形式的编码用以区分之,识别出源程序中的单词并以二元式的形式输出。
三、实验要求1、该个词法分析器要求至少能够识别以下几类单词:a.关键字:else if int return void while共6个,所有的关键字都是保留字,并且必须是小写;b.标识符:识别与C语言词法规定相一致的标识符,通过下列正则表达式定义:ID = letter (letter | digit)*;c.常数:NUM = digit digit*(.digit digit* |ε)(e(+ | - |ε) digit digit* |ε),letter = a|..|z|A|..|Z|,digit = 0|..|9,包括整数,如123等。
d.专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */;2、分析器的输入为由上述几类单词构成的程序,输出为该段程序的机内表示形式,即关键字、运算符、界限符变为其对应的机内符,常数使用二进制形式,标识符使用相应的标识符表指针表示。
#include<fstream>#include<iostream>#include<string>#include<strstream>using namespace std;#define BUFLEN 256#define MAXLEN 256#define MAXTOKENLEN 40#define MAXCHILDREN 4static int lineno;static int linepos = 0;//读取的字符在lineBuf的位置static int EOF_FLAG = false;static int bufsize = 0;//lineBuf的长度static char lineBuf[BUFLEN];FILE * source;char tokenString[MAXTOKENLEN+1];string output;//输出文件enum TokenType{ENDFILE,ERROR,IF,ELSE,INT,RETURN,VOID,WHILE,ID,NUM,ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI,LBRACKET,RBRA CKET,LBRACE,RBRACE,COMMA,GT,GEQ,NEQ,LEQ};enum StateType{START,INASSIGN,INCOMMENT,INNUM,INID,DONE,PRECOMMENT,AFTERCOMMENT };struct{char* str;TokenType tok;}ReserverWords[6]= { {"if",IF},{"else",ELSE},{"int",INT},{"return",RETURN},{"void",VOID},{"w hile",WHILE} };void UnGetNextChar(){if (!EOF_FLAG)linepos--;}int GetNextChar(){if(!(linepos<bufsize)){lineno++;if(fgets(lineBuf,BUFLEN-1,source)){bufsize=strlen(lineBuf);linepos=0;return lineBuf[linepos++];}else{EOF_FLAG=true;return EOF;}}else{return lineBuf[linepos++];}}TokenType ReservedLookUp(char * s){int i;for (i = 0; i < 6; i++){if(!strcmp(s,ReserverWords[i].str)){return ReserverWords[i].tok;}}return ID;}TokenType GetToken(){StateType state = START;//初始状态为startbool save;TokenType CurrentToken;int tokenStringIndex=0;string assign="";while(state!=DONE){int c=GetNextChar();save = true;switch (state){case START:if (isdigit(c)){state = INNUM;}else if (isalpha(c)){state = INID;}else if ((c == '<')||(c=='>')||(c=='=')||(c=='!')){state = INASSIGN;assign+=char(c);}else if ((c == ' ') || (c == '\t') || (c == '\n'))save = false;else if (c == '/'){save = false;state = PRECOMMENT;}else{state = DONE;switch (c){case EOF:save = false;CurrentToken = ENDFILE;break;case'+':CurrentToken = PLUS;break;case'-':CurrentToken = MINUS;break;case'*':CurrentToken = TIMES;break;case'(':CurrentToken = LPAREN;break;case')':CurrentToken = RPAREN;break;case';':CurrentToken = SEMI;break;case'[':CurrentToken = LBRACKET;break;case']':CurrentToken = RBRACKET;break;case'{':CurrentToken = LBRACE;break;case'}':CurrentToken = RBRACE;break;case',':CurrentToken = COMMA;break;default:CurrentToken = ERROR;break;}}break;case INCOMMENT:save = false;if (c == EOF){state = DONE;CurrentToken = ENDFILE;}else if (c == '*')state = AFTERCOMMENT;else{state=INCOMMENT;}break;case INASSIGN:if (c == '='){CurrentToken = EQ;state=DONE;}else if(assign=="!"){UnGetNextChar();save = false;CurrentToken = ERROR;state=DONE;}else if(assign=="="){UnGetNextChar();save = false;CurrentToken =ASSIGN ;state=DONE;}else if(assign=="<"){UnGetNextChar();save = false;CurrentToken =LT ;state=DONE;}else{UnGetNextChar();save = false;CurrentToken =GT ;state=DONE;}break;case INNUM:if (!isdigit(c)){UnGetNextChar();save = false;state = DONE;CurrentToken = NUM;}break;case INID:if (!isalpha(c)){UnGetNextChar();save = false;state = DONE;CurrentToken = ID;}break;case PRECOMMENT:if(c=='*'){state=INCOMMENT;save=false;}else{UnGetNextChar();CurrentToken=OVER;state=DONE;}break;case AFTERCOMMENT:save=false;if(c=='/'){state=START;}else if(c=='*'){state=AFTERCOMMENT;}else{state=INCOMMENT;}break;case DONE:default:state = DONE;CurrentToken = ERROR;break;}if((save)&&(tokenStringIndex<=MAXTOKENLEN)){tokenString[tokenStringIndex++]=(char)c;}if(state==DONE){tokenString[tokenStringIndex]='\0';if(CurrentToken==ID){CurrentToken=ReservedLookUp(tokenString);}}}return CurrentToken;}enum NodeKind//节点类型{FuncK,IntK,IdK,ParamsK,ParamK,CompK,ConstK,CallK,ArgsK,VoidK,Var_De clK,Arry_DeclK,Arry_ElemK,AssignK/*,WhileK*/,OpK,Selection_StmtK,Iteration_StmtK,Return_StmtK};struct//节点类型和字符串关系{string str;NodeKind nk;}nodekind[18]= { {"Funck",FuncK},{"IntK",IntK},{"IdK",IdK},{"ParamsK",ParamsK},{"ParamK" ,ParamK},{"CompK",CompK},{"ConstK",ConstK},{"CallK",CallK},{"ArgsK",ArgsK},{"VoidK",VoidK},{"Var_DeclK",Var_DeclK},{"Arry_DeclK",Arry_ DeclK},{"Arry_ElemK",Arry_ElemK},{"AssignK",AssignK},/*{"WhileK",WhileK},*/{"OpK",OpK},{"Selection_StmtK",Selection_StmtK},{"Ite ration_StmtK",Iteration_StmtK},{"Return_StmtK",Return_StmtK}};struct//符号与字符串关系{string str;TokenType tk;}Ope[11]= { {"=",ASSIGN},{"==",EQ},{"<",LT},{"+",PLUS},{"-",MINUS},{"*",TIMES},{"/" ,OVER},{">",GT},{">=",GEQ},{"!=",NEQ},{"<=",LEQ}};string OpeLookUp(TokenType tk)//操作符转换为字符串{int i;for(i=0;i<11;i++){if(tk==Ope[i].tk){return Ope[i].str;}}}string Change(NodeKind nk)//节点类型转换为字符串{int i;for(i=0;i<19;i++){if(nk==nodekind[i].nk){return nodekind[i].str;break;}}}TokenType token;struct TreeNode{struct TreeNode * child[4];struct TreeNode * sibling;int lineno;NodeKind nodekind;union { TokenType op; int val; const char * name;} attr;};TreeNode * declaration_list(void);TreeNode * declaration(void);TreeNode * params(void);TreeNode * param_list(TreeNode * p);TreeNode * param(TreeNode * p);TreeNode * compound_stmt(void);TreeNode * local_declaration(void);TreeNode * statement_list(void);TreeNode * statement(void);TreeNode * expression_stmt(void);TreeNode * selection_stmt(void);TreeNode * iteration_stmt(void);TreeNode * return_stmt(void);TreeNode * expression(void);TreeNode * var(void);TreeNode * simple_expression(TreeNode * p); TreeNode * additive_expression(TreeNode * p); TreeNode * term(TreeNode * p);TreeNode * factor(TreeNode * p);TreeNode * call(TreeNode * p);TreeNode * args(void);char * copyString(char *s){int n;char * t;if (s==NULL){return NULL;}n=strlen(s)+1;t=(char*)malloc(n);if (t==NULL){}else{strcpy(t,s);}return t;}void match(TokenType expected){if(token==expected)token=GetToken();else{cout<<"unexpected token"<<endl;}}TreeNode * newNode(NodeKind kind){TreeNode * t = (TreeNode *) malloc(sizeof(TreeNode));int i;if (t==NULL){;}else {for (i=0;i<4;i++){t->child[i] = NULL;}t->sibling = NULL;t->nodekind = kind;t->lineno = lineno;if (kind==OpK||kind==IntK||kind==IdK){if(kind==IdK)t-> = "";}if(kind==ConstK)t->attr.val = 0;}return t;}TreeNode * declaration_list(void)//declaration_list->declaration_list decla ration | declaration{TreeNode * t = declaration();TreeNode * p =t;while((token!=INT)&&(token!=VOID)&&(token!=ENDFILE)){token = GetToken();if(token==ENDFILE)break;}while(token==INT||token==VOID){TreeNode * q;q = declaration();if (q!=NULL){if (t==NULL){t=p=q;}else{p->sibling=q;p=q;}}}match(ENDFILE);return t;}TreeNode * declaration(void){TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;TreeNode * s = NULL;TreeNode * a = NULL;if (token==INT){p=newNode(IntK);match(INT);}else//(token==VOID){p=newNode(VoidK);match(VOID);}if(p!=NULL&&token==ID){q = newNode(IdK);q-> = copyString(tokenString);match(ID);if (token==LPAREN){t = newNode(FuncK);t->child[0] = p; //p是t子节点t->child[1] = q;match(LPAREN);t->child[2] = params();match(RPAREN);t->child[3] = compound_stmt();}else if (token==LBRACKET){t = newNode(Var_DeclK);a = newNode(Arry_DeclK);t->child[0] = p; //p是t子节点t->child[1] = a;match(LBRACKET);s = newNode(ConstK);s->attr.val = atoi(tokenString);match(NUM);a->child[0]=q;a->child[1]=s;match(RBRACKET);match(SEMI);}else if (token==SEMI){t = newNode(Var_DeclK);t->child[0] = p;t->child[1] = q;match(SEMI);}else{;}}else{;}return t;}TreeNode * params(void)//params_list | void{TreeNode * t = newNode(ParamsK);TreeNode * p = NULL;if (token==VOID){p = newNode(VoidK);match(VOID);if (token==RPAREN){if(t!=NULL)t->child[0] = p;}else//参数列表为(void id,[……]){t->child[0] = param_list(p);}}else//(token==INT){t->child[0] = param_list(p);}return t;}TreeNode * param_list(TreeNode * k)//params_list->params_list,param | param {TreeNode * t = param(k);TreeNode * p = t;k = NULL;//没有要传给param的VoidK,所以将k设为NULLwhile (token==COMMA){TreeNode * q = NULL;match(COMMA);q = param(k);if (q!=NULL){if (t==NULL){t=p=q;}else{p->sibling = q;p = q;}}}return t;}TreeNode * param(TreeNode * k){TreeNode * t = newNode(ParamK);TreeNode * p = NULL;TreeNode * q = NULL;if(k==NULL&&token==VOID){p = newNode(VoidK);match(VOID);}else if(k==NULL&&token==INT){p = newNode(IntK);match(INT);}else if (k!=NULL){p = k;}if(p!=NULL){t->child[0] = p;if (token==ID){q = newNode(IdK);q-> = copyString(tokenString);t->child[1] = q;match(ID);}if (token==LBRACKET&&(t->child[1]!=NULL))//@@@@@@@@@@@@{match(LBRACKET);t->child[2] = newNode(IdK);match(RBRACKET);}else{return t;}}else{;}return t;}TreeNode * compound_stmt(void){TreeNode * t = newNode(CompK);match(LBRACE);t->child[0] = local_declaration();t->child[1] = statement_list();match(RBRACE);return t;}TreeNode * local_declaration(void){TreeNode * t = NULL;TreeNode * q = NULL;TreeNode * p = NULL;while(token==INT || token==VOID){p = newNode(Var_DeclK);if(token==INT){TreeNode * q1 = newNode(IntK);p->child[0] = q1;match(INT);}else if(token==VOID){TreeNode * q1 = newNode(VoidK);p->child[0] = q1;match(INT);}if((p!=NULL)&&(token==ID)){TreeNode * q2 = newNode(IdK);q2-> = copyString(tokenString);p->child[1] = q2;match(ID);if(token==LBRACKET){TreeNode * q3 = newNode(Var_DeclK);p->child[3] = q3;match(LBRACKET);match(RBRACKET);match(SEMI);}else if(token==SEMI){match(SEMI);}else{match(SEMI);}}if(p!=NULL){if(t==NULL)t = q = p;else{q->sibling = p;q = p;}}}return t;}TreeNode * statement_list(void){TreeNode * t = statement();TreeNode * p = t;while (IF==token || LBRACKET==token || ID==token || WHILE==token || RETURN ==token || SEMI==token || LPAREN==token || NUM==token){TreeNode * q;q = statement();if(q!=NULL){if(t==NULL){t = p = q;}else{p->sibling = q;p = q;}}}return t;}TreeNode * statement(void){TreeNode * t = NULL;switch(token){case IF:t = selection_stmt();break;case WHILE:t = iteration_stmt();break;case RETURN:t = return_stmt();break;case LBRACE:t = compound_stmt();break;case ID: case SEMI: case LPAREN: case NUM:t = expression_stmt();break;default:token = GetToken();break;}return t;}TreeNode * selection_stmt(void){TreeNode * t = newNode(Selection_StmtK);match(IF);match(LPAREN);if(t!=NULL){t->child[0] = expression();}match(RPAREN);t->child[1] = statement();if(token==ELSE){match(ELSE);if(t!=NULL){t->child[2] = statement();}}return t;}TreeNode * iteration_stmt(void){TreeNode * t = newNode(Iteration_StmtK);match(WHILE);match(LPAREN);if(t!=NULL){t->child[0] = expression();}match(RPAREN);if(t!=NULL){t->child[1] = statement();}return t;}TreeNode * return_stmt(void){TreeNode * t = newNode(Return_StmtK);match(RETURN);if (token==SEMI){match(SEMI);return t;}else{if(t!=NULL){t->child[0] = expression();}}match(SEMI);return t;}TreeNode * expression_stmt(void){TreeNode * t = NULL;if(token==SEMI){match(SEMI);return t;}else{t = expression();match(SEMI);}return t;}TreeNode * expression(void){TreeNode * t = var();if(t==NULL)//不是以ID开头,只能是simple_expression情况{t = simple_expression(t);}else//以ID开头,可能是赋值语句,或simple_expression中的var和call类型的情况{TreeNode * p = NULL;if(token==ASSIGN)//赋值语句{p = newNode(AssignK);match(ASSIGN);p->child[0] = t;p->child[1] = expression();return p;}else//simple_expression中的var和call类型的情况{t = simple_expression(t);}}return t;}TreeNode * var(void){TreeNode * t = NULL;TreeNode * p = NULL;TreeNode * q = NULL;if(token==ID){p = newNode(IdK);p-> = copyString(tokenString);match(ID);if(token==LBRACKET){match(LBRACKET);q = expression();match(RBRACKET);t = newNode(Arry_ElemK);t->child[0] = p;t->child[1] = q;}else{t = p;}}return t;}TreeNode * simple_expression(TreeNode * k){TreeNode * t = additive_expression(k);k = NULL;if(EQ==token || GT==token || GEQ==token || LT==token || LEQ==token || NEQ==token){TreeNode * q = newNode(OpK);q->attr.op = token;q->child[0] = t;t = q;match(token);t->child[1] = additive_expression(k);return t;}return t;}TreeNode * additive_expression(TreeNode * k){TreeNode * t = term(k);k = NULL;while((token==PLUS)||(token==MINUS)){TreeNode * q = newNode(OpK);q->attr.op = token;q->child[0] = t;match(token);q->child[1] = term(k);t = q;}return t;}TreeNode * term(TreeNode * k){TreeNode * t = factor(k);k = NULL;while((token==TIMES)||(token==OVER)){TreeNode * q = newNode(OpK);q->attr.op = token;q->child[0] = t;t = q;match(token);q->child[1] = factor(k);}return t;}TreeNode * factor(TreeNode * k){TreeNode * t = NULL;if(k!=NULL)//k为上面传下来的已经解析出来的以ID开头的var,可能为call或var{if(token==LPAREN && k->nodekind!=Arry_ElemK) //call{t = call(k);}else{t = k;}}else//没有从上面传下来的var{switch(token){case LPAREN:match(LPAREN);t = expression();match(RPAREN);break;case ID:k = var();if(LPAREN==token && k->nodekind!=Arry_ElemK){t = call(k);}else//如果是连续计算,进入这一步{t=k;}break;case NUM:t = newNode(ConstK);if((t!=NULL)&&(token==NUM)){t->attr.val = atoi(tokenString);}match(NUM);break;default:token = GetToken();break;}}return t;}TreeNode * call(TreeNode * k){TreeNode * t = newNode(CallK);if(k!=NULL)t->child[0] = k;match(LPAREN);if(token==RPAREN){match(RPAREN);return t;}else if(k!=NULL){t->child[1] = args();match(RPAREN);}return t;}TreeNode * args(void){TreeNode * t = newNode(ArgsK);TreeNode * s = NULL;TreeNode * p = NULL;if(token!=RPAREN){s = expression();p = s;while(token==COMMA){TreeNode * q;match(COMMA);q = expression();if(q!=NULL){if(s==NULL){s = p = q;}else{p->sibling = q;p = q;}}}}if(s!=NULL){t->child[0] = s;}return t;}int blank_number=0;void PreOrder(TreeNode* t){string blank=" ";int i;for(i=0;i<blank_number;i++){blank+=" ";}if(t!=NULL){if(t->nodekind==OpK){cout<<blank<<"Op: "<<OpeLookUp(t->attr.op)<<endl;output+=blank+"Op: "+OpeLookUp(t->attr.op)+"\n";}else if(t->nodekind==IdK){cout<<blank<<Change(t->nodekind)<<": "<<t-><<endl;output+=blank+Change(t->nodekind)+": "+t->+"\n";}else if(t->nodekind==ConstK){cout<<blank<<Change(t->nodekind)<<": "<<t->attr.val<<endl;int n=t->attr.val;strstream ss;string s;ss << n;ss >> s;output+=blank+Change(t->nodekind)+": "+s+"\n";}else if(t->nodekind==AssignK){cout<<blank<<"Assign"<<endl;output+=blank+"Assign"+"\n";}else if(t->nodekind==Selection_StmtK){cout<<blank<<"If"<<endl;output+=blank+"If"+"\n";}else if(t->nodekind==Iteration_StmtK){cout<<blank<<"While"<<endl;output+=blank+"While"+"\n";}else if(t->nodekind==Return_StmtK){cout<<blank<<"Return"<<endl;output+=blank+"Return"+"\n";}else{cout<<blank<<Change(t->nodekind)<<endl;output+=blank+Change(t->nodekind)+"\n";}}for(i=0;i<MAXCHILDREN;i++){if(t->child[i]!=NULL){blank_number+=2;PreOrder(t->child[i]);blank_number-=2;}}if(t->sibling!=NULL){PreOrder(t->sibling);}}void parse(void){TreeNode * t;cout<<"Syntax tree:"<<endl;token = GetToken();t = declaration_list();PreOrder(t);}void main(){char* file=(char *)malloc(100);//打开的文件名string result;//输出结果文件名cout<<"请输入文件名.例如:gcd.c-"<<endl;scanf("%s",file);while((source=fopen(file,"r"))==NULL){cout<<"文件名无效,请重新输入"<<endl;scanf("%s",file);}ofstream write;//输出文件result=string(file)+"-Result.txt";write.open(result);write<<"Syntax tree:"<<endl;parse();write<<output;write.close();system("PAUSE");}。