• 【编译原理】-- 递归下降语法分析设计原理与实现(C语言实现)


    本实验基于词法分析程序实现,可参考本人前面的文章。


    目录

    一、目标任务

    二、程序功能描述

    三、主要数据结构描述

    四、程序结构描述

    设计方法

    First集和Follow集

    递归子程序框图

    函数定义及函数之间的调用关系

    五、程序测试

    测试用例1

    测试结果1

    测试用例2

    测试结果2

    测试用例3

    测试结果3

    测试用例4

    测试结果4


    一、目标任务

    完成以下描述赋值语句的 LL(1)文法的递归下降分析程序
    G[S]: S→V=E
    E→TE′
    E′→ATE′|ε
    T→FT′

    T′→MFT′|ε
    F→ (E)|i
    A→+|-
    M→*|/
    V→i终结符号 i 为用户定义的简单变量,即标识符的定义。

    二、程序功能描述

    输入词法分析输出的二元式序列,能够输出该算术表达式是否为该文发定义的判断结果;

    输出二元式序列对应的算术表达式;

    输出算术表达式对应的单词符号类别编码;

    输出递归下降语法分析的过程;

    能够通过递归下降分析发现简单的语法错误。

    三、主要数据结构描述

    常量MAX_LENG定义数组的最大长度;

    sign用于标记语句是否正确;

    key[MAX_LENG]存放单词符号的编码类别;

       buf[MAX_LENG]保存词法分析程序的二元式序列;

       shuru[MAX_LENG]保存待检测的算术表达式;

       len为buf的长度。

    四、程序结构描述

    设计方法

    First集和Follow集

    递归子程序框图

    函数定义及函数之间的调用关系

    S():调用V、E

    E():调用E’

    E’():调用A、T、E’

    T():调用F、T’、

    T’():调用M、F、T’

    F():调用E

    A()

    M()

    V()

    五、代码

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #define MAX_LENG 1024
    5. int i;
    6. int sign=0;//标记语句是否正确
    7. int key[MAX_LENG];//存放单词符号的编码类别
    8. void S();
    9. void E();
    10. void E_();
    11. void T();
    12. void T_();
    13. void F();
    14. void A();
    15. void M();
    16. void V();
    17. void S(){
    18. if(sign==0){
    19. printf("S ");
    20. if(key[i]==1){
    21. V();
    22. if(sign==0&&key[i]==31){
    23. i++;
    24. E();
    25. }
    26. else{
    27. sign=1;
    28. printf("\nS处出现错误\n");
    29. }
    30. }
    31. else{
    32. sign=1;
    33. printf("\nS处出现错误\n");
    34. }
    35. }
    36. }
    37. void E(){
    38. if(sign==0){
    39. printf("->E ");
    40. if(key[i]==23||key[i]==1){
    41. T();
    42. if(sign==0){
    43. if(key[i]==16||key[i]==17){
    44. E_();
    45. }else if(key[i]==24||key[i]==-1){
    46. return;
    47. }else{
    48. sign=1;
    49. printf("\nE处出现错误\n");
    50. }
    51. }
    52. }else{
    53. sign=1;
    54. printf("\nE处出现错误\n");
    55. }
    56. }
    57. }
    58. void E_(){
    59. if(sign==0){
    60. printf("->E' ");
    61. if(key[i]==16||key[i]==17){
    62. A();
    63. if(sign==0){
    64. if(key[i]==23||key[i]==1){
    65. T();
    66. if(sign==0){
    67. if(key[i]==16||key[i]==17){
    68. E_();
    69. }else if(key[i]==24||key[i]==-1){
    70. return;
    71. }else{
    72. sign=1;
    73. printf("\nE'处出现错误\n");
    74. }
    75. }
    76. }else{
    77. sign=1;
    78. printf("\nE'处出现错误\n");
    79. }
    80. }
    81. }else if(key[i]==24||key[i]==-1){
    82. return;
    83. }else{
    84. sign=1;
    85. printf("\nE'处出现错误\n");
    86. }
    87. }
    88. }
    89. void T(){
    90. if(sign==0){
    91. printf("->T ");
    92. if(key[i]==23||key[i]==1){
    93. F();
    94. if(sign==0){
    95. if(key[i]==18||key[i]==19){
    96. T_();
    97. }else if(key[i]==16||key[i]==17||key[i]==24||key[i]==-1){
    98. return;
    99. }else{
    100. sign=1;
    101. printf("\nT处出现错误\n");
    102. }
    103. }
    104. }else{
    105. sign=1;
    106. printf("\nT处出现错误\n");
    107. }
    108. }
    109. }
    110. void T_(){
    111. if(sign==0){
    112. printf("->T' ");
    113. if(key[i]==18||key[i]==19){
    114. M();
    115. if(sign==0){
    116. F();
    117. if(sign==0){
    118. T_();
    119. }
    120. }
    121. }else if(key[i]==16||key[i]==17||key[i]==24||key[i]==-1){
    122. return;
    123. }else{
    124. sign=1;
    125. printf("\nT'处出现错误\n");
    126. }
    127. }
    128. }
    129. void F(){
    130. if(sign==0){
    131. printf("->F ");
    132. if(key[i]==23){
    133. i++;
    134. if(key[i]==23||key[i]==1){
    135. E();
    136. if(sign==0){
    137. if(key[i]==24){
    138. i++;
    139. }
    140. else{
    141. sign=1;
    142. printf("\nF处出现错误\n");
    143. }
    144. }
    145. }
    146. else{
    147. sign=1;
    148. printf("\nF处出现错误\n");
    149. }
    150. }
    151. else if(key[i]==1){
    152. i++;
    153. }
    154. else{
    155. sign=1;
    156. printf("\nF处出现错误\n");
    157. }
    158. }
    159. }
    160. void A()
    161. {
    162. if(sign==0){
    163. printf("->A ");
    164. if(key[i]==16||key[i]==17){
    165. i++;
    166. }
    167. else{
    168. sign=1;
    169. printf("\nA处出现错误\n");
    170. }
    171. }
    172. }
    173. void M()
    174. {
    175. if(sign==0){
    176. printf("->M");
    177. if(key[i]==18||key[i]==19){
    178. i++;
    179. }
    180. else{
    181. sign=1;
    182. printf("\nM处出现错误\n");
    183. }
    184. }
    185. }
    186. void V()
    187. {
    188. if(sign==0){
    189. printf("->V ");
    190. if(key[i]==1){
    191. i++;
    192. }
    193. else{
    194. sign=1;
    195. printf("\nV处出现错误\n");
    196. }
    197. }
    198. }
    199. int main(){
    200. FILE *fp;
    201. char buf[MAX_LENG]={0};//用于保存文件词法分析的结果
    202. char shuru[MAX_LENG]={0};//shuru为待检测的语句
    203. int len;//buf的长度
    204. int k=0,x=0,j=0;
    205. printf("词法分析二元式序列:\n");
    206. if((fp=fopen("demo_out.txt","r"))!=NULL){
    207. while(fgets(buf,MAX_LENG,fp)!=NULL){//每次读取一行
    208. len=strlen(buf);
    209. buf[len]='\0';//去除换行符
    210. printf("%s \n",buf);
    211. for(i=0;i<len;i++){
    212. if(buf[i]=='('){//将单词符号类别编码转换成数字
    213. if(buf[i+2]!=',')//如果是十位数数字
    214. key[j++]=int((buf[i+1]-'0')*10+buf[i+2]-'0');
    215. else//如果是个位数数字
    216. key[j++]=int(buf[i+1]-'0');
    217. continue;
    218. }
    219. if(buf[i]==','){
    220. i++;
    221. if(buf[i]==')')//解决(24,))的情况
    222. {
    223. shuru[x++]=')';
    224. i++;
    225. continue;
    226. }
    227. while(buf[i]!=')'){//分析的词法可能多个字符,如果没有while则只能保存一个字符
    228. shuru[x++]=buf[i];
    229. i++;
    230. }
    231. }
    232. }
    233. }
    234. }
    235. shuru[x++]='#';
    236. key[j++]=-1;
    237. fclose(fp);
    238. printf("算术表达式为:\n%s\n",shuru);
    239. printf("算术表达式的单词符号类别编码依次为:\n");
    240. for(i=0;i<j;i++)
    241. printf("%d ",key[i]);
    242. printf("\n");
    243. if(key[0]==-1)//当输入的第一个字符为#,直接结束
    244. return 0;
    245. printf("递归下降语法分析过程:\n");
    246. i=0;
    247. S();
    248. printf("\n");
    249. if(key[i]==-1&&sign==0){
    250. printf("此语句合法!\n");
    251. }else{
    252. printf("此语句不合法!\n");
    253. }
    254. return 0;
    255. }

    六、程序测试

    输入为词法分析程序的二元式序列

    测试用例1

    (1,a)(31,=)(1,b)(18,*)(1,c)(16,+)(1,d)(16,+)(1,e)

    测试结果1

    测试用例2

    (1,a)(31,=)(1,b)(18,*)(1,c)(16,+)(23,()(1,d)(16,+)(1,e)(24,))

    测试结果2

    测试用例3

    (1,a)(31,=)(1,b)(18,*)(1,c)(16,+)(1,d)(16,+)(1,e)(24,))

    测试结果3

    测试用例4

    (1,p)(31,=)(1,a)(16,+)(23,()(1,b)(18,*)(23,()(1,c)(16,+)(1,d)(24,))(19,/)(1,e)(16,+)(23,()(1,x)(16,+)(1,y)(24,))

    测试结果4


    如果对你有帮助,不妨点个赞~~~

  • 相关阅读:
    PostwomanApi接口测试工具
    带头双向循环链表(最6的链表结构,数据结构必看)
    半导体器件结构测试稳定性中的加氢效应是什么
    操作表 函数的使用
    光电探测器怎么选
    【论文阅读】YOLO-World | 开集目标检测
    利用C++开发一个迷你的英文单词录入和测试小程序-升级版本
    目标检测YOLO实战应用案例100讲-基于YOLOv5_tiny算法的路面裂缝智能检测
    ddddocr:一款强大的开源OCR库
    【立创机械狗从0到成品PCB画图总结】
  • 原文地址:https://blog.csdn.net/Tir_zhang/article/details/127654416