编译原理课程设计词法分析

合集下载

编译原理课程设计-词法分析器

编译原理课程设计-词法分析器

计算机与信息学院编译原理课程设计实验报告专业班级计算机科学与技术专业08-4班学生姓名及学号胡义涛20082645课程教学班号0001任课教师王仲宾实验指导教师王仲宾实验地点逸夫楼5072010~2011 第三学年第一学期一、实验目的和要求:设计并实现一个C语言(或C++语言)的词法分析程序,加深对词法分析原理的理解。

二、试验设计和算法分析:实验原理:程序流程:置初值→调用扫描子程序→输出串结束→输出单词二元组→是→否→结束词法分析主程序示意图待分析的简单语言的词法(1) 关键字:begin if then while do end所有关键字都是小写。

(2)运算符和界符::= + - * / < > <= <> >= ; ( ) #(3)空格由空白、制表符和换行符组成。

词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

三、源代码:#include "stdio.h"#include "string.h"#include "conio.h"#include "ctype.h"char prog[80]={'\0'},token[8]; /*存放构成单词符号的字符串*/char ch;int syn, /*存放单词字符的种别码*/n,sum, /*存放整数型单词*/m,p; /*p是缓冲区prog的指针,m是token的指针*/char*rwtab[6]={"begin","if","then","while","do","end" };void scaner(){m=0;sum=0;for(n=0;n<8;n++){token[n]='\0';}ch=prog[p++];while(ch==' '){ch=prog[p++];}if(isalpha(ch)) //ch为字母字符{while(isalpha(ch)||isdigit(ch))//ch 为字母字符或者数字字符{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(isdigit(ch)) //ch是数字字符{while(isdigit(ch)) //ch是数字字符{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;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=20;ch=prog[p--];}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='=')syn=24;token[m++]=ch;}else{syn=23;ch=prog[p--];}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;ch=prog[p--];break;case'10':syn=12;token[0]='n';break;case'11':syn=12;token[0]='n';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=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;}}main(){printf("\n\n对应信息:\n""1.1-6为关键字\n""2.10-11为字符或常量\n""3.12-28为表示符\n");p=0;printf("\nplease input string:\n");do {ch=getchar();prog[p++]=ch;}while(ch!='#');p=0;do{scaner();switch(syn){case 11: printf("(%d,%d)\n",syn,sum);break;case -1: printf("\n ERROR;\n");break;default: printf("(%d,%s)\n",syn,token); }}while(syn!=0);getch();}四、实验结果及总结:输出:总结:通过该实验,主要有以下几方面收获:一、对实验原理有更深的理解。

编译原理课程设计(词法分析,语法分析,语义分析,代码生成)

编译原理课程设计(词法分析,语法分析,语义分析,代码生成)

