wfp11..c
Upload User: sgdz88
Upload Date: 2014-05-31
Package Size: 3k
Code Size: 6k
Development Platform:

Visual C++

  1. /************************************************************************
  2.  * 文件名 :test3.c
  3.  * 文件描述:预测分析法实现的语法分析器。分析如下文法:
  4.  *                      E->E+T | E-T | T
  5.  *                      T->T*F | T/F |F
  6.  *                             F->(E) | i 
  7.  *                      输入:每行含一个表达式的文本文件(#号结束)。
  8.  *                      输出:分析成功或不成功信息。
  9.  * 创建人:余洪周 <nick19842000.cublog.cn>  2006-12-16
  10.  * 版本号:1.0 
  11.  * 说明    :为了表示的方便采用了如下的所示表示方法:
  12.  *    A=E'  B=T'
  13.  *    非终结符:0=E 1=E'  2=T  3=T'  4=F  
  14.  *    终结符  :0=i  1=+  2=-  3=*  4=/  5=(  6=)  7=#
  15.  ***********************************************************************/
  16. #include <iostream.h>
  17. #include<stdio.h>
  18. #include<malloc.h>
  19. struct struCH{
  20. char  ch;
  21. struct  struCH *next;
  22. }struCH,*temp,*head,*shift,*top,*base;
  23. /*head指向线性链表的头结点,shift指向动态建成的结点
  24.  *top和base分别指向堆栈的顶和底
  25.  */
  26. FILE  *fp;
  27. char  curchar;   /*存放当前待比较的字符*/
  28. char  curtocmp;   /*存放当前栈顶的字符*/
  29. char   ch;
  30. int   right, i,j;
  31. int table[5][9]={ /*存储预测分析表,1为有产生式,0为无*/
  32. {1,0,0,0,0,1,0,0,0},
  33. {0,1,1,0,0,0,1,1,1},
  34. {1,0,0,0,0,1,0,0,0},
  35. {0,1,1,1,1,0,1,1,1},
  36. {1,0,0,0,0,1,0,0,0}}; 
  37. void main(int argc,char *argv[]){
  38. void puch(char ch);
  39. void pop();
  40. void doforpush(int t);
  41. void identify();
  42. int errnum=0, k=0, countchar=0, rownum;
  43. int m=0;
  44. int charerr=0; /*有非法字符时的开关控制量*/
  45. /*******************以只读方式打开文件*********************/
  46. if((fp=fopen(argv[1],"r"))==NULL){
  47. printf("ntCan not open file %s,or not exist it!n",argv[1]);
  48. exit(0);     /*文件不存在or打不开时,正常退出程序*/
  49. }
  50. else printf("ntSuccess open file: %sn",argv[1]); /*成功打开文件*/
  51. /******************遍历整个文件检测是否有非法字符********************/
  52. /*如果用while(!feof(fp))语言,将会多出一个字符而难以控制,
  53.  *所以这里采用先计算字符数量再遍历整个文件来检测其否有非法字符*/
  54. /*[1]计算文件中字符数量*/
  55. while(!feof(fp)){
  56. ch=getc(fp);  /*这里只是让指针往前移*/
  57. countchar++; /*统计文件中的字符数(包括换行符及文件结束符)*/
  58. }
  59. rewind(fp); /*将fp文件指针重新指向文件头处,以备后面对文件的操作*/
  60. if(countchar==0){ /*空文件*/
  61. printf("t%s is a blank file!n",argv[1]); 
  62. exit(0); /*正常退出本程序*/
  63. }
  64. /*[2]开始遍历文件*/
  65. while(k<(countchar-1)) {/*加换行符后countchar仍多一个,故减1*/
  66. ch=getc(fp);
  67. if(!(ch=='('||ch==')'||ch=='i'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='#'||ch=='n')){ 
  68. charerr=1;errnum++;/*charerror出错标记,errnum统计出错个数*/
  69. }
  70. k++;
  71. }
  72. rewind(fp); /*将fp文件指针重新指向文件头处,以备后面的建链表操作*/
  73. if(charerr==1){ /*文件中有非法字符*/
  74. printf("nt%d Unindentify characters in file %s n",errnum,argv[1]);
  75. exit(0); /*正常退出本程序*/
  76. }
  77. /*******************非空且无非法字符,则进行识别操作*****************/
  78. for(rownum=1;m<(countchar-1);rownum++) { /*识别所有行,rownum记录行号*/
  79. /* 初始变量及堆栈和 */
  80. right=1;
  81. /* '#''E'进栈 */
  82. base=malloc(sizeof(struCH));   /*初始化堆栈*/
  83. base->next=NULL;
  84. base->ch='#';
  85. temp=malloc(sizeof(struCH));
  86. temp->next=base;
  87. temp->ch='E';
  88. top=temp;                               /*栈顶指针top指向栈顶*/
  89. /*初始存放待识别的表达式的线性链表头*/
  90. shift=malloc(sizeof(struCH));
  91. shift->next=NULL;
  92. head=shift;
  93. /*读取一行形成线性链表*/
  94. ch=getc(fp);putchar(ch);m++;
  95. while(ch!='n'&&m<(countchar)){ /*行末or到文件尾。最后会读取文件结束符*/
  96. /*读取ch,读取存入链*/
  97. temp=malloc(sizeof(struCH));
  98. temp->ch=ch;
  99. temp->next=NULL;
  100. shift->next=temp;
  101. shift=shift->next;
  102. ch=getc(fp);
  103. if(m!=(countchar-1)) putchar(ch); /*不输出最后一次读取的文件结束符*/
  104. m++;
  105. }
  106. head=head->next; /*消去第一个空头结点,并使head指向非空线性链表头*/
  107. shift=head; /*shift指向头结点,以便后面识别操作*/
  108. putchar('n');
  109. identify(); /*开始识别一行*/
  110. if(!right)  /*错误提示:[文件名] Line [行号]:error expression!*/
  111. printf("%s  Line %d:t  error expression!n",argv[1],rownum);
  112. else /*正确提示:[文件名] Line [行号]:right expression!*/
  113. printf("%s  Line %d:t  right expression!n",argv[1],rownum);
  114. putchar('n');
  115. }/*end for*/
  116. printf("Completed!n");
  117. fclose(fp); /*关闭文件*/
  118. exit(0); /*正常退出程序*/
  119. /*入栈函数*/
  120. void push(char ch) {
  121. temp=malloc(sizeof(struCH));
  122. temp->ch=ch;
  123. temp->next=top;
  124. top=temp;
  125. }
  126. /*出栈函数*/
  127. void pop(void){
  128. curtocmp=top->ch;
  129. if(top->ch!='#')
  130. top=top->next;
  131. }
  132. /*根据数组下标计算的值找对应的产生式,并入栈*/
  133. void doforpush(int t){
  134. switch(t){
  135. case 0:push('A');push('T');break;
  136. case 5:push('A');push('T');break;
  137. case 11:push('A');push('T');push('+');break;
  138. case 12:push('A');push('T');push('-');break;
  139. case 20:push('B');push('F');break;
  140. case 25:push('B');push('F');break;
  141. case 33:push('B');push('F');push('*');break;
  142. case 34:push('B');push('F');push('/');break;
  143. case 40:push('i');break;
  144. case 45:push(')');push('E');push('(');
  145. }
  146. }
  147. /*根据curchar,curtocmp转为数字以判断是否有产生式*/
  148. void changchartoint()
  149. {
  150. switch(curtocmp)        /*非终结符:栈顶*/
  151. {
  152. case 'A':i=1;break;
  153. case 'B':i=3;break;
  154. case 'E':i=0;break;
  155. case 'T':i=2;break;
  156. case 'F':i=4;
  157. }
  158. switch(curchar) /*终结符:待识别的表达式中*/
  159. {
  160. case 'i':j=0;break;
  161. case '+':j=1;break;
  162. case '-':j=2;break;
  163. case '*':j=3;break;
  164. case '/':j=4;break;
  165. case '(':j=5;break;
  166. case ')':j=6;break;
  167. case '#':j=7;
  168. }
  169. }
  170. /*识别算法函数*/
  171. void identify()
  172. {
  173. int t;
  174. for(;;)
  175. {
  176. pop();  /*读取栈顶的字符存curtocmp中*/
  177. curchar=shift->ch; /*读取链中的一个字符存curchar*/
  178. printf("t%c-->%cn",curchar,curtocmp);
  179. if(curtocmp=='#' && curchar=='#') break;
  180. if(curtocmp=='A'||curtocmp=='B'||curtocmp=='E'||curtocmp=='T'||curtocmp=='F'){
  181. if(curtocmp!='#'){ /*[1]未到栈底时,匹配字符*/
  182. changchartoint();
  183. if(table[i][j]){  /*[1.1]有产生式*/
  184. t=10*i+j;   /*计算产生式在数组中的位置*/
  185. doforpush(t); /*找对应t的产生式,并入栈*/
  186. continue;
  187. }
  188. else{  /*[1.2]没有产生式*/
  189. right=0;    /*出错*/
  190. break;
  191. }
  192. }
  193. else{    /*[2]到栈底,当前比较字符为'#'*/
  194. if(curtocmp!=curchar){ /*输入行中最后一字符非'#'*/
  195. right=0;     /*出错*/
  196. break;
  197. }
  198. else
  199. break;        /*正确*/
  200. }
  201. }
  202. else{ /*若当前字符为终结符*/
  203. if(curtocmp!=curchar){
  204. right=0;  /*出错*/
  205. break;
  206. }
  207. else{
  208. shift=shift->next; /*读取下一个字符*/
  209. continue;
  210. }
  211. }
  212. }/*end for*/
  213. }