编译原理实验一:简单PL/0词法分析器C语言代码

ゝ一世哀愁。 2022-06-17 06:10 297阅读 0赞

思路分析:我的个人思路比较简单,首先定义几个二维数组,分别保存PL语言关键字,界符,或者运算符,然后在主函数中,读入字符串,或者从文件中读入,然后对字符串进行分割,进行一些过滤空格(ASCII码为10,换行的ASCII码为13),之后将分割后的字符串与我们定义的数组进行比较(这相当于一个词库),假如匹配,就与之对应对它进行标记,如果既不是关键字,也不是界符.运算符,那么就是用户自定义的标识符.然后分别输出就OK.


code类别表:

1 : 关键字
2 : 标识符
3 : 常量
4 : 运算符
5 : 对应的是界符中元素的位置


关键字只有如下几个:

Const——用来声明常量;

Var——用来声明变量;

Procedure——用来声明过程;

Begin——声明过程的开始;

End——声明过程的结束;

Ood——单目运算符,声明为关键字;

If——条件语句;

Then——条件语句;

Call——声明调用函数;

While——循环语句;

Read——读文件语句;

Write——写文件语句;

对于用户自定义标识符应该满足:以字母开头,其后是字母和数字的组合,即:字母(字母|数字)*

数字则是数字字符(0——9)组成的数字串;

特殊符号有如下几个:
+,-,*,/,=<>,<,>=,<=,:=

把关键字、算符和界符称为语言固有的单词,标识符、常量称为用户自定义的单词。

实验指导书上说啥用SYM,ID,NUM,我个人觉得没必要,这是为了后面的自动转换机准备的,什么枚举类型啊,实验一应该用不到,况且第一节上机课代码给老师验收的时候,老师说差不多就可以了.那就差不多,没必要那么复杂,个人觉得对编译原理这门课没必要太重视,毕竟太冷门了,以后谁吃多了做编译器设计语言呢?不实用..