#include<cstdio>#include<iostream>#include<cstdlib>#include<fstream>#include<string>#include<cmath>using namespace std;/*********************下面是一些重要数据结构的声明***************************/struct token//词法token结构体{int code;//编码int num;//递增编号token *next;};token *token_head,*token_tail;//token队列struct str//词法string结构体{int num;//编号string word;//字符串内容str *next;};str *string_head,*string_tail;//string队列struct ivan//语法产生式结构体{char left;//产生式的左部string right;//产生式的右部int len;//产生式右部的长度};ivan css[20];//语法20个产生式struct pank//语法action表结构体{char sr;//移进或归约int state;//转到的状态编号};pank action[46][18];//action表int go_to[46][11];//语法go_to表struct ike//语法分析栈结构体,双链{ike *pre;int num;//状态int word;//符号编码ike *next;};ike *stack_head,*stack_tail;//分析栈首尾指针struct L//语义四元式的数据结构{int k;string op;//操作符string op1;//操作数string op2;//操作数string result;//结果L *next;//语义四元式向后指针L *Ltrue;//回填true链向前指针L *Lfalse;//回填false链向前指针};L *L_four_head,*L_four_tail,*L_true_head,*L_false_head;//四元式链,true链,false链struct symb//语义输入时符号表{string word;//变量名称int addr;//变量地址symb *next;};symb *symb_head,*symb_tail;//语义符号链表/*********************下面是与词法分析相关的一些函数的声明***************************/void scan();//按字符读取源文件void cifa_main();//词法分析主程序int judge(char ch);//判断输入字符的类型void out1(char ch);//写入token.txtvoid out3(char ch,string word);//写入string.txtvoid input1(token *temp);//插入结点到队列tokenvoid input3(str *temp);//插入结点到队列stringvoid output();//输出三个队列的内容void outfile();//输出三个队列的内容到相应文件中/*********************下面是与语法分析相关的一些函数的声明***************************/void yufa_main();//语法分析主程序void yufa_initialize();//初始化语法分析数据结构int yufa_SLR1(int a);//语法分析主体部分int ID1(int a);//给输入字符编号,转化成action表列编号string ID10(int i);//给输入字符反编号int ID2(char ch);//给非终结状态编号,转化成go_to表列编号int ID20(char ch);//给非终结状态编号char ID21(int j);//给非终结状态反编号void add(ike *temp);//给ike分析栈链表增加一个结点void del();//给ike分析栈链表删除一个结点/*********************下面是与语义分析相关的一些函数的声明***************************/void yuyi_main(int m);//语义分析主程序void add_L_four(L *temp);//向四元式链中加一个结点void add_L_true(L *temp);//向true链中加一个结点void add_L_false(L *temp);//向false链中加一个结点void add_symb(symb *temp);//向语义符号表链中加一个结点void output_yuyi();//输出中间代码四元式和最后符号表string newop(int m);//把数字变成字符串string id_numtoname(int num);//把编号转换成相应的变量名int lookup(string m);//变量声明检查/*********************下面是一些全局变量的声明***************************/FILE *fp;//文件指针int wordcount;//标志符计数int err;//标志词法分析结果正确或错误int nl;//读取行数int yuyi_linshi;//语义临时变量string E_name,T_name,F_name,M_name,id_name,id1_name,id2_name,errword;//用于归约时名称传递和未声明变量的输出int id_num,id1_num,id2_num,id_left,id_while,id_then,id_do;//用于记录一些特殊的字符位置信息/****************************主程序开始**************************/int main(){cout<<"************************"<<endl;cout<<"* 说明:*"<<endl;cout<<"* 第一部分:词法分析*"<<endl;cout<<"* 第二部分:语法分析*"<<endl;cout<<"* 第三部分:语义分析*"<<endl;cout<<"************************"<<endl;cifa_main();//词法yufa_main();//语法output_yuyi();//语义cout<<endl;system("pause");return(0);}/****************************以上是主程序,以下是词法**************************/void cifa_main(){token_head=new token;token_head->next=NULL;token_tail=new token;token_tail->next=NULL;string_head=new str;string_head->next=NULL;string_tail=new str;string_tail->next=NULL;//初始化三个队列的首尾指针L_four_head=new L;L_four_head->next=NULL;L_four_tail=new L;L_four_tail->k=0;L_four_tail->next=NULL;L_true_head=new L;L_true_head->Ltrue=NULL;L_false_head=new L;L_false_head->Lfalse=NULL;symb_head=new symb;symb_head->next=NULL;symb_tail=new symb;symb_tail->next=NULL;yuyi_linshi=-1;id_num=0;wordcount=0;//初始化字符计数器err=0;//初始化词法分析错误标志nl=1;//初始化读取行数scan();if(err==0){char m;output();cout<<"词法分析正确完成!"<<endl<<endl<<"如果将结果保存到文件中请输入y ,否则请输入其它字母:";cin>>m;cout<<endl;if(m=='y'){outfile();cout<<"结果成功保存在token.txt和sting.txt两个文件中,请打开查看"<<endl;cout<<endl;}}void scan(){cout<<endl;system("pause");cout<<endl;char ch;string word;char document[50];int flag=0;cout<<"请输入源文件路径及名称:";cin>>document;cout<<endl;cout<<"************************"<<endl;cout<<"* 第一部分:词法分析*"<<endl;cout<<"************************"<<endl;if((fp=fopen(document,"rt"))==NULL){err=1;cout<<"无法找到该文件!"<<endl;return;}while(!feof(fp)){word="";ch=fgetc(fp);flag=judge(ch);if(flag==1)out1(ch);else if(flag==3)out3(ch,word);else if(flag==4 || flag==5 ||flag==6)continue;else{cout<<nl<<"行"<<"错误:非法字符! "<<ch<<endl;err=1;}}fclose(fp);}int judge(char ch)int flag=0;if(ch=='=' || ch=='+' || ch=='*' || ch=='>' || ch==':' || ch==';' || ch=='{' || ch=='}' || ch=='(' || ch==')') flag=1;//界符else if(('a'<=ch && ch<='z') || ('A'<=ch && ch<='Z'))flag=3;//字母else if(ch==' ')flag=4;//空格else if(feof(fp))flag=5;//结束else if(ch=='\n'){flag=6;//换行nl++;}elseflag=0;//非法字符return(flag);}void out1(char ch){int id;switch(ch){case '=' : id=1;break;case '+' : id=2;break;case '*' : id=3;break;case '>' : id=4;break;case ':' : id=5;break;case ';' : id=6;break;case '{' : id=7;break;case '}' : id=8;break;case '(' : id=9;break;case ')' : id=10;break;//界符编码default : id=0;}token *temp;temp=new token;temp->code=id;temp->num=-1;temp->next=NULL;input1(temp);return;}void out3(char ch,string word){token *temp;temp=new token;temp->code=-1;temp->num=-1;temp->next=NULL;str *temp1;temp1=new str;temp1->num=-1;temp1->word="";temp1->next=NULL;int flag=0;word=word+ch;ch=fgetc(fp);flag=judge(ch);if(flag==1 || flag==4 || flag==5 || flag==6){if(word=="and" || word=="if" || word=="then" || word=="while" || word=="do" || word=="int") {if(word=="and")temp->code=31;else if(word=="if")temp->code=32;else if(word=="then")temp->code=33;else if(word=="while")temp->code=35;else if(word=="do")temp->code=36;else if(word=="int")temp->code=37;//关键字编码input1(temp);if(flag==1)out1(ch);else if(flag==4 || flag==5 || flag==6)return;}else if(flag==1){wordcount++;temp->code=25;temp->num=wordcount;input1(temp);temp1->num=wordcount;temp1->word=word;input3(temp1);out1(ch);}else if(flag==4 || flag==5 || flag==6){wordcount++;temp->code=25;temp->num=wordcount;input1(temp);temp1->num=wordcount;temp1->word=word;input3(temp1);}return;}else if(flag==2 || flag==3)out3(ch,word);//形成字符串else{err=1;cout<<nl<<"行"<<"错误:非法字符! "<<ch<<endl; return;}}void input1(token *temp){if(token_head->next == NULL){token_head->next=temp;token_tail->next=temp;}else{token_tail->next->next=temp;token_tail->next=temp;}}void input3(str *temp){if(string_head->next == NULL){string_head->next=temp;string_tail->next=temp;}else{string_tail->next->next=temp;string_tail->next=temp;}}void output(){cout<<"token表内容如下:"<<endl;token *temp1;temp1=new token;temp1=token_head->next;while(temp1!=NULL){cout<<temp1->code;if(temp1->num == -1){cout<<endl;}else{cout<<" "<<temp1->num<<endl;}temp1=temp1->next;}cout<<"符号表内容如下:"<<endl;str *temp3;temp3=new str;temp3=string_head->next;while(temp3!=NULL){cout<<temp3->num<<" "<<temp3->word<<endl; temp3=temp3->next;}}void outfile(){ofstream fout1("token.txt");//写文件ofstream fout3("string.txt");token *temp1;temp1=new token;temp1=token_head->next;while(temp1!=NULL){fout1<<temp1->code;if(temp1->num == -1)fout1<<endl;elsefout1<<" "<<temp1->num<<endl;temp1=temp1->next;}str *temp3;temp3=new str;temp3=string_head->next;while(temp3!=NULL){fout3<<temp3->num<<" "<<temp3->word<<endl;temp3=temp3->next;}}/****************************以上是词法,以下是语法**************************/void yufa_main(){if(err==0){system("pause");cout<<endl;cout<<"************************"<<endl;cout<<"* 第二部分:语法分析*"<<endl;cout<<"************************"<<endl;yufa_initialize();//初始化语法分析数据结构token *temp;temp=new token;temp=token_head->next;int p,q;p=0;q=0;cout<<"语法分析过程如下:"<<endl;while(temp!=NULL){int w;w=ID1(temp->code);p=yufa_SLR1(w);if(p==1) break;if(p==0)temp=temp->next;if(temp==NULL) q=1;}//语法分析if(q==1)while(1){p=yufa_SLR1(17);if(p==3) break;}//最后输入$来完成语法分析}}void yufa_initialize(){stack_head=new ike;stack_tail=new ike;stack_head->pre=NULL;stack_head->next=stack_tail;stack_head->num=0;stack_head->word='!';stack_tail->pre=stack_head;stack_tail->next=NULL;//初始化栈分析链表css[0].left='Q';css[0].right="P";css[1].left='P';css[1].right="id()L;R";css[2].left='L';css[2].right="L;D";css[3].left='L';css[3].right="D";css[4].left='D';css[4].right="id:int";css[5].left='E';css[5].right="E+T";css[6].left='E';css[6].right="T";css[7].left='T';css[7].right="T*F";css[8].left='T';css[8].right="F";css[9].left='F';css[9].right="(E)";css[10].left='F';css[10].right="id";css[11].left='B';css[11].right="B and B";css[12].left='B';css[12].right="id>id";css[13].left='M';css[13].right="id=E";css[14].left='S';css[14].right="if B then M";css[15].left='S';css[15].right="while B do M";css[16].left='S';css[16].right="M";css[17].left='N';css[17].right="N;S";css[18].left='N';css[18].right="S";css[19].left='R';css[19].right="{N}";int i,j;for(i=0;i<20;i++){char *css_len;css_len=&css[i].right[0];css[i].len=strlen(css_len);}css[1].len=6;css[4].len=3;css[10].len=1;css[11].len=3;css[12].len=3;css[13].len=3;css[14].len=4;css[15].len=4;//初始化产生式for(i=0;i<46;i++){for(j=0;j<18;j++)action[i][j].sr='#';}//初始化action表for(i=0;i<46;i++){for(j=0;j<11;j++)go_to[i][j]=-1;}//初始化go_to表/****************************以下是给action表和go_to表赋初值************************/action[0][0].sr='s';action[0][0].state=2; action[1][17].sr='@';//结束action[2][1].sr='s';action[2][1].state=3; action[3][2].sr='s';action[3][2].state=4; action[4][0].sr='s';action[4][0].state=5; action[5][4].sr='s';action[5][4].state=6; action[6][11].sr='s';action[6][11].state=7; action[7][3].sr='r';action[7][3].state=4; action[8][3].sr='r';action[8][3].state=3; action[9][3].sr='s';action[9][3].state=10; action[10][0].sr='s';action[10][0].state=5; action[10][9].sr='s';action[10][9].state=13; action[11][17].sr='r';action[11][17].state=1; action[12][3].sr='r';action[12][3].state=2; action[13][0].sr='s';action[13][0].state=14; action[13][13].sr='s';action[13][13].state=23; action[13][15].sr='s';action[13][15].state=27; action[14][8].sr='s';action[14][8].state=15; action[15][0].sr='s';action[15][0].state=36; action[15][1].sr='s';action[15][1].state=41; action[16][6].sr='s';action[16][6].state=43; action[16][3].sr='r';action[16][3].state=13; action[16][10].sr='r';action[16][10].state=13; action[17][3].sr='s';action[17][3].state=19; action[17][10].sr='s';action[17][10].state=18; action[18][17].sr='r';action[18][17].state=19; action[19][0].sr='s';action[19][0].state=14; action[19][13].sr='s';action[19][13].state=23; action[19][15].sr='s';action[19][15].state=27; action[20][3].sr='r';action[20][3].state=17; action[20][10].sr='r';action[20][10].state=17; action[21][3].sr='r';action[21][3].state=18; action[21][10].sr='r';action[21][10].state=18; action[22][3].sr='r';action[22][3].state=16; action[22][10].sr='r';action[22][10].state=16; action[23][0].sr='s';action[23][0].state=31; action[24][12].sr='s';action[24][12].state=34; action[24][14].sr='s';action[24][14].state=25; action[25][0].sr='s';action[25][0].state=14; action[26][3].sr='r';action[26][3].state=14; action[26][10].sr='r';action[26][10].state=14; action[27][0].sr='s';action[27][0].state=31; action[28][12].sr='s';action[28][12].state=34; action[28][16].sr='s';action[28][16].state=29;action[30][3].sr='r';action[30][3].state=15; action[30][10].sr='r';action[30][10].state=15; action[31][7].sr='s';action[31][7].state=32; action[32][0].sr='s';action[32][0].state=33; action[33][12].sr='r';action[33][12].state=12; action[33][14].sr='r';action[33][14].state=12; action[33][16].sr='r';action[33][16].state=12; action[34][0].sr='s';action[34][0].state=31; action[35][12].sr='r';action[35][12].state=11; action[35][14].sr='r';action[35][14].state=11; action[35][16].sr='r';action[35][16].state=11; action[36][2].sr='r';action[36][2].state=10; action[36][3].sr='r';action[36][3].state=10; action[36][5].sr='r';action[36][5].state=10; action[36][6].sr='r';action[36][6].state=10; action[36][10].sr='r';action[36][10].state=10; action[37][2].sr='r';action[37][2].state=8; action[37][3].sr='r';action[37][3].state=8; action[37][5].sr='r';action[37][5].state=8; action[37][6].sr='r';action[37][6].state=8; action[37][10].sr='r';action[37][10].state=8; action[38][2].sr='r';action[38][2].state=6; action[38][3].sr='r';action[38][3].state=6; action[38][5].sr='s';action[38][5].state=39; action[38][6].sr='r';action[38][6].state=6; action[38][10].sr='r';action[38][10].state=6; action[39][0].sr='s';action[39][0].state=36; action[39][1].sr='s';action[39][1].state=41; action[40][2].sr='r';action[40][2].state=7; action[40][3].sr='r';action[40][3].state=7; action[40][5].sr='r';action[40][5].state=7; action[40][6].sr='r';action[40][6].state=7; action[40][10].sr='r';action[40][10].state=7; action[41][0].sr='s';action[41][0].state=36; action[41][1].sr='s';action[41][1].state=41; action[42][2].sr='s';action[42][2].state=45; action[42][6].sr='s';action[42][6].state=43; action[43][0].sr='s';action[43][0].state=36; action[43][1].sr='s';action[43][1].state=41; action[44][2].sr='r';action[44][2].state=5; action[44][3].sr='r';action[44][3].state=5; action[44][5].sr='s';action[44][5].state=39; action[44][6].sr='r';action[44][6].state=5;action[45][2].sr='r';action[45][2].state=9;action[45][3].sr='r';action[45][3].state=9;action[45][5].sr='r';action[45][5].state=9;action[45][6].sr='r';action[45][6].state=9;action[45][10].sr='r';action[45][10].state=9;go_to[0][0]=1;go_to[4][1]=8;go_to[4][9]=9;go_to[10][1]=12;go_to[10][2]=11;go_to[13][7]=22;go_to[13][8]=2 1;go_to[13][10]=17;go_to[15][3]=16;go_to[15][4]=38;go_to[15][5]=37;go_to[19][7]=20;go_to[19][8]=20;go_to[23][6]=24;go_to[2 5][7]=26;go_to[27][6]=28;go_to[29][7]=30;go_to[34][6]=35;go_to[39][5]=40;go_to[41][3]=42;go_to[41][4]=38;go_to[41][5]=37;go_to[4 3][4]=44;go_to[43][5]=37;/****************************action表和go_to表赋初值完毕************************/}int ID1(int i)//按action表,给输入字符编号{int j;j=-1;if(i==25) {j=0;id_num++;}//设置变量名称标志if(i==1) {j=8,id_left=id_num;}//设置产生试左边变量名称标志if(i==2) j=6;if(i==3) j=5;if(i==4) j=7;if(i==5) j=4;if(i==6) j=3;if(i==7) j=9;if(i==8) j=10;if(i==9) j=1;if(i==10) j=2;if(i==31) j=12;if(i==32) j=13;if(i==33) {j=14;id_then=L_four_tail->k+1;}//设置if语句中then位置标志if(i==35) {j=15;id_while=L_four_tail->k+1;}//设置while语句中while位置标志if(i==36) {j=16;id_do=L_four_tail->k+1;}//设置while语句中do位置标志if(i==37) j=11;return(j);}string ID10(int i)//反编号输入字符{string ch;if(i==0) ch="id";if(i==1) ch="(";if(i==2) ch=")";if(i==3) ch=";";if(i==4) ch=":";if(i==5) ch="*";if(i==6) ch="+";if(i==7) ch=">";if(i==8) ch="=";if(i==9) ch="{";if(i==10) ch="}";if(i==11) ch="int";if(i==12) ch="and";if(i==13) ch="if";if(i==14) ch="then";if(i==15) ch="while";if(i==16) ch="do";if(i==17) ch="$";return(ch);}int ID2(char ch)//按go_to表给非终结符编号{int j;j=-1;if(ch=='P') j=0;if(ch=='D') j=1;if(ch=='R') j=2;if(ch=='E') j=3;if(ch=='T') j=4;if(ch=='F') j=5;if(ch=='B') j=6;if(ch=='M') j=7;if(ch=='S') j=8;if(ch=='L') j=9;if(ch=='N') j=10;return(j);}int ID20(char ch)//给非终结符编号{int j;j=-1;if(ch=='P') j=100;if(ch=='D') j=101;if(ch=='R') j=102;if(ch=='E') j=103;if(ch=='T') j=104;if(ch=='F') j=105;if(ch=='B') j=106;if(ch=='M') j=107;if(ch=='S') j=108;if(ch=='L') j=109;if(ch=='N') j=1010;return(j);}char ID21(int j)//反编号非终结符{char ch;if(j==100 || j==0) ch='P';if(j==101 || j==1) ch='D';if(j==102 || j==2) ch='R';if(j==103 || j==3) ch='E';if(j==104 || j==4) ch='T';if(j==105 || j==5) ch='F';if(j==106 || j==6) ch='B';if(j==107 || j==7) ch='M';if(j==108 || j==8) ch='S';if(j==109 || j==9) ch='L';if(j==1010 || j==10) ch='N'; return(ch);}void add(ike *temp)//加一个结点{if(stack_head->next==stack_tail) {temp->pre=stack_head;temp->next=stack_tail;stack_head->next=temp;stack_tail->pre=temp;}else{temp->pre=stack_tail->pre; temp->next=stack_tail;stack_tail->pre->next=temp; stack_tail->pre=temp;}}void del()//删除一个结点{stack_tail->pre->pre->next=stack_tail;stack_tail->pre=stack_tail->pre->pre;}int yufa_SLR1(int w){/*cout<<"当前输入符号:"<<ID10(w)<<" ";*/int i,flag=0,state_temp;//flag错误标志,0正常移进,1错误,2归约,3结束char sr_temp;sr_temp=action[stack_tail->pre->num][w].sr;//动作state_temp=action[stack_tail->pre->num][w].state;//状态变化if(sr_temp=='#')//错误动作{flag=1;err=3;cout<<"语法分析出错!"<<endl;}else if(sr_temp=='s')//移进动作{ike *temp;temp=new ike;temp->next=NULL;temp->pre=NULL;temp->word=w;temp->num=state_temp;add(temp);cout/*<<"动作(移进):"*/<<sr_temp<<state_temp<<" "/*<<"状态转为:"<<stack_tail->pre->num<<" "<<"栈顶符号:"<<ID10(stack_tail->pre->word)*/<<endl;flag=0;}else if(sr_temp=='r')//归约动作{int p=ID2(css[state_temp].left);int q=css[state_temp].len;for(i=0;i<q;i++)del();ike *temp;temp=new ike;temp->next=NULL;temp->pre=NULL;temp->word=ID20(css[state_temp].left);temp->num=go_to[stack_tail->pre->num][p];//查go_to表add(temp);cout/*<<"动作(归约):"*/<<sr_temp<<state_temp<<" "<<css[state_temp].left<<"→"<<css[state_temp].right<<" "/*<<"状态转为:"<<stack_tail->pre->num<<" "<<"栈顶符号:"<<ID21(stack_tail->pre->word)*/<<endl;flag=2;yuyi_main(state_temp);//在产生树的同时进行语义分析}else if(sr_temp=='@')//结束动作{cout<<"END"/*<<"动作(归约):"<<sr_temp<<state_temp*/<<" "<<css[state_temp].left<<"→"<<css[state_temp].right<<" "/*<<"状态转为:"<<stack_tail->pre->num<<" "<<"栈顶符号:"<<ID21(stack_tail->pre->word)*/<<endl;flag=3;cout<<"语法分析正确完成!"<<endl;}else//其他意外情况{flag=1;err=3;cout<<"语法分析出错!"<<endl;}return(flag);}/****************************以上是语法,以下是语义**************************/void yuyi_main(int m){L *temp;int k;k=1;temp=new L;temp->op=" ";temp->op1=" ";temp->op2=" ";temp->result="";temp->next=NULL;temp->Ltrue=NULL;temp->Lfalse=NULL;if(m==4)//变量声明时加入符号表链{symb *Stemp;Stemp=new symb;id_name=id_numtoname(id_num);Stemp->word=id_name;Stemp->next=NULL;add_symb(Stemp);}if(m==5)//归约E→E+T{temp->op="+";temp->op1=E_name;temp->op2=T_name;yuyi_linshi++;//申请临时变量E_name="t"+newop(yuyi_linshi); temp->result=E_name;add_L_four(temp);//加一个四元式结点}if(m==6)//归约E→T{E_name=T_name;}if(m==7)//归约T→T*F{temp->op="*";temp->op1=T_name;temp->op2=F_name;yuyi_linshi++;//申请临时变量T_name="t"+newop(yuyi_linshi); temp->result=T_name;add_L_four(temp);//加一个四元式结点}if(m==8)//归约T→F{T_name=F_name;}if(m==9)//归约F→(E){F_name=E_name;}if(m==10)//归约F→id{id_name=id_numtoname(id_num);F_name=id_name;k=lookup(id_name);//检查变量是否声明if(k==0){err=2;errword=id_name;return;}}if(m==12)//归约B→id>id{temp->op="J>";id1_num=id_num-1;id1_name=id_numtoname(id1_num);k=lookup(id1_name);//检查变量是否声明if(k==0){err=2;errword=id1_name;return;}id2_num=id_num;id2_name=id_numtoname(id2_num);k=lookup(id2_name);//检查变量是否声明if(k==0){err=2;errword=id2_name;return;}temp->result="-1";temp->op1=id1_name;temp->op2=id2_name;add_L_four(temp);//加一个四元式结点add_L_true(temp);//加一个true链结点L *temp2;temp2=new L;temp2->op="J";temp2->op1=" ";temp2->op2=" ";temp2->result="-1";add_L_four(temp2);//加一个四元式结点add_L_false(temp2);//加一个false链结点}if(m==13)//归约M→id=E{temp->op="=";temp->op1=E_name;temp->op2=" ";id_name=id_numtoname(id_left);temp->result=id_name;add_L_four(temp);//加一个四元式结点yuyi_linshi=-1;//临时变量开始重新计数}if(m==14)//归约S→if B then M{int a;a=id_then;temp=L_true_head->Ltrue;while(temp!=NULL){temp->result="L"+newop(a);a=temp->k;temp=temp->Ltrue;}a=L_four_tail->k+1;temp=L_false_head->Lfalse;while(temp!=NULL){temp->result="L"+newop(a);temp=temp->Lfalse;}L_true_head->Ltrue=NULL;L_false_head->Lfalse=NULL;//回填并清空true链和false链}if(m==15)//归约S→while B do M{int a;a=id_do;temp=L_true_head->Ltrue;while(temp!=NULL){temp->result="L"+newop(a);a=temp->k;temp=temp->Ltrue;}a=L_four_tail->k+2;temp=L_false_head->Lfalse;while(temp!=NULL){temp->result="L"+newop(a);temp=temp->Lfalse;}L *temp1;temp1=new L;temp1->op="J";temp1->op1=" ";temp1->op2=" ";temp1->next=NULL;temp1->result="L"+newop(id_while);add_L_four(temp1);//加一个四元式结点L_true_head->Ltrue=NULL;L_false_head->Lfalse=NULL;//回填并清空true链和false链}}string newop(int m)//数字变成字符串{int shang,yushu;string chuan,chuan1;shang=m;chuan="";while(1){yushu=shang%10;chuan=chuan+char(48+yushu);shang=shang/10;if(shang==0)break;}int i;char *ch;ch=&chuan[0];chuan1="";for(i=strlen(ch)-1;i>=0;i--)chuan1=chuan1+chuan[i];return(chuan1);}void add_L_four(L *temp)//加一个四元式结点{temp->k=L_four_tail->k+1;if(L_four_head->next == NULL){L_four_head->next=temp;L_four_tail->next=temp;}else{L_four_tail->next->next=temp;L_four_tail->next=temp;}L_four_tail->k=L_four_tail->next->k;}void add_L_true(L *temp)//加一个true链结点{temp->Ltrue=L_true_head->Ltrue;L_true_head->Ltrue=temp;}void add_L_false(L *temp)//加一个false链结点{temp->Lfalse=L_false_head->Lfalse;L_false_head->Lfalse=temp;}void add_symb(symb *temp)//加一个语义符号表链结点{if(symb_head->next == NULL){temp->addr=0;symb_head->next=temp;symb_tail->next=temp;}else{temp->addr=symb_tail->next->addr+4;symb_tail->next->next=temp;symb_tail->next=temp;}}void output_yuyi(){if(err==0)//语义分析正确时的输出{cout<<endl;system("pause");cout<<endl;cout<<"************************"<<endl;cout<<"* 第三部分:语义分析*"<<endl;cout<<"************************"<<endl;cout<<"中间代码如下:"<<endl;L *temp;temp=L_four_head->next;while(temp!=NULL){。

