PL0语言词法分析程序.docx

上传人:b****4 文档编号:27118812 上传时间:2023-06-27 格式:DOCX 页数:18 大小:26.04KB
下载 相关 举报
PL0语言词法分析程序.docx_第1页
第1页 / 共18页
PL0语言词法分析程序.docx_第2页
第2页 / 共18页
PL0语言词法分析程序.docx_第3页
第3页 / 共18页
PL0语言词法分析程序.docx_第4页
第4页 / 共18页
PL0语言词法分析程序.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

PL0语言词法分析程序.docx

《PL0语言词法分析程序.docx》由会员分享,可在线阅读,更多相关《PL0语言词法分析程序.docx(18页珍藏版)》请在冰豆网上搜索。

PL0语言词法分析程序.docx

PL0语言词法分析程序

PL/0语言词法分析程序

  //这是我编译原理的一次作业,中间有许多不足之处希望大家指正

  /*编写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

  ======================

  CONSTA=10;

  VARB,C;

  PROCEDUREP;

  VARD;

  PROCEDUREQ;

  VARX;

  BEGIN

  READ(X);

  D:

=X;

  WHILEX

  DOCALLP;

  END;

  BEGIN

  WRITE(D);

  CALLQ;

  END;

  BEGIN

  CALLP;

  END.

  */

  /*programname:

chifufenxi*/

  /*作者:

小万QQ:

421404493*/

  /*date:

2004.10.11*/

  #include

  #include

  #include

  #include

  #include

  

  #defineN256//每一行的字符数不能超过256个

  

  charbuffer[N];//用作存放一行字符

  charword[20];//用作存放经过分析单词

  char*kword[13]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"};

  charktype[13]={'f','g','h','i','j','k','l','m','n','o','p','q','r'};

  intlen;//记录每一行的长度

  intcount=0;//用来记录行数

  voidwrite(char*wstr,charwc,FILE*wout)//将分析结果按照规则写入到文件

  {

  fputc('(',wout);

  fputs(wstr,wout);

  fputc(',',wout);

  fputc(wc,wout);

  fputc(')',wout);

  }

  intreadbuffer(FILE*fp)

  {

  charch;

  len=0;

  ch=fgetc(fp);

  while(!

feof(fp)&&ch!

='\n')//读取字符到缓冲区

  {

  buffer[len]=ch;

  ch=fgetc(fp);

  len++;

  }

  

  len--;//用来控制词法分析时行分析中字母的个数

  

  if(feof(fp))//标志文件是否结束

  return0;

  else

  return1;

  }

  voiderror(inttype)

  {

  if(type==1)

  printf("为无效字符,第%d行词法出错,标志符不能以数字开头\n",count);

  elseif(type==2)

  printf("第%d行词法出错,赋值符应为\:

\=\n",count);

  

  elseprintf("为无效字符,第%d行词法出错\n",count);

  }

  voidcheck(char*str,FILE*out);//声明函数,此函数用来分类单词

  voidfenxi(char*row,FILE*op)//此函数用来对每一行的单词进行语法分析

  {

  //printf("%d\n",count);

  intk=0;//用作控制临时存放单词的变量str0

  inti=0;//定义两个变量用作控制每一行是否结束,

  intferror=0;//用作出错标志

  charstr0[20];//临时存放单词的变量

  while(i<=len)

  {

  k=0;//将k置0

  strcpy(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;

  }

  else

  i--;

  }

  /*判断是否为数字*/

  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(intj=0;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(intch)判断标点符号*/

  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]=='-'||row[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(intj=0;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++;//使指针后移,取出下一个字母

  }

  }

  voidcheck(char*str,FILE*out)

  {

  

  

  if(isdigit(str[0]))/*如果第一个字符是数字那么整个单词都是数字组成的,即为常数*/

  {

  write(str,'d',out);//调用写函数将分好类的单词写入文件

  }

  

  if(isalpha(str[0]))/*如果第一个字符是字母,那么这个单词是标志符或关键字*/

  {

  intfyiyong=0;//用作标记这个单词是否已被分类

  /*以下判别是否是关键字*/

  for(intct=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]=='.'||str[0]=='#'||str[0]=='=')

  {

  write(str,str[0],out);

  }

  

  

  }

  voidmain()

  {

  count=1;

  charscfilename[20],rsfilename[20];//定义用来存放输入源文件和输出目标文件的名字

  printf("Pleaseinputyoursourcefilename:

");

  gets(scfilename);

  printf("Pleaseinputyourresultfilename:

");

  gets(rsfilename);

  FILE*fp,*op;

  fp=fopen(scfilename,"r");

  op=fopen(rsfilename,"w");

  if(fp)//打开文件成功后调用函数对源文件进行词法分析

  {

  while(readbuffer(fp))

  {

  fenxi(buffer,op);

  count++;//行加一

  }

  }

  else//whilethefilenotexist

  {

  printf("Yoursoucefilenotexist!

!

!

\n");

  exit(0);

  }

  fclose(fp);//closethefiles

  fclose(op);

  printf("ok!

");//outputthemarkofend

  getchar();

  }

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1