当前位置:   article > 正文

词法分析二(词法分析程序)_编写一个将输入的源代码识别出词法分析的二元组,并且输出。

编写一个将输入的源代码识别出词法分析的二元组,并且输出。

1、词法分析功能

输入:所给文法的源程序字符串

输出:二元组(syn,token或sum)构成的序列。其中,

 syn为单词种别码。

 Token为存放的单词自身字符串。

 Sum为整型常量。

具体实现时,可以将单词的二元组用结构进行处理。

2、待分析的C语言子集的词法

1)关键字

main  if  then  while  do  static  int  double  struct  break  else  long  switch  case  typedef  char  return  const  float  short  continue  for  void  default  sizeof

所有的关键字都是小写。

2)运算符和界符

 +  -  *  /  : <  <>  <=  >  >=  =  ; (  )  #

3)其他标记ID和NUM

通过以下正规式定义其他标记:

ID→letter(letter|digit)*

NUM→digit digit*

letter→a|…|z|A|…|Z

digit→0|…|9…

4)空格由空白、制表符和换行符组成

空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。

3、各种单词符号对应的种别码

表1   各种单词符号的种别码

单词符号   种别码       单词符号   种别码      单词符号   种别码      单词符号   种别码      单词符号   种别码      

#                  0               else        11               for               22           ==               33            )                 44

main            1               long        12               void             23           <                 34           {                 45 

if                  2               switch      13              default        24           <>                35            }                46

then            3                case        14               sizeof         25           <=               36             ,                47

while           4                typedef     15              ID               26           >                 37          

do               5                 char        16               NUM           27           >=               38

static           6                 return      17              +                 28            =                39          

int               7                 const       18               -                 29             [                40     

double        8                 float       19                 *                 30             ]                41    

struct          9                 short       20                /                 31             ;                42     