编译原理课程设计词法分析器文档

编译原理课程设计词法分析器文档

2011—2012学年第一学期《编译原理》课程设计报告专业:计算机科学与技术学生姓名:张金荣指导教师:孔繁茹完成时间:2017年8月15日目录第 1 节课程设计目的 (1)第 2 节课程设计要求 (1)第 3 节课程设计内容 (2)第 4 节状态转换图 (4)第 5 节实现工具 (4)第 6 节实现函数 (4)第7 节测试结果 (5)第8 节实验源代码 (6)第9 节参考文献 (9)致谢感设计目的①理解词法分析器的基本功能。

词法分析的任务是:从左至右逐个字符地对源程序进行扫描,产生一个个的单词符号(token),把作为字符串的源程序改造成单词符号串的中间程序。

因此,词法分析是编译的基础。

②理解词法规则的描述方法。

程序设计语言一般可以用标识符、关键字、运算符、分隔符、常量、字符串和注释符来描述④理解状态转换图及其实现。

一个状态转换图可用于识别(或接受)一定的字符。

大多数程序语言的单词符号都可以用转换图予以识别。

转换图非常易于用程序实现,最简单的办法是让每个状态结对应一小段程序。

④能够编写简单的词法分析器。

2.课程设计的要求手工构造一个简单的词法分析程序, 能够识别标识符、整数、关键字、算符、界符。

