编写词法分析程序
词法分析及词法分析程序
– w,p,n初值为0,e初值为1;
– 处理整数部分时,对于每个di ,令w=w10+di ; – 处理小数部分时,对于每个di ,令w=w10+di ;及n++;
– 处理指数时,E后若有‘-’号,令e=-1;计算指数值 p=p10+d;
– 在出口处,令ICON=w或FCON=w10^(e(p-n)).
(2)设当前处在Ai状态,所扫描的字符为ai+1,在结点Ai所 射出的诸矢线中,寻找标记为ai+1的矢线(若不存在,则 表明w有语法错误),读入ai+1,并进入状态Ai+1;
(3)重复(2),直到w中所有字符被读完且恰好进入终态F 时,宣告整个识别结束,w可被接受.
28
例:G[Z]:
状态转换图:
Z→0U∣1V
{return ( ICON= w ); {n++; w=w*10+d;}
{return (FCON =w*pow(10,e*p-n) ) ;} {n++;w=w*10+d;} error {p=p*10+d;}
e=-1; error {p=p*10+d;} error {p=p*10+d;} {return (FCON=w*pow(10,e*p-n) );
(1)对于G中形如Aa 的产生式,引矢线RA,且标记
为a;
(2)对于G中形如ABa 的产生式,引矢线 BA,且标
记为a。
34
由左线性文法构造状态转换图
已给文法G=({S,U},{0,1},{SS1 |U1, UU0 | 0},S)
R0
0
1
U1 S
编写PL-0语言词法分析程序(c)
编写PL/0语言的词法分析程序要求:1、读入用PL/0语言编写的源程序,正确的进行词法分析,并输出二元式序列。
2、若源程序有词法错误,能够给出出错的准确位置。
3、词法代号如下(+,+);(-,-);(*,*);(/,/);((,();(),));(,,,);(;,;);(.,.);(#,#);(=,=);(>,>);(<,<);(:=,a);(>=,b);(<=,c);(数字,d);(标识符,e);关键字代号:(begin,f);(call,g);(const,h);(do,i);(end,j);(if,k);(odd,l);(procedure,m);(read,n);(then,o);(var,p);(while,q);(write,r);4、等于运算符号为一个 =测试程序:A.C======================CONST A=10;VAR B,C;PROCEDURE P;VAR D;PROCEDURE Q;VAR X;BEGINREAD(X);D:=X;WHILE X<0DO CALL P;END;BEGINWRITE(D);CALL Q;END;BEGINCALL P;END.*//*program name:chifufenxi*//*作者:小万 qq:421404493*//*date:2004.10.11*/#include<stdio.h>#include<stdlib.h>#include<conio.h>#include<ctype.h>#include<string.h>#define N 256//每一行的字符数不能超过256个char buffer[N]; //用作存放一行字符char word[20]; //用作存放经过分析单词char *kword[13]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"};char ktype[13]={'f','g','h','i','j','k','l','m','n','o','p','q','r'};int len;//记录每一行的长度int count=0;//用来记录行数void write(char *wstr,char wc,FILE *wout)//将分析结果按照规则写入到文件{fputc('(',wout);fputs(wstr,wout);fputc(',',wout);fputc(wc,wout);fputc(')',wout);}int readbuffer(FILE *fp){char ch;len=0;ch=fgetc(fp);while(!feof(fp) && ch!='\n')//读取字符到缓冲区{buffer[len]=ch;ch=fgetc(fp);len++;}len--;//用来控制词法分析时行分析中字母的个数if(feof(fp))//标志文件是否结束return 0;elsereturn 1;}void error(int type){if(type==1)printf("为无效字符,第%d行词法出错,标志符不能以数字开头\n",count); else if(type==2)printf("第%d行词法出错,赋值符应为\:\= \n ",count);else printf("为无效字符,第%d行词法出错\n",count);}void check(char *str,FILE *out);//声明函数,此函数用来分类单词void fenxi(char *row,FILE *op)//此函数用来对每一行的单词进行语法分析{//printf("%d\n",count);int k=0;//用作控制临时存放单词的变量str0int i=0;//定义两个变量用作控制每一行是否结束,int ferror=0;//用作出错标志char str0[20];//临时存放单词的变量while(i<=len){k=0;//将k置0strcpy(word,"\0");//将存放单词的变量清空/*去除空格*/if(isspace(row[i]))//去出空格,跳格符,换行符{i++;continue;}/*去出无效字符*/while(!isalpha(row[i])&&!isdigit(row[i])&&i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'|| row[i]=='<'||row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';' || row[i]=='.'|| row[i]=='#' || row[i]=='=')){putchar(row[i]);i++;ferror=1;//设置错误标志符}if(ferror==1){error(3);//调用出错处理函数ferror=0;}/*对注释进行处理,假设此语言的注释只能单行注释以双斜杠“//”为注释开始标志*/if(row[i]=='/'){i++;if(row[i]=='/'){i=len+1;//忽略注释符后面的单词continue;}elsei--;}/*判断是否为数字*/if(isdigit(row[i])){while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]=='+' || row[i]==' -' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]= ='='))//当不到行尾,是数字或字母当然有可能是无效字符{if(isdigit(row[i]))//是数字则将字符逐个存入临时数组{str0[k]=row[i];i++;k++;// putchar('e');}else //数字中加有字母或无效字符则报错{// putchar('x');ferror=1;break;//已经出错设置标志并退出循环}}if(ferror==1)//检测是否出错{ /*将刚刚的那个单词后面的数字和字母清空,如123abc123或则123$$23等,当出现错误后,需要消除abc123和$$23以免误作为下一个标志符*/for(int j=0;j<k;j++)putchar(str0[j]);while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]==' =')){putchar(row[i]);i++;}error(1);//putchar('e');//调用出错处理函数ferror=0;//重新设置错误标志位//i--;//strcpy(word,"");}else//未出错照常处理{str0[k]='\0';strcpy(word,str0);i--;//减一是为了使最后取出的那个字符不在被下面的程序判断// str0[0]='\0';}}/*判断是否为标志符和关键字即由字母开头并且不含标点符号用ispunct(int ch)判断标点符号*/if(isalpha(row[i]))//标志符或关键字由字母开头{k=0;while(i<=len&&row[i]!=32&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]=='+' || row[i]=='-' || ro w[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]=='='))/ /关键字和标志符由数字和字母组成{if(isalpha(row[i])||isdigit(row[i]))//由数字和字母组成{str0[k]=row[i];i++;k++;}else//出错,原因可能是出现了不可识别的字符{ferror=1;break;}}if(ferror){for(int j=0;j<k;j++)putchar(str0[j]);while(i<=len&&!isspace(row[i])&&!(row[i]=='\0'||row[i]==':'||row[i]=='>'||row[i]=='<'||row[i]=='+' || row[i]=='-' || row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'|| row[i]=='.'|| row[i]=='#' || row[i]==' =')){putchar(row[i]);//消除整个非法单词i++;}ferror=0;error(3);//i--;}else{str0[k]='\0';strcpy(word,str0);str0[0]='\0';i--;}}/*判断运算符*/if(row[i]=='+' ||row[i]=='-' ||row[i]=='*' || row[i]=='/' || row[i]=='(' || row[i]==')' || row[i]==',' || row[i]==';'||row[ i]=='.'||row[i]=='#' || row[i]=='='){str0[0]=row[i];str0[1]='\0';strcpy(word,str0);str0[0]='\0';}//要先判断单个字符的运算符,以避免诸如>=的运算符后面的=再次被判断if(row[i]==':'){i++;if(row[i]=='='){//word[0]=':';//word[1]='=';//word[2]='\0';strcpy(word,">=");}else{error(2);//出错后调用处理函数i--;}}if(row[i]=='>'){i++;if(row[i]=='='){strcpy(word,">=");}else{strcpy(word,">");i--;}}if(row[i]=='<'){i++;if(row[i]=='='){strcpy(word,"<=");}else{strcpy(word,"<");i--;}}//puts(word);check(word,op);/*调用分类函数,辨别每一个单词的类别要求输入的每一个单词必须符合词法规则*///word[0]='\0';i++;//使指针后移,取出下一个字母}}void check(char *str,FILE *out){if(isdigit(str[0]))/*如果第一个字符是数字那么整个单词都是数字组成的,即为常数*/ {write(str,'d',out);//调用写函数将分好类的单词写入文件}if(isalpha(str[0]))/*如果第一个字符是字母,那么这个单词是标志符或关键字*/ {int fyiyong=0;//用作标记这个单词是否已被分类/*以下判别是否是关键字*/for(int ct=0;ct<13;ct++){if(!strcmp(str,kword[ct])){write(str,ktype[ct],out);fyiyong=1;}}/*经过以上判别,可以判别是否是关键字,不是即为标志符*/if(fyiyong!=1){write(str,'e',out);}}/*以下对运算符分类*/if(str[0]=='>'){if(str[1]=='='){write(str,'b',out);}else{write(str,'>',out);}}if(str[0]=='<'){if(str[1]=='='){write(str,'c',out);else{write(str,'<',out);}}if(!strcmp(str,":=")){write(str,'a',out);}if(str[0]=='+' || str[0]=='-' || str[0]=='*' || str[0]=='/' || str[0]=='(' || str[0]==')' || str[0]==',' || str[0]==';'|| str[0]=='.'|| st r[0]=='#' || str[0]=='=' ){write(str,str[0],out);}}void main(){count=1;char scfilename[20],rsfilename[20];//定义用来存放输入源文件和输出目标文件的名字printf("Please input your source file name:");gets(scfilename);printf("Please input your result file name:");gets(rsfilename);FILE *fp,*op;fp=fopen(scfilename,"r");op=fopen(rsfilename,"w");if(fp)//打开文件成功后调用函数对源文件进行词法分析{while(readbuffer(fp)){fenxi(buffer,op);count++;//行加一}}else//while the file not exist{printf("Your souce file not exist\n"); exit(0);}fclose(fp);//close the filesfclose(op);printf("ok!");//output the mark of end getchar();}。
词法分析程序的设计(共15张PPT)
➢方法二:每个基本字一个编码;所有标识符 方法一:按单词的5大种类每种一个码,例如标识符为l,常数为2,基本字为3,运算符为4,界符为5。
GetChar();
分别判别ch字符是否为字为母或一数字 个编码;常数按类型分类,每类一个编 码;每个运算符一个编码;每个界符一个编 码。
(1,指向x的符号表入口)
(3,‘then’) 方法一:按单词的5大种类每种一个码,例如标识符为l,常数为2,基本字为3,运算符为4,界符为5。
(1,指向y的符号表入口)
(1,指向y的符号表入口)
(1,指向x的符号表入口 else If(ch=‘/’) {状态 l 的对应程序段;}
)
(4,‘:=’)
二元式(单词种别,单词自身的值) 对常数,基本字,运算符,界符就是他们本身的值
3. 换行符不能删,对于错误处理起作用。 (1,指向i的符号表入口)
每当遇到左括号,则计数器加1
❖ 复合型特殊符,如“:=”的处理
读到“:”时不能判断是否为冒号,必须读下一字符。
第9页,共15页。
❖ 括号类配对: “‘”和“’”、左注释符和右注释符的配对。也 可以把begin …end ,if …then,[ ],{ },( )等语 法配对在词法分析中进行处理 处理方法:
第5页,共15页。
单词的机内表示
二元式(单词种别,单词自身的值) 种别是语法分析需要的信息 二元式(单词种别,单词自自身身的值)值是编译其他阶段需要的信息 种别编码(常用整数编码) 常数按类型分类,每类一个编码;
二元式(单词种别,单词自身的值) GetChar();
➢ 方法一:按单词的5大种类每种一个码,例 常数按类型分类,每类一个编码;
实验1:词法分析程序
实验1 词法分析程序一、实验目的与要求1.复习正规文法、正规式、有限自动机之间的相互转换的原理及技术;2.学会使用Visual C++等高级语言编程实现上述转换,并能合理显示结果;3.以C++的一个真子集为案例,具体分析词法分析程序的设计步骤、基本架构及代码编制,并通过一定实例验证其可行性,以加深对词法分析原理的理解;4.通过本次实验,使学生理解模块化程序设计的思想,从而从全局角度领会一个完整软件的设计精髓,为后续试验的顺利完成奠定坚实的基础。
二、实验仪器及设备1.微型电子计算机80台2.配置Windows 2000及以上版本操作系统3.安装Visual C++6.0/Visual C#2000/Delphi6.0等以上版本的开发环境三、实验内容及步骤(一)正规文法与有限自动机的相互转换1.正规文法⇒有限自动机已知某正规文法G[S]如下:S→aAS→bBS→εA→aBA→bAB→aSB→bAB→ε请编程实现:(1)将G[S]转换为NFA;(2)将上述得到的NFA确定化为DFA;(3)再将DFA最简化为MFA。
2.有限自动机⇒正规文法已知某有限自动机NFA M=(Q,∑,f,q0,Z)如下:状态集:Q={1,2,3,4,5,6,7,8,9}字母表:∑={a,b}转移函数:f(1,a)=5f(1,ε)=2f(1,a)=4f(5,ε)=6f(2,b)=3f(4,ε)=7f(6,ε)=2f(6,b)=9f(3,ε)=8f(8,a)=9f(7,b)=9初态:q0=1终态集:Z={6,7,9}请编程实现:(1)首先将此NFA确定化为DFA;(2)再将得到的DFA最简化为MFA;(3)最后,将MFA转化为正规文法(左线性或右线性均可)。
(二)编程实现MiniC++的词法分析这里的MiniC++为C++语言的一个真子集,其语法结构与C++类似。
基本组成如下:(1)关键字有18个,分别为:void、int、char、bool、float、double、if、else、switch、case、default、break、continue、do、while、for、return以及struct等。
词法分析程序(C语言编写,针对PL_0语言)
#include <stdio.h>#include <stdlib.h>#include <string.h>#define NORW 13 /* of reserved words */#define TXMAX 100 /* length of identifier table */#define NMAX 14 /* max number of digits in numbers */#define AL 10 /* length of identifiers */#define AMAX 2047 /* maxinum address */#define LEVMAX 3 /* max depth of block nesting */#define CXMAX 200 /* size of code array */#define STACKSIZE 500char *symbol[32]= {"nul","ident","number","plus","minus","times","slash","oddsym","eql","neq","lss","leq","gtr","geq","lparen","rparen","comma","semicolon","period","becomes","beginsym","endsym","ifsym","thensym","whilesym","writesym","readsym","dosym","callsym","constsym","varsym","procsym"}; /* type of symbols */c har *word[NORW]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"}; /* table of reserved words */ char *wsym[NORW]={ "beginsym","callsym","constsym","dosym","endsym","ifsym", "oddsym","procsym","readsym","thensym","varsym","whilesym","writesym"};char *mnemonic[8]= {"lit","opr","lod","sto","cal","ini","jmp","jpc"};char ch; /* last char read */char id[AL+1]; /*last identifier read */char sym[10]; /* last symbol read */char line[81];char a[AL+1],fname[AL+1];enum object{constant,variable,procedur};enum object kind;enum fct{lit,opr,lod,sto,cal,ini,jmp,jpc};enum listswitcher{false,true}; /*true set list object code */enum listswitcher listswitch;FILE *fa;FILE *fa1, *fa2;FILE *fin, *fout;int num; /* last number read */int cc; /* character count */int ll; /* line length */int cx; /* code allocation index */int err;int lev=0,tx=0,dx=3;int linecnt=0;struct instruction{enum fct f; /* function code */int l; /* level */int a; /* displacement addr */}; /* lit 0,a: load constant aopr 0,a: execute opr alod l,a: load variable 1, asto l,a: store variable 1, acal l,a: call procedure a at level 1int 0,a: increment t-register by ajmp 0,a: jump to ajpc 0,a: jump conditional to a */ struct instruction code[CXMAX+1];struct table1{char name[AL+1];enum object kind;int val,level,adr,size;};struct table1 table[TXMAX+1];struct node{c har *pa[32];}*declbegsys,*statbegsys,*facbegsys,*tempsetsys; int in(str, set)char *str;struct node *set;{i nt i=0;w hile(set->pa[i]!=NULL){if(strcmp(str,set->pa[i])==0)return( 1 );elsei++;}r eturn( 0 );}struct node *add(set1,set2)struct node *set1,*set2;{i nt i=0,j=0,k=0,cnt;s truct node *pt;p t=(struct node *)malloc(sizeof(struct node));f or(cnt=0; cnt < 32; cnt++)pt->pa[cnt]=(char*)malloc(10*sizeof(char));w hile(set1->pa[i]!=NULL)strcpy(pt->pa[j++],set1->pa[i++]);w hile(set2->pa[k]!=NULL){if (in(set2->pa[k],set1)==0)strcpy(pt->pa[j++],set2->pa[k++]);elsek++;}p t->pa[j]=NULL;r eturn( pt );}error(int n){i nt i;p rintf ("***");f puts ("***", fa1);f or (i=0;i<cc;i++){printf (" ");}f or (i=0;i<cc;i++){fputs (" ",fa1);}p rintf ("error%d\n",n);f printf (fa1, "error%d\n",n);e rr=err+1;}void get_ch( ){i f (cc==ll+1){if (feof(fin)){printf ("program incomplete");}ll= 0;cc= 0;while ((!feof(fin)) && ((ch=fgetc(fin))!='\n')){putchar(ch);fputc(ch,fa1);line[ll++]=ch;}printf ("\n");line[ll]=ch;fprintf (fa1,"\n");}c h=line[cc++];}void getsym( ){i nt i,j,k;w hile(ch==' '||ch=='\t'||ch=='\n')get_ch( );i f (ch>='a'&&ch<='z'){ /* id or reserved word */k=0;do {if(k<AL){a[k]=ch;k=k+1;}get_ch( );}while((ch>='a'&&ch<='z')||(ch>='0'&&ch<='9'));a[k]='\0';strcpy(id,a);i=0;j=NORW-1;do { /* look up reserved words by binary search */k=(i+j)/2;if (strcmp(id,word[k])<=0) j=k-1;if (strcmp(id,word[k])>=0) i=k+1;}while (i<=j);if (i-1>j) strcpy(sym,wsym[k]);else strcpy(sym,"ident");}e lse if (ch>='0'&&ch<='9'){ /* number */k=0;num=0;strcpy(sym,"number");do {num=10*num+(int)ch-'0';k=k+1;get_ch( );}while(ch>='0'&&ch<='9');if(k>NMAX) error(30);}e lse if (ch==':'){get_ch( );if (ch=='='){strcpy(sym,"becomes");get_ch( );}else strcpy(sym,"nul");}e lse if (ch=='<'){get_ch( );if (ch=='='){strcpy(sym,"leq");get_ch( );}else strcpy(sym,"lss");}e lse if (ch=='>'){get_ch( );if (ch=='='){strcpy(sym,"geq");get_ch( );}else strcpy(sym,"gtr");}e lse {switch(ch){case '+': strcpy(sym,"plus");break;case '-': strcpy(sym,"minus");break;case '*': strcpy(sym,"times");break;case '/': strcpy(sym,"slash");break;case '(': strcpy(sym,"lparen");break;case ')': strcpy(sym,"rparen");break;case '=': strcpy(sym,"eql");break;case ',': strcpy(sym,"comma");break;case '.': strcpy(sym,"period");break;case '#': strcpy(sym,"neq");break;case ';': strcpy(sym,"semicolon");break;}get_ch( );}}void gen(x,y,z)enum fct x;int y,z;{i f (cx>CXMAX){printf("program too long");}c ode[cx].f=x;c ode[cx].l=y;c ode[cx].a=z;c x++;}void test(s1,s2,n)struct node *s1,*s2;int n;{i f (in(sym,s1)==0){error(n);s1=add(s1,s2);while(in(sym,s1)==0) getsym( );}}void enter(k) /* enter object into table */ enum object k;{t x=tx+1;s trcpy(table[tx].name,id);t able[tx].kind=k;s witch(k){case constant:if (num>NMAX){error(31);num=0;}table[tx].val=num;break;case variable:table[tx].level=lev;table[tx].adr=dx;dx++;break;case procedur:table[tx].level=lev;break;}}int position(id) /* find identifier in table */ char id[10];{i nt i;s trcpy(table[0].name,id);i=tx;w hile (strcmp(table[i].name,id)!=0)i--;r eturn i;}void constdeclaration( ){i f (strcmp(sym,"ident")==0){getsym( );if (strcmp(sym,"eql")==0||strcmp(sym,"becomes")==0){if (strcmp(sym,"becomes")==0) error(1);getsym( );if (strcmp(sym,"number")==0){enter(constant);getsym( );}else error(2);}else error(3);}e lse error(4);}void vardeclaration( ){i f (strcmp(sym,"ident")==0){enter(variable);getsym( );}e lse error(4);}void listcode(int cx0) /* list code generated for this block */ {i nt i;i f (listswitch==true){for(i=cx0;i<=cx-1;i++){printf("%2d %5s %3d %5d\n",i,mnemonic[(int)code[i].f],code[i].l,code[i].a);fprintf(fa,"%2d %5s %3d %5d\n",i,mnemonic[(int)code[i].f],code[i].l,code[i].a);}}}void factor(fsys)struct node *fsys;{v oid expression( );i nt m=0,n=0,i;c har *tempset[ ]={"rparen",NULL};s truct node *temp;t emp=(struct node *)malloc(sizeof(struct node));w hile(tempset[m]!=NULL)temp->pa[n++]=tempset[m++];t emp->pa[n]=NULL;t est(facbegsys,fsys,24);w hile(in(sym,facbegsys)==1){if (strcmp(sym,"ident")==0){i=position(id);if (i==0) error(11);else switch(table[i].kind){case constant: gen(lit,0,table[i].val);break; /*some thing error here(lev)*/ case variable: gen(lod,lev-table[i].level,table[i].adr);/*must use para pass in*/break;case procedur: error(21);break;}getsym( );}else if (strcmp(sym,"number")==0){if (num>AMAX){error(31);num=0;}gen(lit,0,num);getsym( );}else if (strcmp(sym,"lparen")==0){getsym( );expression(add(temp,fsys));if (strcmp(sym,"rparen")==0) getsym( );else error(22);}test(fsys,facbegsys,23);}}void term(fsys)struct node *fsys;{i nt i=0,j=0;c har mulop[10];c har *tempset[ ]={"times","slash",NULL};s truct node *temp;t emp=(struct node *)malloc(sizeof(struct node));w hile(tempset[i]!=NULL)temp->pa[i++]=tempset[j++];t emp->pa[i]=NULL;f actor(add(temp,fsys));w hile (in(sym,temp)==1){strcpy(mulop,sym);getsym( );factor(add(temp,fsys));if (strcmp(mulop,"times")==0) gen(opr,0,4);else gen(opr,0,5);}}void expression(fsys)struct node *fsys;{i nt m=0,n=0;c har addop[10];c har *tempset[ ]={"plus","minus",NULL};s truct node *temp;t emp=(struct node *)malloc(sizeof(struct node));w hile(tempset[m]!=NULL)temp->pa[n++]=tempset[m++];t emp->pa[n]=NULL;i f(in(sym,temp)==1){strcpy(addop,sym);getsym( );term(add(fsys,temp));if (strcmp(addop,"minus")==0) gen(opr,0,1);}e lse term(add(fsys,temp));w hile (in(sym,temp)==1){strcpy(addop,sym);getsym( );term(add(fsys,temp));if (strcmp(addop,"plus")==0) gen(opr,0,2);else gen(opr,0,3);}}void condition(fsys)struct node *fsys;{i nt i=0,j=0;c har relop[10];c har *tempset[ ]={"eql","neq","lss","leq","gtr","geq",NULL}; s truct node *temp;t emp=(struct node *)malloc(sizeof(struct node));w hile(tempset[i]!=NULL)temp->pa[j++]=tempset[i++];t emp->pa[j]=NULL;i f (strcmp(sym,"oddsym")==0){getsym( );expression(fsys);gen(opr,0,6);}e lse {expression(add(temp,fsys));if (in(sym,temp)==0) error(20);else {strcpy(relop,sym);getsym( );expression(fsys);if(strcmp(relop,"eql")==0) gen(opr,0,8);if(strcmp(relop,"neq")==0) gen(opr,0,9);if(strcmp(relop,"lss")==0) gen(opr,0,10);if(strcmp(relop,"geq")==0) gen(opr,0,11);if(strcmp(relop,"gtr")==0) gen(opr,0,12);if(strcmp(relop,"leq")==0) gen(opr,0,13);}}}void statement(fsys,plev)struct node *fsys;int plev;{i nt i,cx1,cx2,m=0,n=0;c har *tempset1[ ]={"rparen","comma",NULL};c har *tempset2[ ]={"thensym","dosym",NULL};c har *tempset3[ ]={"semicolon","endsym",NULL};c har *tempset4[ ]={"semicolon",NULL};c har *tempset5[ ]={"dosym",NULL};c har *tempset6[ ]={NULL};s truct node *temp1,*temp2,*temp3,*temp4,*temp5,*temp6; t emp1=(struct node *)malloc(sizeof(struct node));t emp2=(struct node *)malloc(sizeof(struct node));t emp3=(struct node *)malloc(sizeof(struct node));t emp4=(struct node *)malloc(sizeof(struct node));t emp5=(struct node *)malloc(sizeof(struct node));t emp6=(struct node *)malloc(sizeof(struct node));w hile(tempset1[m]!=NULL)temp1->pa[n++]=tempset1[m++];t emp1->pa[n]=NULL;m=0;n=0;w hile(tempset2[m]!=NULL)temp2->pa[n++]=tempset2[m++];t emp2->pa[n]=NULL;m=0;n=0;w hile(tempset3[m]!=NULL)temp3->pa[n++]=tempset3[m++];t emp3->pa[n]=NULL;m=0;n=0;w hile(tempset4[m]!=NULL)temp4->pa[n++]=tempset4[m++];t emp4->pa[n]=NULL;m=0;n=0;w hile(tempset5[m]!=NULL)temp5->pa[n++]=tempset5[m++];t emp5->pa[n]=NULL;m=0;n=0;w hile(tempset6[m]!=NULL)temp6->pa[n++]=tempset6[m++];t emp6->pa[n]=NULL;m=0;n=0;i f (strcmp(sym,"ident")==0){i=position(id);if (i==0)error(11);else {if (table[i].kind!=variable){error(12);i=0;}}getsym( );if (strcmp(sym,"becomes")==0) getsym( );else error(13);expression(fsys);if (i!=0)gen(sto,plev-table[i].level,table[i].adr);}e lse if (strcmp(sym,"readsym")==0){getsym( );if (strcmp(sym,"lparen")!=0) error(24);else {do{getsym( );if (strcmp(sym,"ident")==0) i=position(id);else i=0;if (i==0) error(35);else {gen(opr,0,16);gen(sto,plev-table[i].level,table[i].adr);}getsym( );}while(strcmp(sym,"comma")==0);}if (strcmp(sym,"rparen")!=0) {error(22);while(in(sym,fsys)==0) getsym( );}else getsym( );}e lse if (strcmp(sym,"writesym")==0){getsym( );if (strcmp(sym,"lparen")==0){do{getsym( );expression(add(temp1,fsys));gen(opr,0,14);}while(strcmp(sym,"comma")==0);if (strcmp(sym,"rparen")!=0) error(33);else getsym( );}gen(opr,0,15);}e lse if (strcmp(sym,"callsym")==0){getsym( );if (strcmp(sym,"ident")!=0) error(14);else {i=position(id);if (i==0) error(11);else {if (table[i].kind==procedur)gen(cal,plev-table[i].level,table[i].adr);else error(15);}getsym( );}}e lse if (strcmp(sym,"ifsym")==0){getsym( );condition(add(temp2,fsys));if (strcmp(sym,"thensym")==0) getsym( );else error(16);cx1=cx;gen(jpc,0,0);statement(fsys,plev);code[cx1].a=cx;}e lse if (strcmp(sym,"beginsym")==0){getsym( );statement(add(temp3,fsys),plev);while(in(sym,add(temp4,statbegsys))==1){if (strcmp(sym,"semicolon")==0) getsym( );else error(10);statement(add(temp3,fsys),plev);}if (strcmp(sym,"endsym")==0) getsym( );else error(17);}e lse {if (strcmp(sym,"whilesym")==0){cx1=cx;getsym( );condition(add(temp5,fsys));cx2=cx;gen(jpc,0,0);if (strcmp(sym,"dosym")==0) getsym( );else error(18);statement(fsys,plev);gen(jmp,0,cx1);code[cx2].a=cx;}}t est(fsys,temp6,19);}void block(plev,fsys)int plev;struct node *fsys;{i nt m=0,n=0;i nt dx0=3; /* data allocation index */ i nt tx0; /* initial table index */i nt cx0; /* initial code index */c har *tempset1[ ]={"semicolon","endsym",NULL};c har *tempset2[ ]={"ident","procsym",NULL};c har *tempset3[ ]={"semicolon",NULL};c har *tempset4[ ]={"ident",NULL};c har *tempset5[ ]={NULL};s truct node *temp1,*temp2,*temp3,*temp4,*temp5;t emp1=(struct node *)malloc(sizeof(struct node));t emp2=(struct node *)malloc(sizeof(struct node));t emp3=(struct node *)malloc(sizeof(struct node));t emp4=(struct node *)malloc(sizeof(struct node));t emp5=(struct node *)malloc(sizeof(struct node));w hile(tempset1[m]!=NULL)temp1->pa[n++]=tempset1[m++];t emp1->pa[n]=NULL;m=0;n=0;w hile(tempset2[m]!=NULL)temp2->pa[n++]=tempset2[m++];t emp2->pa[n]=NULL;m=0;n=0;w hile(tempset3[m]!=NULL)temp3->pa[n++]=tempset3[m++];t emp3->pa[n]=NULL;m=0;n=0;w hile(tempset4[m]!=NULL)temp4->pa[n++]=tempset4[m++];t emp4->pa[n]=NULL;m=0;n=0;w hile(tempset5[m]!=NULL)temp5->pa[n++]=tempset5[m++];t emp5->pa[n]=NULL;m=0;n=0;l ev=plev;t x0=tx;t able[tx].adr=cx;g en(jmp,0,1);i f (plev>LEVMAX) error(32);d o{if (strcmp(sym,"constsym")==0){getsym( );do{constdeclaration( );while(strcmp(sym,"comma")==0){getsym( );constdeclaration( );}if (strcmp(sym,"semicolon")==0) getsym( );else error(5);}while(strcmp(sym,"ident")==0);}if (strcmp(sym,"varsym")==0){getsym( );do{dx0++;vardeclaration( );while (strcmp(sym,"comma")==0){getsym( );dx0++;vardeclaration( );}if (strcmp(sym,"semicolon")==0) getsym( );else error(5);}while(strcmp(sym,"ident")==0);}while (strcmp(sym,"procsym")==0){getsym( );if (strcmp(sym,"ident")==0){enter(procedur);getsym( );}else error(4);if (strcmp(sym,"semicolon")==0) getsym( );else error(5);block(plev+1,add(temp3,fsys));lev=lev-1;if (strcmp(sym,"semicolon")==0){getsym( );test(add(statbegsys,temp2),fsys,6);}else error(5);}test(add(statbegsys,temp4),declbegsys,7);}while(in(sym,declbegsys)==1);c ode[table[tx0].adr].a=cx;t able[tx0].adr=cx;t able[tx0].size=dx0;c x0=cx;g en(ini,0,dx0);s tatement(add(temp1,fsys),plev);g en(opr,0,0);t est(fsys,temp5,8);l istcode(cx0);}int base(l,b,s)int l;int *b;int s[STACKSIZE];{int b1;b1=*b; /*find base l level down */ while(l>0){b1=s[b1];l=l-1;}return b1;}void interpret( ){i nt p=0; /* p:program register*/ i nt b=1; /* b:base register*/i nt t=0; /* t:topstack registers */ s truct instruction i;i nt s[STACKSIZE]; /* datastore */p rintf("start pl0\n");s[0]=0;s[1]=0;s[2]=0;s[3]=0;d o{i=code[p];p=p+1;switch(i.f){case lit: t=t+1;s[t]=i.a;break;case opr:switch(i.a){ /*operator*/case 0: t=b-1; /*return*/p=s[t+3];b=s[t+2];break;case 1: s[t]=-s[t];break;case 2: t=t-1; /*plus*/s[t]=s[t]+s[t+1];break;case 3: t=t-1; /*minus*/s[t]=s[t]-s[t+1];break;case 4: t=t-1; /*times*/s[t]=s[t]*s[t+1];break;case 5: t=t-1;s[t]=s[t]/s[t+1];break;case 6: if (s[t]%2==0) s[t]=0;else s[t]=1;break;case 8: t=t-1;if (s[t]==s[t+1]) s[t]=1;else s[t]=0;break;case 9: t=t-1;if (s[t]==s[t+1]) s[t]=0;else s[t]=1;break;case 10:t=t-1;if (s[t]<s[t+1]) s[t]=1;else s[t]=0;break;case 11:t=t-1;if (s[t]>=s[t+1]) s[t]=1;else s[t]=0;break;case 12:t=t-1;if (s[t]>s[t+1]) s[t]=1;else s[t]=0;break;case 13:t=t-1;if (s[t]<=s[t+1]) s[t]=1;else s[t]=0;break;case 14:printf("%d",s[t]);fprintf(fa2,"%d",s[t]);t=t-1;break;case 15:printf("\n");fprintf(fa2,"\n");break;case 16:t=t+1;printf("?");fprintf(fa2,"?");scanf("%d",&s[t]);fprintf(fa2,"%d",s[t]);break;}break;case lod: t=t+1;s[t]=s[base(i.l,&b,s)+i.a];break;case sto: s[base(i.l,&b,s)+i.a]=s[t]; /*ptrintf("%d",s[t])*/t=t-1;break;case cal: s[t+1]=base(i.l,&b,s); /*generate new block mark */ s[t+2]=b;s[t+3]=p;b=t+1;p=i.a;break;case ini:t=t+i.a;break;case jmp:p=i.a;break;case jpc:if (s[t]==0) p=i.a;t=t-1;break;}}while(p!=0);f close(fa2);}main( ){i nt m=0,n=0;c har *declbeg[ ]={"constsym","varsym","procsym",NULL};c har *statbeg[ ]={"beginsym","callsym","ifsym","whilesym",NULL};c har *facbeg[ ]={"ident","number","lparen",NULL};c har *tempset[ ]={"period","constsym","varsym","procsym",NULL};d eclbegsys=(struct node *)malloc(sizeof(struct node));s tatbegsys=(struct node *)malloc(sizeof(struct node));f acbegsys=(struct node *)malloc(sizeof(struct node));t empsetsys=(struct node *)malloc(sizeof(struct node));w hile(declbeg[m]!=NULL)declbegsys->pa[n++]=declbeg[m++];d eclbegsys->pa[n]=NULL;m=0;n=0;w hile(statbeg[m]!=NULL)statbegsys->pa[n++]=statbeg[m++];s tatbegsys->pa[n]=NULL;m=0;n=0;w hile(facbeg[m]!=NULL)facbegsys->pa[n++]=facbeg[m++];f acbegsys->pa[n]=NULL;m=0,n=0;w hile(tempset[m]!=NULL)tempsetsys->pa[n++]=tempset[m++];t empsetsys->pa[n]=NULL;i f((fa1=fopen("fa1.txt","w"))==NULL){printf("Cannot open file\n");exit( 0 );}p rintf("Input file?\n");f printf(fa1,"Input file?\n");s canf("%s",fname);f printf(fa1,"%s",fname);i f((fin=fopen(fname,"r"))==NULL){printf("Cannot open file according to given filename\n");exit( 0 );}p rintf("list object code?\n");s canf("%s",fname);f printf(fa1,"list object code?\n");i f (fname[0]=='y')listswitch=true;e lselistswitch=false;e rr=0;c c=1; cx=0; ll=0;c h=' ';g etsym( );i f((fa=fopen("fa.txt","w"))==NULL){printf("Cannot open fa.txt file\n");exit( 0 );}i f((fa2=fopen("fa2.txt","w"))==NULL){printf("Cannot open fa2.txt file\n");exit( 0 );}b lock(0,add(statbegsys,tempsetsys));f close(fa);f close(fa1);i f (strcmp(sym,"period")!=0)error(9);i f (err==0)interpret( );elseprintf("%d errors in PASCAL program\n",err);f close (fin);}。
编译原理实验 词法分析&语法分析程序
编译原理实验词法分析程序实验一:词法分析程序1、实验目的从左至右逐个字符的对源程序进行扫描,产生一个个单词符号,把字符串形式的源程序改造成单词符号形式的中间程序。
2、实验内容表C语言子集的单词符号及内码值单词符号种别编码助记符内码值while 1 while --if 2 if --else 3 else --switch 4 switch --case 5 case --标识符 6 id id在符号表中的位置常数7 num num在常数表中的位置+ 8 + --- 9 - --* 10 * --<= 11 relop LE< 11 relop LT== 11 relop LQ= 12 = --; 13 ; --输入源程序如下if a==1 a=a+1;else a=a+2;输出对应的单词符号形式的中间程序3、实验过程实验上机程序如下:#include "stdio.h"#include "string.h"int i,j,k;char s ,a[20],token[20];int letter(){if((s>=97)&&(s<=122))return 1;else return 0;}int Digit(){if((s>=48)&&(s<=57))return 1;else return 0;}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(){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;else return 0;}void main(){printf("please input you source program,end('#'):\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!='#');i=1;memset(token,0,sizeof(char)*10);j=0;get();while(s!='#'){if(s==' '||s==10||s==13)get();else{switch(s){case'a':case'b':case'c':case'd':case'e':case'f':case'g':case'h':case'i':case'j':case'k':case'l':case'm':case'n':case'o':case'p':case'q':case'r':case's':case't':case'u':case'v':case'w':case'x':case'y':case'z':while(Digit()||letter()){token[j]=s;j=j+1;get();}retract();k=lookup();if(k==0)printf("(6,%s)\n",token); elseprintf("(%d,null)\n",k); break;case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':case'8':case'9':while(Digit()){token[j]=s;j=j+1;get();}retract();printf("(%d,%s)\n",7,token); break;case'+':printf("(+,null)\n"); break;case'-':printf("(-,null)\n"); break;case'*':printf("(*,null)\n"); break;case'<':get();if(s=='=')printf("(relop,LE)\n"); else{retract();printf("(relop,LT)\n");}break;case'=':get();if(s=='=')printf("(relop,EQ)\n"); else{retract();printf("(=,null)\n");}break;case';':printf("(;,null)\n"); break;default:printf("(%c,error)\n",s);break;}memset(token,0,sizeof(char)*10);j=0;get();}}}4、实验结果实验结果分析:if是关键字,对应种别编码为2,输出(2,null)a是标识符,对应种别编码为6,值为a,输出(6,a)==的助记符是relop,内码值为LE,输出(relop,LE)1是常数,对应种别编码为7,值为1,输出(7,1)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)1是常数,对应种别编码为7,值为1,输出(7,1);是语句结束符号,直接输出(;,null)else是关键字,对应种别编码为3,输出(3,null)a是标识符,对应种别编码为6,值为a,输出(6,a)=是赋值符号,直接输出,(=,null)a是标识符,对应种别编码为6,值为a,输出(6,a)+是运算符,直接输出(=,null)2是常数,对应种别编码为7,值为2,输出(7,2);是语句结束符号,直接输出(;,null)#是输入结束标志编译原理实验语法分析程序实验二:语法分析程序1、实验目的:将单词组成各类语法单位,讨论给类语法的形成规则,判断源程序是否符合语法规则3、实验内容:给定文法:G[E]:E→E+E|E-E|E*E|E/E|(E)E→0|1|2|3|4|5|6|7|8|9首先把G[E]构造为算符优先文法,即:G’[E]:E→E+T|TT→T-F|FF→F*G|GG→G/H|HH→(E)|i得到优先关系表如下:+ - * / i ( ) # + ·><·<·<·<·<··>·> - ·>·><·<·<·<··>·> * ·>·>·><·<·<··>·> / ·>·>·>·><·<··>·>i ·>·>·>·>·>·>( <·<·<·<·<·<·=) ·>·>·>·>·>·> # <·<·<·<·<·<·=构造出优先函数+ - * / i ( ) #f 6 8 10 12 12 2 12 2g 5 7 9 11 13 13 2 2要求输入算术表达式:(1+2)*3+2*(1+2)-4/2输出其对应的语法分析结果4、实验过程:上机程序如下:#include "stdio.h"#include "string.h"char a[20],optr[10],s,op;int i,j,k,opnd[10],x1,x2,x3;int operand(char s){if((s>=48)&&(s<=57))return 1;else return 0;}int f(char s){switch(s){case'+':return 6;case'-':return 8;case'*':return 10;case'/':return 12;case'(':return 2;case')':return 12;case'#':return 2;default:printf("error");}}int g(char s){switch(s){case'+':return 5;case'-':return 7;case'*':return 9;case'/':return 11;case'(':return 13;case')':return 2;case'#':return 2;default:printf("error");}}void get(){s=a[i];i=i+1;}void main(){printf("请输入算数表达式,并以‘#’结束:\n");i=0;do{scanf("%c",&a[i]);i++;}while(a[i-1]!='#');i=0;j=0;k=0;optr[j]='#';get();while((optr[j]!='#')||(s!='#')){if(operand(s)){opnd[k]=s-48;k=k+1;get();}else if(f(optr[j])<g(s)){j=j+1;optr[j]=s;get();}else if(f(optr[j])==g(s)){if(optr[j]=='('&&s==')'){j=j-1;get();}else if(optr[j]=='('&&s=='#'){printf("error\n");break;}else if(optr[j]=='#'&&s==')'){printf("error\n");break;}}else if(f(optr[j])>g(s)){op=optr[j];j=j-1;x2=opnd[k-1];x1=opnd[k-2];k=k-2;switch(op){case'+':x3=x1+x2;break;case'-':x3=x1-x2;break;case'*':x3=x1*x2;break;case'/':x3=x1/x2;break;}opnd[k]=x3;k=k+1;printf("(%c,%d,%d,%d)\n",op,x1,x2,x3);}else{printf("error\n");break;}}if(j!=0||k!=1)printf("error\n");}5、实验结果:实验结果分析:(1+2)*3+2*(1+2)-4/2#因为‘)’优先级大于‘*’,先计算1+2=3,并输出(+,1,2,3)原式变为:3*3+2*(1+2)-4/2#因为‘*’优先级大于‘+’,先计算3*3=9,并输出(*,3,3,9)原式变为:9+2*(1+2)-4/2#因为‘)’优先级大于‘-’,先计算1+2=3,并输出(+,1,2,3)原式变为:9+2*3-4/2#因为‘*’优先级大于‘-’,先计算2*3=6,并输出(*,2,3,6)原式变为:9+6-4/2#因为‘/’优先级大于‘#’,先计算4/2=2,并输出(/,4,2,2)原式变为:9+6-2#因为‘-’优先级大于‘#’,先计算6-2=4,并输出(-,6,2,4)原式变为:9+4#因为‘+’优先级大于‘#’,计算9+4=13,并输出(+,9,4,13)原式变为13#优先级等于#,跳出while循环,运算结束!。
词法分析程序的设计与实现
词法分析程序的设计与实现方法1:采用C作为实现语言,手工编制一.文法及状态转换图1.语言说明:C语言有以下记号及单词:(1)标识符:以字母开头的、后跟字母或数字组成的符号串。
(2)关键字:标识符集合的子集,该语言定义的关键字有32个,即auto,break,case,char,const,continue,default,do,double,else,enum, extern,float,for,goto,if,int,long,register,return,short,signed,static, sizeof,struct,switch,typedef ,union,unsigned ,void, volatile和while。
(3)无符号数:即常数。
(4)关系运算符:<,<=,==,>,>=,!=。
(5)逻辑运算符:&&、||、!。
(6)赋值号:=。
(7)标点符号:+、++、-、--、*、:、;、(、)、?、/、%、#、&、|、“”、,、.、{}、[]、_、^等(8)注释标记:以“/*”开始,以“*/”结束。
(9)单词符号间的分隔符:空格。
2.记号的正规文法:仅给出各种单词符号的文法产生式(1)标识符的文法id->letter ridrid->ε|letter rid|digit rid(2)无符号整数的文法digits->digit remainderremainder->ε|digit remainder(3)无符号数的文法num->digit num1num1->digit num1|. num2|E num4|εnum2->digit num3num3->digit num3|E num4|εnum4->+digits|-digits|digit num5digits->digit num5num5->digit num5|ε(4)关系运算符的文法relop-> <|<=|==|>|>=|!=(5)赋值号的文法assign_op->=(6)标点符号的文法special_symbol->+|-|*|%|#|^|(|)|{|}|[|]|:|;|”|?|/|,|.& (7)逻辑运算符的文法logic->&&| || | !(8)注释头符号的文法note->/starstar->*3.状态转换图其中,状态0是初始状态,若此时读入的符号是字母,则转换到状态1,进入标识符识别过程;如果读入的是数字,则转换到状态2,进入无符号数识别过程;……;若读入的符号是/,转换到状态11,再读入下一个符号,如果读入的符号是*,则转换到状态12,进入注释处理状态;如果在状态0读入的符号不是语言所定义的单词符号的开始字符,则转换到状态13,进入错误处理状态。
实验一 编写词法分析程序
实验一编写词法分析程序1 实验类型设计型实验,4学时。
2 实验目的通过设计、调试词法分析程序,掌握词法分析程序的设计工具,即有穷自动机,进一步理解自动机理论;掌握文法转换成自动机的技术及有穷自动机实现的方法;会确定词法分析器的输出形式及标识符与关键字的区分方法;加深对课堂教学的理解,提高词法分析方法的实践能力。
3 背景知识词法分析作为相对独立的阶段来完成(对源程序或中间结果从头到尾扫描一次,并作相应的加工处理,生成新的中间结果或目标程序)。
在词法分析过程中,编译程序从外部介质中读取源程序文件中的各个字符,为正确地识别单词,有时还需进行超前搜索和回退字符等操作。
因此,为了提高读盘效率和便于扫描器进行工作,通常可采用缓冲输入的方案,即在内存中设置一个适当大小的输入缓冲区,将磁盘上的源程序字符串分批送入该缓冲区中,供扫描器进行处理。
词法分析程序的一般设计方案是:1、程序设计语言词法规则⇒正则文法⇒ FA;或:词法规则⇒正则表达式⇒ FA;2、NFA确定化⇒ DFA;3、DFA最小化;4、确定单词符号输出形式;5、化简后的DFA+单词符号输出形式⇒构造词法分析程序。
从设计方案可知,要构造词法分析程序,必须掌握以下三个知识点:文法、正则表达式和FA。
文法与语言的形式定义如下:一个形式文法G 是下述元素构成的一个元组(V N,V T,P,S )。
其中:1、V T—非空有限的终结符号集,即Σ;终结符:一个语言不可再分的基本符号。
2、V N—非空有限的非终结符号集;非终结符:也称语法变量,用来代表语法范畴。
一个非终结符代表一个一定的语法概念,是一个类(集合)记号,而不是一个体记号。
3、S —开始符号/识别符号,S∈V N;4、P —产生式规则集(或叫规则或生成式或重写规则);产生式:形如α → β或α ::= β的表达式,其中α为左部,β为右部。
α∈(V T∪V N)+且至少含一个V N;β∈(V T∪V N)*。
编译原理词法分析和语法分析报告+代码(C语言版)
编译原理词法分析和语法分析报告+代码(C语言版)-CAL-FENGHAI.-(YICAI)-Company One1信息工程学院实验报告(2010 ~2011 学年度第一学期)姓名:柳冠天学号:2081908318班级:083词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符: = + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(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)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
编译原理词法分析和语法分析报告+代码(C语言版)
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:输入:所给文法的源程序字符串。
输出:二元组(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)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
编译原理词法分析和语法分析报告+代码[C语言版]
词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求2.1 待分析的简单的词法(1)关键字:begin if then while do end所有的关键字都是小写。
(2)运算符和界符:= + - * / < <= <> > >= = ; ( ) #(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:ID = letter (letter | digit)*NUM = digit digit*(4)空格有空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.2 各种单词符号对应的种别码:表2.1 各种单词符号对应的种别码2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(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)……三、词法分析程序的算法思想:算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
3.1 主程序示意图:主程序示意图如图3-1所示。
其中初始包括以下两个方面:⑴关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};是图3-1(2)程序中需要用到的主要变量为syn,token和sum3.2 扫描子程序的算法思想:首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
实验一手工编写简易词法分析程序
编译原理实验报告日期:班级:题目:组员:1实验目的及要求1.通过设计、编写、调试一个具体的词法分析程序,加深对词法分析原理的理解。
2.掌握在对程序设计语言源程序进行扫描的过程中, 将其分解为各类单词的词法分析方法。
2实验平台Windows + VC + Win32 Console3实验步骤1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。
通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
4实验内容4.1 实现下述功能, 并将分析结果保存在文件中. (既可以参考范例程序, 也可以独立完成)程序输入/输出示例:输入一段C语言程序,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、界符。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)输入源程序示例:main ( ){int a , b =10;int c ;c = a + b * 20;}输出固定表格如下输出动态表格如下运算符表44.2 程序:#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 return 0;}int IsKey(char *Word){ //识别关键字函数int m,i;for(i=0;i<9;i++){if((m=strcmp(Word,Key[i]))==0){if(i==0)return 2;elsereturn 1;}}return 0;}void scanner(FILE *fp){ //扫描函数char Word[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("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│1\t│1\t\t│\n",Word);//不是关键字else if(c==2)printf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│2\t│3\t\t│\n",Word);elseprintf("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│3\t│1\t\t│\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("\t\t├───────┼───┼───────┤\n\t\t │%s\t\t│3\t│1\t\t│\n",Word);}else //开始判断的字符不是字母也不是数字{Word[0]=ch;switch(ch){case'[':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│7\t\t│\n",Word); break;case']':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│9\t\t│\n",Word); break;case'(':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│3\t\t│\n",Word); break;case')':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│4\t\t│\n",Word); break;case'{':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│5\t\t│\n",Word); break;case'}':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│6\t\t│\n",Word); break;case',':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│1\t\t│\n",Word); break;case'"':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│8\t\t│\n",Word); break;case';':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│5\t│2\t\t│\n",Word); break;case'+':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);//运算符"+="}else if(ch=='+'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"++"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│1\t\t│\n",Word); //判断结果为"+"}break;case'-':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); }else if(ch=='-'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"--"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│2\t\t│\n",Word); //判断结果为"-"}break;case'*':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│3\t\t│\n",Word);break;case'/':printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│4\t\t│\n",Word);break;case'!':case'=':ch=fgetc(fp);if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│5\t\t│\n",Word);}break;case'<':ch=fgetc(fp);Word[1]=ch;if(ch=='='){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为运算符"<="}else if(ch=='<'){printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);//判断结果为"<<"}else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word); //判断结果为"<"}break;case'>':ch=fgetc(fp);Word[1]=ch;if(ch=='=') printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}break;case'%':ch=fgetc(fp);Word[1]=ch;if(ch=='='){ printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t\t│4\t│6\t\t│\n",Word);}if(IsAlpha(ch)) printf("\t\t├───────┼───┼───────┤\n\t\t│%s\t│类型标识符\t│ \t│\n",Word);else {fseek(fp,-1,1);printf("\t\t├───────┼───┼───────┤\n\t\t│%s \t│取余运算符\t│ \t\n",Word);}break;default:printf("\t\t├───────┼───┼───────┤\n\t\t│无法识别字符! \t\t\t\t │\n"); break;}}}main(){char in_fn[30]; //文件路径FILE *fp;printf("\n请输入源文件名(包括路径和后缀名):");while(true){gets(in_fn);//scanf("%s",in_fn);if((fp=fopen(in_fn,"r"))!=NULL) break; //读取文件内容,并返回文件指针,该指针指向文件的第一个字符else printf("文件路径错误!请重新输入:");}printf("\n**************************** 单词类别表****************************\n");printf("\t\t┌───────┬───────┐\n\t\t│单词类型\t│单词种别\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│标识符 \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│保留字 \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│常量 \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│运算符 \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│分界符 \t│5 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 保留字表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│保留字 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│int \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│float \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│main \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│printf \t│4 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 运算符表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│算符 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│+ \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│- \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│* \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│/ \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│= \t│5 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│其他 \t│6 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 分界符表******************************\n");printf("\t\t┌───────┬───────┐\n\t\t│界符 \t│地址指针\t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│, \t│1 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│; \t│2 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│( \t│3 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│) \t│4 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│{ \t│5 \t│\n",Word);printf("\t\t├───────┼───────┤\n\t\t│} \t│6 \t│\n",Word);printf("\t\t└───────┴───────┘\n",Word);printf("\n**************************** 词法分析结果如下******************************\n");printf("\t\t┌───────┬───┬───────┐\n\t\t│单词名称\t│类别\t│地址指针\t│\n",Word);do{ch=fgetc(fp);if(ch=='#') break; //文件以#结尾,作为扫描结束条件else if(ch==' '||ch=='\t'||ch=='\n'){} //忽略空格,空白,和换行else{fseek(fp,-1,1); //回退一个字节开始识别单词流scanner(fp);}}while(ch!='#');printf("\t\t└───────┴───┴───────┘\n",Word);return(0);}5实验结果5.1 解析源文件:main ( ){int a , b =10;int c ;c = a + b * 20;}#5.2 解析结果:6实验总结分析在本次实验,使我们再次浏览了有关C语言的一些基本知识,特别是对文件,字符串进行基本操作的方法。
词法分析与语法分析程序设计
实验三词法分析与语法分析程序设计一.实验目的基本掌握计算机语言的词法分析程序和语法分析程序的设计方法。
二.实验要求、内容及步骤实验要求:1.根据以下的正规式,画出状态图;标识符:<字母>(<字母>|<数字字符>)*关键字:if then else while do十进制整数:0 | (1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)* 运算符和分隔符:+ - * / > < = ( ) 。
2.根据状态图,设计词法分析函数int scan( ),从键盘读入数据,分析出一个单词。
3.对于只含有+、*运算的算术表达式的如下文法,编写相应的语法分析程序,要求用LL(1)分析表实现,并以id+id*id为例进行测试:E —> TE′E′—> +TE′|εT —> FT′T′—> *FT′|εF —>(E)| id实验步骤:1.根据状态图,设计词法分析算法;2.采用C++语言,实现该算法;3.调试程序:输入一组单词,检查输出结果;4.编制给定文法的非递归的预测分析程序,并加以测试。
三.实验设备计算机、Windows 操作系统、Visual C++ 程序集成环境。
四.实验原理1. 词法分析器读入输入串,将其转换成将被语法分析器分析的词法单元序列。
产生下述小语言的单词序列。
这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:单词符号种别编码助记符内码值DIMIFDO STOP END标识符常数(整)=+***,()1234567891011121314$DIM$IF$DO$STOP$END$ID$INT$ASSIGN$PLUS$STAR$POWER$COMMA$LPAR$RPAR------内部字符串标准二进形式------对于这个小语言,有几点重要的限制:首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。
所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。
编写词法分析程序
实验报告课程名称:编译原理__ 项目名称:编写词法分析程序姓名:专业:计算机科学与技术_ 班级:2011级学号:同组成员:1注:1、实验准备部分包括实验环境准备和实验所需知识点准备。
2、若是单人单组实验,同组成员填无。
二、实验过程记录2:1、实验目的给出PL/0文法规范,要求编写PL/0语言的词法分析程序,深刻理解词法分析的整个过程,提高词法分析方法的实践能力2、实验内容对PL/0语言作如下功能扩充:(1)扩充条件语句的功能使其为:if<条件>then <语句>[else <语句>](2)增加repeat语句,格式为:repeat<语句>{;<语句>}until<条件>3、实验要求要求:(1)给出扩充后的语法图和EBNF的语法描述。
(2)修改PL/0的编译系统,使它能正确编译扩充后的PL/0程序。
4、实验步骤:(1)整型一维数组,数组的定义格式为:VAR<数组标识名>(<下界>:<上界>)其中上界和下界可以是整数或者常量标识名。
访问数组元素的时候,数组下表是整型的表达式,包括整数、常量或者变量和他们的组合。
(2)扩充条件语句,格式为:<条件语句> ::= IF<条件>THEN<语句> [ELSE<语句>]扩充条件语句的语法图为:2注:实验过程记录要包含实验目的、实验原理、实验步骤,页码不够可自行添加。
(3)增加repeatT语句,格式为:<复合语句> ::= repeat<语句>UNTL<条件>扩充repeat语句的语法图为:源程序代码:#include<stdio.h>#include<string.h>inti,j,k,sign,number,flag,run,sum,autuor;charch;charwords[10]={""};charprogram[500];intScan(charprogram[]){char*keywords[39]={ "auto","default","do","extern","goto","int","short","static","struct","switch", "typedef","void","break","case","char","const","continue","double","else","enum ","float","for","if","long","register","return","signed","zhaixinyuan","sizeof" ,"union","unsigned","volatile","while","main","printf","scanf","include","defin e","string"};number=0;flag=0;j=0;ch=program[i++];while((ch=='')||(ch=='\r')||(ch=='\n'))ch=program[i++];if((ch>='a')&&(ch<='z')){while((ch>='a')&&(ch<='z')){words[j++]=ch;ch=program[i++];}i--;words[j++]='\0';for(k=0;k<38;k++)if(strcmp(words,keywords[k])==0)keywords[k])==0{sign=k+1;flag=1;if(k==27)autuor=1;break;}if(flag==0){sign=100;运行结果:3注:1、实验小结应包含实验所需知识点和实验方法的总结,实验心得体会等。
词法分析程序
00201企业招聘真题陈利娥搜集整理CHANGES.txt包含了我公司开发人员对一个代码库的修改历史。
请用C#来编写一个词法分析(Parse)程序来提取以下要求的字段组成的修改纪录,并将结果写入一个或多个文件中。
字段之间(field)用'|'分隔。
每个记录之间用'#'分隔具体分析的结果要求如下:a) 每个记录应包含下列字段:Change ID: 给每项修改记录分配一个唯一的序号。
Changed Date: 提取原始修改记录中的MM/DD/YYYY格式的日期。
Changed By: 提取原始修改记录中紧跟在日期之后的开发人员名字。
Summary: 提取原始修改记录中由'*)'给出的修改摘要。
Description: 提取原始修改记录中由'Description:'给出的修改说明。
Purpose: 提取原始修改记录中由'Purpose:'给出的修改目的说明。
Changed Files: 提取原始修改记录中由'Changed Files:'给出的修改文件列表。
Added Files: 提取原始修改记录中由'Added Files:'给出的新增文件列表。
输出类似如下的表格:b) 请用'*)'作为一项修改的标示(而不是日期)。
因为一个开发人员在同一天可以做多项修改。
在同一日期下的多个'*)'应被分割成多个修改纪录。
例如:c) 在"Description:"下可能会有多项由"-"给出的说明项CHANGES.txt文档内容如下:Change History:11/12/2004, Simon*) Added this file.11/16/2004, Johnason*) Support saving TDF fileChanged Files: SystemConfig.cpp/hAdded files: TDF.cpp/hDescription:- Add NIST_SUPPORT in cls_cls.cfg- Add cls_nist.cfg. A sample and explaination is put in misc- Add a new class CTDF, which calls some functions of lscvt.liband tdf.lib.Comments:- CTDF need to be enhanced. The basic idea is to use a base class foriniting, reading existing TDF file and saving repacked TDF file. Nobinding data (a virtual function) in base class. Three new class willbe derived from the base class to bind three kinds of data: fromWinCtrlSet, cls_nist.cfg, images. Then ClsMain and ClsDataEntry cancall different class as they required.11/23/2004, Johnason*) Florida payment interfaceChanged files: SystemConfig.cpp/hDescription:- It map FirstName, LastName, MidName, SufName before. Now it only mapthe Name field.*) Flat App VersionChanged files: SystemConfig.cpp/hDescription:- Read nFlatAppVersion in Cls_cls.cfg12/01/2004, Johnason*) Add code to delete transactions from nist_ipa, nist_ipa_pm, nist_ipa_print, nist_ipa_print_pmChanged files:- SystemTrans.cpp- SystemTransNew.cpp- SystemTrans.hDescription:- Add one new function: CLSTransDeleteException- Call this new function in CLSTransDeleteRec() and CLSTransNewDeleteRec() - In this case, these four tables should not be put in INFO_TABLE. Beforewe put them into it, which will cause a bug: When the transaction hasexception and has been scanned, the exception will be removed if userviews demo and saves it.12/02/2004, Johnason*) Add config item FLAT_PHOTO in cls_scan.cfgChanged files:- SystemConfig.cpp- SystemDb.hDescription:- Add code to read FLAT_PHOTO in cls_scan.cfg.12/02/2004, Eric*) Updated logic of checking FBI responsesChanged files:- DaoQTransNew.cppDescription:- New logic to check FBI response12/06/2004, Eric*) Updated CLSTransInsertEmailRec()Changed files:- SystemTrans.cppDescription:- The variable szTblRev needs memset12/08/2004, Eric*) Added new SEND_OPTION to cls_cls.cfgDescription:- Check whether all mandatory data have been captured and transactionis ready for sending out- SEND_OPTION = 11111100DataEntry|TP|Palm|Photo|Sign|DemoImage|Reserved|Reserved Changed files: SystemConfig.cpp/h, SystemTransNew.cpp/h12/09/2004, Eric*) Added new CLEAN_WHEN_LOGOFF to cls_cls.cfgThis is to delete all completed transactions when log-off(for USSS - Child)Changed files:- SystemConfig.cpp/h12/10/2004, Johnason*) Add a config item PALM_CHECK_VERSION in cls_scan.cfgChanged files: SystemConfig.cpp/hDescription:The default value is 0.If it is set to 2, use the new algorithm of palm sequence check.12/11/2004, Johnason*) Add severl parameters for palm sequence check in cls_scan.cfgChanged files: SystemConfig.cpp/hDescription:Add them for new algorithm of palm sequence checkDefault values are 012/13/2004, Johnason*) Add CHECK_IMAGE_BEFORE_SCAN in cls_scan.cfgChanged files: SystemConfig.cpp/hDescription:Add ClsCfgScan.bCheckImageBeforeScan for CHECK_IMAGE_BEFORE_SCAN.The default value is false.*) Add a message in cls_msg.cfg. it is use to show a message to ask userwhether ignore the existing images.Changed files: LSGlobal.cppDescription: Enlarge CLSCfgMsg size to 39, and add the new message item.12/13/2004, Johnason*) Fix a logic problem in FilterChanged Files: SystemTransNew.cpp, DaoQTransNew.cppPurpose:- Filter didn't work for the transactions that came from bridge server.- Reason is in the Filter SQL statement, it put the wrong conditionorder for AND and OR statement.Description:- Change code in LoadNewQTrans, CLSTransNewLoadQ functions- Add parenthesises for condition statement and adjust the sequence.12/16/2004,Simon*) Added a new function CLSIoLogSprintf to support flexible loggingcapability which introduces the dependency on include/af_log.h andgdslib/gd_pub.h.Changed files: SystemIo.cpp/h12/17/2004, Eric*) Added a new config item to cls_scan.cfg, FLAT_PALM_OPTIONALChanged files: SystemConfig.cpp/h*) Added a new config item to cls_scan.cfg, EXCEPTION_ALWAYSAlways save excpetion data (For Mexico)Changed files: SystemConfig.cpp/h*) Added a new function call CLSDbDeleteRecord()Changed files: SystemDb.cpp/h01/06/2005, Simon*) Changed data structure CLS_CFG_CALLTAB and functions CLSCfgLoadCalltab() and CLSIoCallApp() to support application module in DLL mode;*) Added function CLSCfgGetFileName to get configuration file in order toreduce redundant code;*) Added cls_*.cfg for reference.Changed Files: SystemConfig.cpp/h, SystemIo.cpp/hAdded Files: cls_*.cfgDescription:- New changes keep compatible with previous installations. Only whenthe binary extension is 'dll', the system will try to load the givenDLL at runtime and get the function 'StartDllModule' to launch theDLL module.01/07/2005, Simon*) Added new configuration item UID_POLICY in cls_login_ldap.cfgto control behavior when uid cannot obtained from ActiveDirectory.Purpose: This change is to accommodate changes made in coldapi to eliminiate the requirement of maintaining UID by end users such as USSS.Changed Files: SystemConfig.cpp/h, cls_login_ldap.cfg01/10/2005, Eric*) Increased CLS_TRANS_NEWQ_TXSNO_LEN to 30 in SystemTransNew.h, to enlarge trans_no buffer to 30 char long*) Update CLSCfgGetAutoTransNo() in SystemConfig.cpp, to support auto serial as 13 char long01/18/2005, Simon*) Fixed function prototypes of StartDllModule for runtime loading.Changes Files: SystemIo.h。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
二、实验设计
设计原理
“确定的有穷机” :在当前状态下,输入一个符号,有穷自动机将转换到唯一的一个后 继状态; 通过对整个文法构造一个总的 DFA, DFA 的每个终态识别一个单词, 从初始状态出发, 每读入一个单词,切换到下一个状态,期间要是读到非法符号则报错处理。
设计方法
1. 2. 3. 4. 5. 6. 根据 TEST 语言的词法规则,分别写出每条规则的正则文法或者正则表达式; 将每一个正则文法或者正则表达式转换为 NFA; 将多个 NFA 合并; 确定化 NFA 并化简; 确定单词分类、单词输出方案; 编写词法分析程序。
5
3.
双分界符处理 读到一个字符,如果是双分界符,再向前读一个符号,如果是‘=’ ,则输出双分 界符,如果不是‘=’ ,则输出是但分界符。这里有一个特殊情况,就是‘! ’不是一个 单分界符,如果按照之前处理则‘! ’会变成合法的单分界符,我做的处理方式是,读 到的第一个字符如果是‘! ’ ,那么再读一个字符,如果不是‘=’就输出非法字符‘! ’ 。 4. keyword 匹配 在 TEST 语言文法规则中 keyword 是 ID 的子集, 当识别了 ID 时, 就识别了 keyword; 这里做的处理方式是把所有 keyword 字存入一个字符串数组中,当识别了一个 ID 单词 的时候,就把这个 ID 和 keyword 数组的元素挨个比较,如果 ID 在 keyword 数组中,就 把其当成 keyword 输出,如果不在,就把其当成 ID 输出。 5. 注释处理 TEST 语言中注释采取删除的方式,当注释不匹配的时候要输出不匹配的信息,处 理方式为,读到一个字符如果为‘/’,再读一个字符,如果为‘*’ ,进入注释,如果不 是‘*’ ,则把‘/’作为单分界符输出,进入注释后,读入任意非‘*’字符都是直接往 下读字符,如果读到了‘*’ ,把当前状态记录,再读一个字符,如果是‘*’ ,停留在当 前状态,如果是‘/’ ,退出注释,如果是其他字符,则跳到刚进入注释状态,继续往下 扫描字符。 6. 注释匹配 当进入注释后,并没有注释结束标志,这时就是注释不匹配了。 处理方式: 当进入注释如果不退出注释的话, 则注释开始标记后面的代码内容 全部都是注释,一直到文件结尾,我设置一个 bool 变量 IsNote,当 IsNote 为 true 时,则处于注释状态中,当 IsNote 为 false 则退出注释状态,在词法分析程序结束 末尾判断 IsNote,如果为真就输出注释不匹配。
数字|字母 1 字母 数字
ε
非0整数 0
2
ε
+|-|*|?|(|)|{|}|,|;
0
7 ε =
/
>|<|!|=
/ 4 *
3 5 * 6
4.
NFA 确定化
β=>|<|!|=
注:α=+|-|*|?|(|)|{|}|,|; 字母 0 q0 1,7 q3
非零数字 2,7 q2
α 7 q3
0
β
/ 4 q5
数字
=
*
非*字符
7 q3
3,7 q4
1,7 q1 2,7 q2 7 q3
1,7 q3
1,7 q3 2,7 q2
3,7 q4
7 q3
4
q5
3
5q6
5 6
q6 q7 7
6q7
5q6
DFA:
字母|数字 q1 字母 q0 非0数字 q2 0 +|-|*|?|(|)|{|}|; >|<|!|= q3 q4 q5 * / 非*字符 q6 * q7 数字
注释符:/*|*/
2.
正则文法或者正则表达式转换为 NFA; a) 标识符:
字符
0 字母 1 数字 ε 2
b)
无符号整数:
0 非零数字
0 ε
1
2
数字
c) 分界符:
0
d) 运算符:
(|)|;|{|}
1
0 <|>|!
+|-|*|/|= = 1
2
ε
e)
注释符:
2
1
*
0 /
/
3 *
2
3.
将多个 NFA 合并;
问题及解决方案
1. 空格、制表符、换行的处理 词法分析过程中的空格、制表符、换行是不可看见的,但是确是无关符号,不是非 法符号,遇到此类字符直接跳过。 2. 单个字符组成的 ID 或者 NUM 处理 往下读一个字母,如果是空格、制表符、换行就回到初始状态,输出单个 ID 或者 NUM;如果是其他字符,切换到下一个状态识别。
编译原理实验报告
实验名称: 实验类型: 指导教师: 姓 学 名: 号:
编写词法分析程序 设计型 蒋 范 东六 E301 勇 良 5120140979
专业班级:计算机科学与技术 1402 班
ቤተ መጻሕፍቲ ባይዱ
实验地点: 实验成绩:
日期:
2016 年
4月
9日
实验一
一、实验目的
编写词法分析程序
1. 编写 TEST 语言的词法分析程序,输出其中的非法符号和合法符号,并将合法符号 分类后输出; 2. 加深对正则文法、正则表达式、有穷自动机的理解; 3. 掌握正则文法、正则表达式转化为 NFA,多个 NFA 合并 4. 在实验过程中, 对 C 语言文件操作知识的巩固, 熟悉编写程序过程中单步调试程序, 断点追踪,变量值检测过程。
/
5.
确定单词分类、单词输出方案; 输出格式为 :单词类别 单词值
其中合法单词存入 Lexfile 文件中,不合法单词在屏幕上输出 6. 编写词法分析程序(关键代码见附录)。
4
设计结果
开始
读字符 Y 字母? N 非0数字? N 0? N 单分界 符? N 双分界 符? Y !? Y N 读字符 =? N 输出 SINGLEWOR DS N 读字符 =? Y N 输出非法字 符! *? Y 读字符 Y Y 输出 doublewords 读字符 读字符 Y 输出数字0 读字符 Y NUM 读字符 Y 读字符 数字? N 输出NUM 字母或者 数字? KEYWORD S? 输出ID
Y
ID
N
N Y
输出 KEYWORDS
/
读字符
*? Y
Y
读字符
/?
N
输出 singleword
N
N
输出非法字 符
读字符
结束
程序流程框图
三、实验过程
程序编写基本思路
本程序分为两个文件,词法分析函数一个文件,主函数一个文件(负责传入文件需要做 词法分析的文件和输出文件的地址) 记录单词的字符串有两个 buffer1 和 buffer2,当读到一个字符符合单词匹配的时候放入 buffer1, 继续往下读字符放到 buffer1, 直到读到形成一个完整单词时, 把这个单词放入 buffer2, 以保证 buffer2 中始终存放的是一个单词;继续往下读字符,如果读到了非单词匹配字符, 输出 buffer2,清空 buffer1,buffer2 继续下面的单词匹配;如果读到的字符还能继续匹配, 那就一直读,并把读到的字符放入 buffer1 中,直到读到一个能再次匹配单词的字符,则把 buffer1 中内容放入 buffer2 中,继续往下读,如果不能读到的字符不能匹配当前单词,则输 出 buffer2,再把 buffer1 和 buffer2 清空,如此循环
设计过程
1. 每条规则的正则文法或者正则表达式: a) b) c) d) 标识符: (a|……|z|A|……|Z)(a|……|z|A|……|Z|0|……|9) 无符号整数: (1|……|9) (0|……|9)|0 分界符:(|)|;|{|}| 运算符:+|-|*|/|<|>|>=|<=|!=
1
e)