编译原理------语法分析器C/C++代码实现

偏执的太偏执、 2022-04-24 15:10 620阅读 0赞

一、实验目的

编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

二、实验内容

利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

2.1 待分析的简单语言的语法

用扩充的BNF表示如下:

⑴<程序>::=begin<语句串>end

⑵<语句串>::=<语句>{;<语句>}

⑶<语句>::=<赋值语句>

⑷<赋值语句>::=ID:=<表达式>

⑸<表达式>::=<项>{+<项> | -<项>}

⑹<项>::=<因子>{*<因子> | /<因子>}

⑺<因子>::=ID | NUM | (<表达式>)

2.2 实验要求说明

输入单词串,以“#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。

例如:

  1. 输入 begin a:=9; x:=2\*3; b:=a+x end \#
  2. 输出 success
  3. 输入 x:=a+b\*c end \#
  4. 输出 error

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JhaWR1XzQxNzc0MTIw_size_16_color_FFFFFF_t_70

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JhaWR1XzQxNzc0MTIw_size_16_color_FFFFFF_t_70 1

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JhaWR1XzQxNzc0MTIw_size_16_color_FFFFFF_t_70 2

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JhaWR1XzQxNzc0MTIw_size_16_color_FFFFFF_t_70 3

代码如下:

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<iostream>
  4. using namespace std;
  5. //定义几个全局变量
  6. int syn;
  7. char s[1000];
  8. int p=0;
  9. int k=0;// 定义 k 作为一个标记符,记录是否出错,若 k=0 ,则说明没有出错,否则发生错误
  10. char key[6][20] = {"begin","if","then","while","do","end"};//定义一个二维数组存放关键字
  11. char token[20]; //存放字符(单词)
  12. void expression();
  13. //判断关键字
  14. int isKey(char s[])
  15. {
  16. for(int i = 0; i < 6;i++)
  17. {
  18. if(strcmp(s,key[i]) == 0)
  19. {
  20. return i+1; //关键字的种别码依次为 begin=1,if=2,then=3,while=4,do=5,end=6即为 i+1 的值
  21. }
  22. }
  23. return -1;
  24. }
  25. //判断是不是字母
  26. bool isChar(char ch)
  27. {
  28. if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))
  29. return true;
  30. else
  31. return false;
  32. }
  33. //判断是不是数字
  34. bool isNum(char ch)
  35. {
  36. if(ch>='0' && ch<='9')
  37. return true;
  38. else
  39. return false;
  40. }
  41. //词法分析器
  42. void scanner()
  43. {
  44. int count = 0;
  45. if(s[p] == ' ') p++;
  46. //开头是字母
  47. if(isChar(s[p]))
  48. {
  49. while(isNum(s[p]) || isChar(s[p]))
  50. {
  51. token[count++] = s[p];
  52. p++;
  53. }
  54. token[count] = '\0'; //'\0'作为结束符 ,将单词分隔开
  55. syn = isKey(token);
  56. if(syn == -1)
  57. {
  58. syn = 10; //标识符letter(letter|digit) *
  59. }
  60. }
  61. //开头是数字
  62. else if(isNum(s[p]))
  63. {
  64. while(isNum(s[p]))
  65. {
  66. token[count++] = s[p];
  67. p++;
  68. }
  69. token[count] = '\0';//结束标识
  70. syn = 11; //数字digit(digit) *
  71. }
  72. //如果是运算符或者界符
  73. else
  74. {
  75. //先处理没有争议的字符
  76. switch(s[p])
  77. {
  78. case '+': syn = 13;token[0] = s[p];token[1]='\0';break;
  79. case '-': syn = 14;token[0] = s[p];token[1]='\0';break;
  80. case '*': syn = 15;token[0] = s[p];token[1]='\0';break;
  81. case '/': syn = 16;token[0] = s[p];token[1]='\0';break;
  82. case '=': syn = 25;token[0] = s[p];token[1]='\0';break;
  83. case ';': syn = 26;token[0] = s[p];token[1]='\0';break;
  84. case '(': syn = 27;token[0] = s[p];token[1]='\0';break;
  85. case ')': syn = 28;token[0] = s[p];token[1]='\0';break;
  86. case '#': syn = 0 ;token[0] = s[p];token[1]='\0';break;
  87. }
  88. //处理有争议的
  89. //: :=
  90. if(s[p] == ':')
  91. {
  92. token[count++] = s[p];
  93. if(s[p+1] == '=')
  94. {
  95. p++;
  96. token[count++] = s[p];
  97. syn = 18;
  98. }
  99. else
  100. {
  101. syn = 17;
  102. }
  103. token[count] = '\0';
  104. }
  105. //< <> <=
  106. if(s[p] == '<')
  107. {
  108. token[count++] = s[p];
  109. if(s[p+1] == '>')
  110. {
  111. p++;
  112. token[count++] = s[p];
  113. syn = 21;
  114. }
  115. else if(s[p+1] == '=')
  116. {
  117. p++;
  118. token[count++] = s[p];
  119. syn = 22;
  120. }
  121. else
  122. {
  123. syn = 20;
  124. }
  125. token[count] = '\0';
  126. }
  127. //> >=
  128. if(s[p] == '>')
  129. {
  130. token[count++] = s[p];
  131. if(s[p+1] == '=')
  132. {
  133. p++;
  134. token[count++] = s[p];
  135. syn = 24;
  136. }
  137. else
  138. {
  139. syn = 23;
  140. }
  141. token[count] = '\0';
  142. }
  143. //后移
  144. p++; //判断运算符和界符的这部分由于指针 p 没有向后指,所以需要将指针 p 向后移一位
  145. }
  146. }
  147. 以下各函数均要先调用 scanner()函数,用于首先产生 syn 的值
  148. //因子-->项-->表达式-->赋值语句-->语句-->程序
  149. //由小到大逐层封装函数
  150. void factor() //因子 :<因子> :=ID | NUM | (<表达式>)
  151. {
  152. if(syn==10||syn==11) //当扫描的是数字或者字母时,继续扫描
  153. {
  154. scanner();
  155. }
  156. else if(syn==27) //当扫描到 '('时,后面应该为一个表达式,继续扫描
  157. {
  158. scanner();
  159. expression();
  160. if(syn==28) //当扫描的是 ')'时,继续扫描
  161. scanner();
  162. else
  163. {
  164. k=1; //出错
  165. cout<<"ERROR!缺少')'"<<endl; //表达式缺 ')',出错
  166. }
  167. }
  168. else
  169. {
  170. k=1;
  171. cout<<"ERROR!运算符号后面不是常数或'('或标识符"<<endl; //扫描表达式 ,表达式不是以 '('开头
  172. }
  173. }
  174. void term()//项 : <项> :=<因子>{*<因子> | /<因子> }
  175. {
  176. factor();
  177. while(syn==15||syn==16) //当开头扫描的是 '*' 或者 '/'时('*'或者'/'后面是因子),继续扫描
  178. {
  179. scanner();
  180. factor();
  181. }
  182. }
  183. void expression()//表达式 : <表达式> :=<项>{+<项> | -<项>}
  184. {
  185. term();
  186. while(syn==13||syn==14) //当开头扫描的是 '+' 或者 '-'时('+'或者'-'后面是项),继续扫描
  187. {
  188. scanner();
  189. term();
  190. }
  191. }
  192. void statement()//赋值语句 : ID = <表达式>
  193. {
  194. if(syn==10) //当开头扫描的是字母时,继续扫描
  195. {
  196. scanner();
  197. if(syn==18) //扫描的是 ':='时,继续扫描
  198. {
  199. scanner();
  200. expression();
  201. }
  202. else
  203. {
  204. k=1;
  205. cout<<"ERROR!缺少 ':=' "<<endl;
  206. }
  207. }
  208. else
  209. {
  210. k=1;
  211. cout<<"ERROR!开头不是标识符!"<<endl;
  212. }
  213. }
  214. void sens()//语句串 :<语句串>:=<语句>{;<语句>}
  215. {
  216. statement();
  217. while(syn==26) //当开始扫描的是 ';'时,继续扫描
  218. {
  219. scanner();
  220. statement();
  221. }
  222. }
  223. //程序 : <程序> :=begin<语句串>end
  224. void lrparser()
  225. {
  226. if(syn==1) //当开头扫描的是 'begin'时,继续扫描
  227. {
  228. scanner() ;
  229. sens();
  230. if(syn==6) //扫描到 'end'时,继续扫描
  231. {
  232. scanner();
  233. if(syn==0&&k==0) //当数字串最后扫描的是 '#',而且无出错,分析成功
  234. cout<<"success!" <<endl;
  235. else if(syn!=0||k==1)
  236. cout<<"error!"<<endl;
  237. }
  238. else
  239. {
  240. cout<<"ERROR!没有 'end'"<<endl;
  241. }
  242. }
  243. else
  244. {
  245. cout<<"ERROR!没有 'begin'"<<endl;
  246. }
  247. }
  248. int main()
  249. {
  250. char ch;
  251. while(true)
  252. {
  253. cout<<"Please input a string: "<<endl;
  254. cin.getline(s,1000);//getline()函数可以滤去空格
  255. p=0;
  256. scanner();
  257. lrparser();
  258. }
  259. return 0;
  260. }

" class="reference-link">watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2JhaWR1XzQxNzc0MTIw_size_16_color_FFFFFF_t_70 4

发表评论

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

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

相关阅读