①画出识别单词的状态转换图。

(若状态转换图过于复杂,可以只画出主要部分;若依旧复杂,可只识别标识符和整数)②根据状态转换图手工构造词法分析程序。

从以下方法中选一:✧词法分析器作为独立的一遍。

词法分析结果输出到屏幕上或存入文件。

✧词法分析器作为一个子程序被语法分析器调用。

每次调用返回一个单词同时将单词及属性存入符号表③实现状态转换图。

从以下方法中选一:✧直接转向法✧表驱动法四、选做实验☻使用缓冲技术3.课程设计内容程序语言的单词符号一般可分为下列五种。

(1)关键字是由程序语言定义的具有固定意义的标志符。

本程序定义char,short,int,unsigned,long,float,double,struct,union,void,enum,cons t,typedef,auto,static,break,case,continue,default,do,else,for,if,retu rn,switch,while,sizeof,printf,FILE,fopen,NULL,fclose,exit,read,closef ,printf为关键字。

编译原理-词法分析

编译原理-词法分析
编译原理-词法分析
词法分析是编译原理中的重要阶段,负责将源代码分解为词法单元,为后续 的语法分析准备输入。
词法分析的定义和作用
词法分析是编译器的第一阶段,其主要目的是将源代码转换为有意义的词法 单元,如标识符、关键字、操作符等,以便后续的语法分析和语义分析使用。
词法分析的流程
1
扫描
将源代码分割为符号序列。
2
识别
将符号序列映射到相应的词法单元。