下面上代码:

  1. /*************************************************************************
  2. > File Name: pl0.c
  3. > Author:chendiyang
  4.      > School:WUST_CST_1501班
  5.      > Myblog: www.chendsir.com
  6. > Mail:1441353519@qq.com
  7. > Created Time: 2017年04月06日 星期四 20时27分34秒
  8. ************************************************************************/
  9. #include<stdio.h>
  10. #include<stdlib.h>
  11. #include<string.h>
  12. /*
  13. code类别表:
  14. 1 : 关键字
  15. 2 : 标识符
  16. 3 : 常量
  17. 4 : 运算符
  18. 5 : 对应的是界符中元素的位置
  19. */
  20. typedef struct Word
  21. {
  22. int num;//词所属类型 SYM
  23. char w[20];//词的标识识别符的值 ID
  24. }Word;
  25. int main()
  26. {
  27. char ch,word_temp[20]=""; //缓存区
  28. int i=0,j=0,k=0,key=0,chioce;
  29. char ktt[42][20]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write",",",";",":","(",")","[","]","{","}","+","-","*","/","=","<",">","<=",">=",":=","0","1","2","3","4","5","6","7","8","9"}; //SYM用户关键字,运算符,界符
  30. FILE *fp;
  31. Word word[100];
  32. printf("1:输入源程序保存成文件\n");
  33. printf("2:打开文件进行词法分析\n");
  34. printf("请输入你的选择:");
  35. scanf("%d",&chioce);
  36. switch(chioce)
  37. {
  38. case 1:
  39. fp=fopen("nasm.txt","wt");
  40. if(!fp)
  41. {
  42. printf("can't open file C_program.txt\n");
  43. exit(1);
  44. }
  45. printf("请输入一段程序(以#结束):\n");
  46. ch=getchar();
  47. while(ch!='#')
  48. {
  49. fputc(ch,fp);
  50. ch=getchar();
  51. }
  52. fclose(fp);break;
  53. case 2:
  54. fp=fopen("nasm.txt","r");
  55. if(!fp)
  56. {
  57. printf("can't open file C_program.txt\n");
  58. exit(1);
  59. }
  60. printf("源程序如下:");
  61. while((ch=fgetc(fp))!=EOF)
  62. {
  63. putchar(ch);
  64. }
  65. fclose(fp);
  66. printf("\n词法分析结果如下:\n");
  67. fp=fopen("nasm.txt","r");
  68. if(!fp)
  69. {
  70. printf("can't open file C_program.txt\n");
  71. exit(1);
  72. }
  73. while((ch=fgetc(fp))!=EOF)
  74. {
  75. if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'))
  76. {
  77. word_temp[key++]=ch;//连续几个字母的连成单词
  78. word_temp[key]='\0';
  79. continue;
  80. }
  81. else
  82. { if(strcmp(word_temp,"")!=0)
  83. {
  84. strcpy(word[i].w,word_temp);//将单词拷贝到结构数组中
  85. strcpy(word_temp,"");
  86. key=0;//回到临时数组的开始位置
  87. i++;//结构数组的下标加1
  88. }
  89. if(ch==' '||ch==10||ch==13||ch==' ')//去掉空格、回车和tab键
  90. {
  91. continue;
  92. }
  93. else
  94. {
  95. word_temp[0]=ch;
  96. if(word_temp[0]==':'||word_temp[0]=='>'||word_temp[0]=='<')
  97. ch=fgetc(fp);
  98. if(ch=='=')
  99. word_temp[1]=ch;
  100. word_temp[2]='\0';//字符串结束符
  101. strcpy(word[i].w,word_temp);//将非字母数字符号拷贝到结构数组中
  102. strcpy(word_temp,"");
  103. key=0;//回到临时数组的开始位置
  104. i++;
  105. }
  106. }
  107. }break;
  108. default: printf(" 输入错误!");
  109. }
  110. for(j=0;j<i;j++)
  111. {
  112. for(k=0;k<43;k++)
  113. {
  114. if((strcmp(word[j].w,ktt[k]))==0)
  115. {
  116. if(k>=0&&k<13)
  117. word[j].num=1;//保留字
  118. else if(k>=13&&k<21)
  119. word[j].num=5;//分隔符
  120. else if(k>=21&&k<32)
  121. word[j].num=4;//运算符
  122. else if(k>=32&&k<43)
  123. word[j].num=3;//数字
  124. break;
  125. }
  126. else
  127. word[j].num=2;//变量
  128. }
  129. }
  130. printf("code类别表:\n");printf("1 : 关键字 \n");
  131. printf("2 : 标识符\n");
  132. printf("3 : 常量\n");
  133. printf("4 : 运算符 \n");
  134. printf("5 : 对应的是界符中元素的位置\n");
  135. for(j=0;j<i;j++)//按格式要求打印输出
  136. {
  137. printf("(%d,'%s')\n",word[j].num,word[j].w);
  138. }
  139. //输出保留字
  140. printf("\n保留字表:\n\n");
  141. for(j=0;j<i;j++)
  142. {
  143. if(word[j].num==1)
  144. {
  145. printf("%s ",word[j].w);
  146. }
  147. }
  148. //分隔符表
  149. printf("\n分隔符表:\n\n");
  150. for(j=0;j<i;j++)
  151. {
  152. if(word[j].num==5)
  153. {
  154. printf("%s ",word[j].w);
  155. }
  156. }
  157. //运算符表
  158. printf("\n运算符表:\n\n");
  159. for(j=0;j<i;j++)
  160. {
  161. if(word[j].num==4)
  162. {
  163. printf("%s ",word[j].w);
  164. }
  165. }
  166. //数字表
  167. printf("\n数字表:\n\n");
  168. for(j=0;j<i;j++)
  169. {
  170. if(word[j].num==3)
  171. {
  172. printf("%s ",word[j].w);
  173. }
  174. }
  175. //变量表
  176. printf("\n变量表:\n");
  177. for(j=0;j<i;j++)
  178. {
  179. if(word[j].num==2&strcmp(word[j].w," ")!=0)
  180. {
  181. printf("%s ",word[j].w);
  182. }
  183. }
  184. printf("\n");
  185. fclose(fp);
  186. return 0;
  187. }

运行结果如图:
2017-04-09-17-50-53_E5_B1_8F_E5_B9_95_E6_88_AA_E5_9B_BE-300x158.png 2017-04-09-17-51-13_E5_B1_8F_E5_B9_95_E6_88_AA_E5_9B_BE-300x176.png 2017-04-09-17-51-26_E5_B1_8F_E5_B9_95_E6_88_AA_E5_9B_BE-300x177.png

注意,敲黑板了,注意符号的拼数问题:比如":"和":=",">="之类....

以上.......

发表评论

表情:
评论列表 (有 0 条评论,297人围观)

还没有评论,来说两句吧...

相关阅读