break         10                continue    21             **               32          (                 43

  

 上述为一些基本符号,可以自己另加。

 

状态转换图:

 

代码:

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <cstring>
  5. #include <string>
  6. using namespace std;
  7. FILE *fp; // 文件指针,处理源文件
  8. char *ScanBuffer; // 扫描缓冲区,一分为二,每次一半存放预处理后的字符串
  9. int capacity; // 扫描缓冲区容量
  10. int BufferFlag; // 状态标志,0 表示使用缓冲区的左半区,1 表示使用右半区
  11. int PreprocessFlag; // 预处理的状态标志
  12. string rwtab[25]={"main","if","then","while","do"," static",
  13. "int"," double","struct","break","else","long","switch",
  14. "case","typedef","char","return","const","float","short",
  15. "continue","for","void","default","sizeof"};
  16. // init fp, ScanBuffer, BufferFlag,SP,EP,PreprocessFlag
  17. void init(){
  18. fp = fopen("test.txt","r");
  19. if(fp == NULL) exit(0);
  20. capacity = 120;
  21. ScanBuffer = new char[capacity]; // 缓冲区分配长度 :120。
  22. memset(ScanBuffer,0,sizeof(ScanBuffer));
  23. BufferFlag = 0;
  24. PreprocessFlag = 0;
  25. }
  26. void close(){
  27. fclose(fp);
  28. delete ScanBuffer;
  29. }
  30. void Preprocess(){
  31. //参见词法分析一
  32. }
  33. /*
  34. 分析器变量
  35. SP: 分析器的起点指示器
  36. EP: 分析器的搜索指示器
  37. syn: 种别编码
  38. token: 存放一个处理的字符串
  39. sum: 常量
  40. status:状态
  41. */
  42. int SP = 0; int EP = 0;
  43. int syn = -1; string token = "";
  44. int sum = 0; int status = 0;
  45. // 字母
  46. int IsLetter(char c){
  47. if(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') return 1;
  48. return 0;
  49. }
  50. //数字
  51. int IsDigit(char c){
  52. if(c >= '0' && c <= '9') return 1;
  53. return 0;
  54. }
  55. // 关键字或者是变量
  56. void Key(){
  57. token = "";
  58. if(SP < EP){
  59. for(int i = SP; i < EP; i++) token.push_back(ScanBuffer[i]);
  60. }else{
  61. for(int i = SP; i < capacity; i++) token.push_back(ScanBuffer[i]);
  62. for(int i = 0; i < EP; i++) token.push_back(ScanBuffer[i]);
  63. }
  64. for(int i = 0; i < 25; i++) if(token.compare(rwtab[i]) == 0) {syn = i+1; return;}
  65. syn = 26; return;
  66. }
  67. void Number(){
  68. sum = 0;
  69. if(SP < EP){
  70. for(int i = SP; i < EP; i++) sum = sum * 10 + ScanBuffer[i] - '0';
  71. }else{
  72. for(int i = SP; i < capacity; i++) sum = sum * 10 + ScanBuffer[i] - '0';
  73. for(int i = 0; i < EP; i++) sum = sum * 10 + ScanBuffer[i] - '0';
  74. }
  75. syn = 27;
  76. }
  77. // 不合法变量的处理,例如以数字开头的变量
  78. void InvalidToken(){
  79. token = "";
  80. if(SP < EP){
  81. for(int i = SP; i < EP; i++) token.push_back(ScanBuffer[i]);
  82. }else{
  83. for(int i = SP; i < capacity; i++) token.push_back(ScanBuffer[i]);
  84. for(int i = 0; i < EP; i++) token.push_back(ScanBuffer[i]);
  85. }
  86. while(IsLetter(ScanBuffer[EP]) || IsDigit(ScanBuffer[EP])) {token.push_back(ScanBuffer[EP]); EP++;}
  87. }
  88. // 单个字符 ,例如‘<’
  89. void OneCharacter(){
  90. switch(status){
  91. case 11: syn = 39; break;
  92. case 16: syn = 30; break;
  93. case 22: syn = 34; break;
  94. case 24: syn = 37; break;
  95. }
  96. }
  97. // 双字符 ,例如‘<=’
  98. void TwoCharacter(){
  99. switch(status){
  100. case 12: syn = 33; break;
  101. case 17: syn = 32; break;
  102. case 20: syn = 35; break;
  103. case 21: syn = 36; break;
  104. case 25: syn = 38; break;
  105. }
  106. }
  107. void CharacterMatch(char ch){
  108. switch(ch){
  109. case ' ': break;
  110. case ';': {status = 5; syn = 42; break;}
  111. case '(': {status = 6; syn = 43; break;}
  112. case ')': {status = 7; syn = 44; break;}
  113. case '[': {status = 8; syn = 40; break;}
  114. case ']': {status = 9; syn = 41; break;}
  115. case '{': {status = 27;syn = 45; break;}
  116. case '}': {status = 28;syn = 46; break;}
  117. case ',': {status = 29;syn = 47; break;}
  118. case '+': {status = 13;syn = 28; break;}
  119. case '-': {status = 14;syn = 29; break;}
  120. case '/': {status = 18;syn = 31; break;}
  121. case '#': {status = 26;syn = 0; break;}
  122. case '=': {status = 10; break;}
  123. case '*': {status = 15; break;}
  124. case '<': {status = 19; break;}
  125. case '>': {status = 23; break;}
  126. default: {status = -1; break;}
  127. }
  128. }
  129. void StatusHandle(){
  130. switch(status){
  131. case -2: {
  132. InvalidToken(); cout<<"invalid token: "<<token<<endl; status = 0; SP = EP;break;
  133. }
  134. case -1: {
  135. printf("invalid character: %c\n",ScanBuffer[EP]); EP++; status = 0; SP = EP;break;
  136. }
  137. case 1: case 3: case 10: case 15: case 19: case 23:{
  138. EP++; break;
  139. }
  140. case 0:{
  141. EP++; SP = EP; break;
  142. }
  143. case 2:{
  144. Key(); cout<<"("<<syn<<","<<token<<")"<<endl; SP = EP; status = 0; break;
  145. }
  146. case 4:{
  147. Number();cout<<"("<<syn<<","<<sum<<")"<<endl; SP = EP; status = 0; break;
  148. }
  149. case 5:case 6:case 7:case 8:case 9:case 13:case 14:case 18:case 26:case 27:case 28:case 29:{
  150. cout<<"("<<syn<<","<<ScanBuffer[SP]<<")"<<endl; EP++; SP = EP; status = 0; break;
  151. }
  152. case 11: case 16: case 22: case 24:{
  153. OneCharacter(); cout<<"("<<syn<<","<<ScanBuffer[SP]<<")"<<endl; SP++; EP = SP; status = 0; break;
  154. }
  155. case 12: case 17: case 20: case 21: case 25:{
  156. TwoCharacter();
  157. cout<<"("<<syn<<","<<ScanBuffer[SP]<<ScanBuffer[EP]<<")"<<endl;
  158. EP++; SP = EP;
  159. status = 0; break;
  160. }
  161. }
  162. }
  163. // 状态转换图
  164. void Analyse(char ch){
  165. switch(status){
  166. case 0:{
  167. if(IsLetter(ch)) status = 1;
  168. else if(IsDigit(ch)) status = 3;
  169. else CharacterMatch(ch);
  170. break;
  171. }
  172. case 1:{
  173. if(IsLetter(ch) || IsDigit(ch)) break;
  174. else status = 2; break;
  175. }
  176. case 3:{
  177. if(IsDigit(ch)) break;
  178. else if(IsLetter(ch)){
  179. status = -2; break;
  180. }else {
  181. status = 4; break;
  182. }
  183. }
  184. case 10:{
  185. if(ch == '=') {status = 12; break;}
  186. else status = 11; break;
  187. }
  188. case 15:{
  189. if(ch == '*') {status = 17; break;}
  190. else status = 16; break;
  191. }
  192. case 19:{
  193. if(ch == '>') {status = 20; break;}
  194. else if(ch == '='){status = 21; break;}
  195. else status = 23;break;
  196. }
  197. case 23:{
  198. if(ch == '=') {status = 25; break;}
  199. else status = 24; break;
  200. }
  201. }
  202. StatusHandle();
  203. }
  204. void Analyzer(){
  205. while(!feof(fp)){
  206. Preprocess(); BufferFlag = BufferFlag ^ 1;
  207. if(BufferFlag){
  208. EP = 0; // 使用左半缓冲区
  209. if(SP == capacity) SP = 0; // 防止SP越界
  210. while(ScanBuffer[EP] != -1 && EP < capacity/2){
  211. Analyse(ScanBuffer[EP]);
  212. }
  213. }else{
  214. while(ScanBuffer[EP] != -1 && EP < capacity){
  215. Analyse(ScanBuffer[EP]);
  216. }
  217. }
  218. }
  219. }
  220. int main(){
  221. init();
  222. Analyzer();
  223. close();
  224. return 0;
  225. }

      

测试用例:

// 单行注释

/*
    多行注释
*/
int ArraySum(int **a, int m, int n){
    int 9sum = 0;
    for(int i = 0; i < m; i = i + 1){
        for(int j = 0; j < n; j = j + 1){
            sum = sum + a[i][j];
        }
    }
    return sum;
}

 

测试结果:

          

      

 

 

 


       

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/294220
推荐阅读
相关标签
  

闽ICP备14008679号