归类
将词法单元分为不同的类别,如标识符、关键字、操作符等。
常见的词法分析技术
正则表达式
用于描述词法单元的模式。
有限自动机
用于识别符号序列并生成词法 单元。
词法分析器生成器
自动生成词法分析器的工具。
词法分析的应用场景
词法分析广泛应用于编译器、解释器和语言处理工具等领域,确保源代码的正确解析和语义分析。
词法分析的挑战和解决方案
错误处理
如何处理错误输入和不合法的词法 单元。
性能优化
如何提高词法分析的速度和效率。
跨平台兼容
如何处理不同编程语言和操作系统 的词法规则。
结论和总结
词法分析是编译原理中不可或缺的一部分,对于编译器的正确性和性能有着 重要影响。了解词法分析的流程和技术,可帮助开发者构建更高效的编译器 和语言处理工具。

编译原理-词法分析

编译原理-词法分析
单词:标识符,保留字,常数,算符,界符 词法分析阶段的工作所依循的是语言的词法规
则。描述词法规则的有效工具是正规式和有限 自动机。
2
3.1 对词法分析器的要求
3.1.1 词法分析器的功能和输出形式
输入源程序,扫描识别, 输出单词符号 程序语言的单词符号一般分为五种:
关 键 字 ( 保 留 字 或 基 本 字 ) : 如 begin,end,if,then,else,while,do等
正规式
正规集
1. ba*
Σ上所有以b为首后跟着
任意多个a的字。
2. a(a|b)*
Σ上所有以a为首的字。
3. (a|b)*(aa|bb)(a|b)* Σ上所有含有两
个相继的a或两个相继的b 的字。
28
正规式与正规集: 例3.2
例3.2: 令Σ={A,B,0,1} , 则:
正规式
正规集
1. (A|B)(A|B|0|1)* 体
字母或数字 0 字母 1 其他 2 *
16
状态转换图识别字符串: 例
识别标识符的状态转换图。其中0为初态,2 为终态。
状态2是终态,它意味着到此已经识别出一个 标识符。终态上打个*号,表示多读进了一个 不属于标识符部分的字符,应把它退还给输入 串。如果在状态0时输入字符不为“字母”, 则意味着这个转换图不工作。
24
正规式定义
正规表达式
正规表达式对应的正规集
1. ,
{},
2. a
{a}
3. 若 r, s
L( r ) , L(s)
则 选择 rs
L( r ) L(s)
连接 r ∙ s
L( r ) ∙ L(s)
闭包 r *

编译原理词法分析报告

编译原理词法分析报告

实验一:词法分析一、实验目的:1、通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。

并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

2、编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本关键字、标识符、常数、运算符、分隔符五大类。

并依次输出各个单词的内部编码及单词符号自身值。

(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。

词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。

本实验中,采用的是一类符号一种别码的方式。

2、单词的BNF表示<标识符>-> <字母><字母数字串><字母数字串>-><字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε<无符号整数>-> <数字><数字串><数字串>-> <数字><数字串> |ε<加法运算符>-> +<减法运算符>->-<大于关系运算符>->><大于等于关系运算符>-> >=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。

如当前待分析字符串为“a>+”,当前字符为’>’,此时,分析器到底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。

于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。

但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。

在分析标识符,无符号整数等时也有类似情况。

编译原理词法分析

编译原理词法分析

编译原理词法分析
编译原理的词法分析是编译器中的一个重要过程,它负责将源代码分
割成一个个的词法单元(Token)。

词法单元是程序中的最小语法单位,
如标识符、关键字、运算符、常数等。

词法分析的主要任务是从左到右扫描源代码字符流,逐个字符进行解析,并根据预先定义的词法规则识别出各种词法单元。

为了实现词法分析,通常会采用有限自动机(DFA)或正则表达式来描述词法规则。

具体的词法分析过程包括以下几个步骤:
1.建立输入缓冲区:将源代码存储在缓冲区中,方便逐个字符进行读
取和处理。

2.扫描字符流:从缓冲区中逐个字符读取并处理,跳过空白字符(空格、制表符、换行符等)。

3.根据词法规则识别词法单元:根据预先定义的词法规则,将字符序
列转换为词法单元,并记录其类型和属性信息。

4.错误处理:如果遇到无法识别的字符序列或不符合词法规则的情况,进行相应的错误处理并报告错误。

5.输出词法单元流:将识别出的词法单元按照顺序输出,作为下一步
的输入。

词法分析是编译器的前端处理阶段,它为语法分析提供了基础数据,
将源代码转化为一个个的词法单元,为后续的语法分析、语义分析和代码
生成等阶段提供支持。

词法分析java编译原理课程设计

词法分析java编译原理课程设计

词法分析java编译原理课程设计一、教学目标本课程旨在让学生掌握词法分析在Java编译原理中的应用,理解并能够运用Java的基本词法规则,包括关键字、标识符、常量、运算符等。

通过本课程的学习,学生应能熟练使用Java编译器进行程序的编译和调试,理解编译过程中词法分析的原理和实现。

具体来说,知识目标包括:1.掌握Java语言的基本词法规则。

2.理解词法分析在编译过程中的作用和重要性。

3.熟悉Java编译器的使用方法和技巧。

技能目标包括:1.能够使用Java编译器进行程序的编译和调试。

2.能够分析并解决Java程序中的词法错误。

3.能够理解和编写简单的词法分析器。

情感态度价值观目标包括:1.培养学生对编译原理的兴趣和好奇心。

2.培养学生解决问题的能力和团队合作的精神。

3.培养学生对编程语言和计算机科学的热爱。

二、教学内容本课程的教学内容主要包括Java的基本词法规则、词法分析的原理和实现、以及Java编译器的使用方法。

具体的教学大纲如下:1.第一章:Java语言概述–Java语言的历史和发展–Java语言的特点和优势–Java语言的应用领域2.第二章:Java的基本词法规则–关键字和保留字–标识符的命名规则–常量的分类和声明–运算符的分类和用法3.第三章:词法分析原理–词法分析在编译过程中的作用–词法分析器的实现方法–词法分析器的测试和优化4.第四章:Java编译器使用–Java编译器的安装和配置–编译和运行Java程序的基本步骤–分析并解决编译过程中的词法错误5.第五章:实战演练–编写简单的Java程序–使用Java编译器进行编译和调试–分析并解决程序中的词法错误三、教学方法为了提高学生的学习兴趣和主动性,本课程将采用多种教学方法相结合的方式。

包括:1.讲授法:通过讲解和演示,让学生掌握Java的基本词法规则和词法分析的原理。

2.讨论法:学生进行小组讨论,培养团队合作的精神,并促进学生对问题的深入思考。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

目录一、实验题目 (2)二、实验目的 (2)三、实验要求 (3)四、实验步骤 (3)基本设计思路 (3)流程框图 (4)算法设计 (5)函数相关说明 (5)输入与输出 (7)程序运行结果 (8)五、实验方案设计实现 (8)六、实验程序亮点描述 (9)七、实验程序使用说明 (9)八、实验心得体会 (9)九、源程序清单........................................................................................错误!未定义书签。

一、实验题目设计、编制、调试一个识别一简单语言单词的词法分析程序。

程序能够识别基本字、标识符、无符号整数、浮点数、运算符和界符)。

单词符号及种别表如下:二、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

三、实验要求词法分析程序需具备词法分析的功能:输入:所给文法的源程序字符串。

(字符串以“#”号结束)输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……四、实验步骤基本设计思路➢基本字作为一类特殊的标识符来处理:识别出标识符,差基本字表,给出相应种别码。

基本字表置初值:char *rwtab[6]={"begin","if","then","while","do","end"};(字符指针的数组)➢识别无符号整数是将数字串转换为无符号整数。

我们在getchar()的时候是把数字当做字符从外部输出读取的。

将数字串345#转换为整数:(3*10+4)*10+5=345送到sum中➢程序主要由2个函数组成,主函数main()和扫描子函数scanner()。

扫描程序每次读取1个独立意义的单词符号,并判断单词类型。

主程序做相应处理后做控制台输出。

流程框图图1主程序图2扫描子程序算法设计词法分析程序所用的较为重要的全局变量和需调用的函数如下:1)ch字符变量,存放当前读进的源程序字符。

2)token[8]字符数组,存放构成单词符号的字符串。

3)prog[80]字符数组,存放所有用户输入的字符。

4)syn整数,存放当前单词的种别码。

5)sum双精度浮点型变量,存放无符号整数,或者浮点数。

6)isDecimal整数,是否为浮点数。

isDecimal为1,则为浮点数。

7)decimal双精度浮点型变量(double),浮点数的小数部分。

8)isExp整数,是否为指数形式表示的浮点数(即是否存在符号E或者e)。

isExp为1,则为指数形式。

9)index整数,指数形式的幂。

10)isNegative整数,是否为负数幂。

isNegative为1,则为负数幂,如123E-2。

11)scanner()扫描子程序。

12)getchar()从控制台读取一个字符数据。

13)double pow(double x,double y),计算x的y次幂。

14)int strcmp(char *str1,char #str2),字符串比较。

函数相关说明1.接收用户输入:getchar()和do…while循环的组合do{ch=getchar();prog[p++]=ch;}while(ch!='#'); //输入以#号键结束2.输出到控制台:do…while循环中,扫描出单词后(扫描程序还会判断种别码syn)输出。

do{scanner(); //扫描,单词switch(syn){case 11:if(isDecimal==0){printf("(%2d,%8d)\n",syn,(int)sum);break;}else if(isExp==1){printf("(%2d,%10.5e)\n",syn,sum);isExp=0;isDecimal=0;break;}else if(isDecimal==1){printf("(%2d,%8.4f)\n",syn,sum);isDecimal=0;break;}case -1:printf("input error\n");break;default:printf("(%2d,%8s)\n",syn,token);}}while(syn!=0);3.浮点数的识别,先识别数字,再识别. ,再识别数字,再识别E或e,再识别- ,再识别数字。

else if((ch>='0')&&(ch<='9')){while((ch>='0')&&(ch<='9')){sum=sum*10+ch-'0'; //ch中数字本身是当做字符存放的ch=prog[p++];}if(ch=='.'){isDecimal=1;ch=prog[p++];while((ch>='0')&&(ch<='9')){//pow(x,y)计算x的y次幂temp=(ch-'0')*pow(0.1,++count);decimal=decimal+temp;//AddToDec();ch=prog[p++];}sum=sum+decimal;}if(ch=='e'||ch=='E'){isExp=1;ch=prog[p++];if(ch=='-'){isNegative=1;ch=prog[p++];}while((ch>='0')&&(ch<='9')){//指数index=index*10+ch-'0';ch=prog[p++];}if(isNegative)sum=sum*pow(0.1,index);elsesum=sum*pow(10,index);}p--;syn=11;}输入与输出词法分析程序需具备词法分析的功能:输入:所给文法的源程序字符串。

(字符串以“#”号结束)输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。

程序运行结果五、实验方案设计实现用C语言实现。

六、实验程序亮点描述浮点数处理部分:巧妙利用double pow(double x,double y)函数,简化了浮点数处理部分。

如果是简单浮点数,如1.23,出现“.”符号,置isDeminal为1,用%f输出。

如果稍微复杂一点,指数形式,但是正数幂,如1.23E2,出现“E”符号,置isExp为1,用%e输出。

如果更复杂一点,指数形式,但是负数幂,如1.23E-2,出现“-”号,置isNegative为1,仍然用%e输出。

如果是有符号数(有符号整数或者有符号浮点数),在识别出“+”或者“-”之后,再读后边一个字符,如果是数字,那么转至识别数字的代码段,并在末尾将sum进行相应处理。

如果后边字符不是数字,证明“+”或者“-”是加减号,而非正负号。

七、实验程序使用说明用户输入待识别字符串(并以“#”结尾,表示字符串输入结束),回车后程序自动输出词法分析结果。

八、实验心得体会词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

通过本试验的完成,更加加深了对词法分析原理的理解。

最初是按照老师课堂上的C语言实现这个思路进行的,但是后来老师要求将识别数字拓展到浮点数(即实数)。

由于本人C语言功底不够扎实,最后只得再回过头去看了一下C语言的语法,不过最后还是通过自己的力量把东西给做出来了。

很有成就感!参考文献[1] 张素琴,吕映芝等.编译原理[M].第2版.北京:清华大学出版社,2005.2[2] 王雷,刘志成等.编译原理课程设计[M].北京:电子工业出版社,2002[3] 何炎祥等.编译程序构造[M].武汉:武汉大学出版社,1988[4] Holub piler Design in C[M].Prentice-Hall,1990源程序代码#include<stdio.h>#include<string.h>#include<math.h>char prog[80]; //存放所有输入字符char token[8]; //存放词组char ch; //单个字符int syn,p,m,n; //syn:种别编码double sum;int count;int isSignal; //是否带正负号(0不带,1负号,2正号)int isDecimal; //是否是小数double decimal; //小数int isExp; //是否是指数int index; //指数幂int isNegative; //是否带负号double temp;int temp2;void scanner();char *rwtab[6]={"begin","if","then","while","do","end"};void main(){p=0;count=0;isDecimal=0;index=0;printf("\n Please input string:\n");do{ch=getchar();prog[p++]=ch;}while(ch!='#'); //输入以#号键结束p=0;do{scanner(); //扫描,单词switch(syn){case 11:if(isDecimal==0){//加了1个强制类型转换printf("(%2d,%8d)\n",syn,(int)sum);break;}else if(isExp==1){printf("(%2d,%10.5e)\n",syn,sum);isExp=0;isDecimal=0;break;}else if(isDecimal==1){printf("(%2d,%8.4f)\n",syn,sum);isDecimal=0;break;}case -1:printf("input error\n");break;default:printf("(%2d,%8s)\n",syn,token);}}while(syn!=0);}void scanner(){sum=0;decimal=0;m=0;for(n=0;n<8;n++)token[n]=NULL;ch=prog[p++]; //从prog中读出一个字符到ch中while(ch==' ') //跳过空字符(无效输入)ch=prog[p++];if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))) //ch是字母字符{while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9'))){token[m++]=ch; //ch=>tokench=prog[p++]; //读下一个字符}token[m++]='\0';p--; //回退一格syn=10; //标识符//如果是"begin","if","then","while","do","end"标识符中的一个for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0')&&(ch<='9')){IsNum:if(isSignal==1){//token[m++]='-';}while((ch>='0')&&(ch<='9')){sum=sum*10+ch-'0'; //ch中数字本身是当做字符存放的ch=prog[p++];}if(ch=='.'){isDecimal=1;ch=prog[p++];while((ch>='0')&&(ch<='9')){//pow(x,y)计算x的y次幂temp=(ch-'0')*pow(0.1,++count);decimal=decimal+temp;//AddToDec();ch=prog[p++];}sum=sum+decimal;}if(ch=='e'||ch=='E'){isExp=1;ch=prog[p++];if(ch=='-'){isNegative=1;ch=prog[p++];}while((ch>='0')&&(ch<='9')){//指数index=index*10+ch-'0';ch=prog[p++];}//10的幂//123e3代表123*10(3)//sum=sum*pow(10,index);是错误的if(isNegative)sum=sum*pow(0.1,index);elsesum=sum*pow(10,index);}if(isSignal==1){sum=-sum;isSignal=0;}p--;syn=11;}else switch(ch){case '<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21; //<>对应21token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=20;p--;}break;case '>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=23;p--;}break;case ':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case '+':temp2=prog[p];if((temp2>='0')&&(temp2<='9')){isSignal=2;ch=prog[p++];goto IsNum;}syn=13;token[m++]=ch;break;case '-':temp2=prog[p];if((temp2>='0')&&(temp2<='9')){isSignal=1;ch=prog[p++];goto IsNum; //转到数字的识别}syn=14;token[m++]=ch;break;case '*':syn=15;token[m++]=ch;break;case '/':syn=16;token[m++]=ch;break;case '=':syn=25;token[m++]=ch;break;case ';':syn=26;token[m++]=ch;break;case '(':syn=27;token[m++]=ch;break;case ')':syn=28;token[m++]=ch;break;case'#':syn=0;token[m++]=ch;break;default:syn=-1;}}。

相关文档
最新文档