C++写的一个简单的词法分析器(分析C语言)

实验用:

几点注意:

1.代码又长又臭,时间关系,没有优化,冗余项多(我都看不下去了。囧)

2.加了一下简单的错误检测。(在mapping.h中定义了错误类型,可以查阅)

3.使用头文件宏定义来表示单词的各种属性,也可以用文件

4.对于标志符的入口地址,无非是为了唯一识别,只要名字相同,都作为一个,使用自增的Int来模拟入口地址,即唯一标识。不考虑变量类型。

5.最后输出有三个表:Token表,错误表,标志符表。

6.一个字符一个字符的读文件,其实可以每次读到一个固定长度的缓冲区,双缓冲区进行分析。也可以读每一行。

代码:

mapping.h:

  1. /* 
  2. 头文件:mapping.h 
  3. */  
  4.   
  5. //关键字  
  6. #define AUTO 1  
  7. #define BREAK 2  
  8. #define CASE 3  
  9. #define CHAR 4  
  10. #define CONST 5  
  11. #define CONTINUE 6  
  12. #define DEFAULT 7  
  13. #define DO 8  
  14. #define DOUBLE 9  
  15. #define ELSE 10  
  16. #define ENUM 11  
  17. #define EXTERN 12  
  18. #define FLOAT 13  
  19. #define FOR 14  
  20. #define GOTO 15  
  21. #define IF 16  
  22. #define INT 17  
  23. #define LONG 18  
  24. #define REGISTER 19  
  25. #define RETURN 20  
  26. #define SHORT 21  
  27. #define SIGNED 22  
  28. #define SIZEOF 23  
  29. #define STATIC 24  
  30. #define STRUCT 25  
  31. #define SWITCH 26  
  32. #define TYPEDEF 27  
  33. #define UNION 28  
  34. #define UNSIGNED 29  
  35. #define VOID 30  
  36. #define VOLATILE 31  
  37. #define WHILE 32  
  38. #define KEY_DESC "关键字"  
  39.   
  40. //标志符  
  41. #define IDENTIFER 40  
  42. #define IDENTIFER_DESC "标志符"  
  43.   
  44. //常量  
  45. #define INT_VAL 51 //整形常量  
  46. #define CHAR_VAL 52 //字符常量  
  47. #define FLOAT_VAL 53 //浮点数常量  
  48. #define STRING_VAL 54 //双精度浮点数常量  
  49. #define MACRO_VAL 55 //宏常量  
  50. #define CONSTANT_DESC "常量"  
  51.   
  52. //运算符  
  53. #define NOT 61   // !  
  54. #define BYTE_AND 62 //&  
  55. #define COMPLEMENT 63 // ~  
  56. #define BYTE_XOR  64 // ^  
  57. #define MUL 65 // *  
  58. #define DIV 66// /  
  59. #define MOD 67 // %  
  60. #define ADD 68 // +  
  61. #define SUB 69 // -  
  62. #define LES_THAN 70 // <  
  63. #define GRT_THAN 71 // >  
  64. #define ASG 72 // =  
  65. #define ARROW 73 // ->  
  66. #define SELF_ADD 74 // ++  
  67. #define SELF_SUB 75 // --  
  68. #define LEFT_MOVE 76 // <<  
  69. #define RIGHT_MOVE 77 // >>  
  70. #define LES_EQUAL 78 // <=  
  71. #define GRT_EQUAL 79 // >=  
  72. #define EQUAL 80 // ==  
  73. #define NOT_EQUAL 81 // !=  
  74. #define AND 82 // &&  
  75. #define OR 83 // ||  
  76. #define COMPLETE_ADD 84 // +=  
  77. #define COMPLETE_SUB 85 // -=  
  78. #define COMPLETE_MUL 86 // *=  
  79. #define COMPLETE_DIV 87 // /=  
  80. #define COMPLETE_BYTE_XOR 88 // ^=  
  81. #define COMPLETE_BYTE_AND 89 // &=  
  82. #define COMPLETE_COMPLEMENT 90 // ~=  
  83. #define COMPLETE_MOD 91 //%=  
  84. #define BYTE_OR 92 // |  
  85.   
  86. #define OPE_DESC "运算符"  
  87.   
  88. //限界符  
  89. #define LEFT_BRA 100 // (  
  90. #define RIGHT_BRA 101 // )  
  91. #define LEFT_INDEX 102 // [  
  92. #define RIGHT_INDEX 103 // ]  
  93. #define L_BOUNDER 104 //  {  
  94. #define R_BOUNDER 105 // }  
  95. #define POINTER 106 // .  
  96. #define JING 107 // #  
  97. #define UNDER_LINE 108 // _  
  98. #define COMMA 109 // ,  
  99. #define SEMI 110 // ;  
  100. #define SIN_QUE 111 // '  
  101. #define DOU_QUE 112 // "  
  102.   
  103. #define CLE_OPE_DESC "限界符"  
  104.   
  105. #define NOTE1 120 // "/**/"注释  
  106. #define NOTE2 121 // "//"注释  
  107. #define NOTE_DESC "注释"  
  108.   
  109.   
  110. #define HEADER 130 //头文件  
  111. #define HEADER_DESC "头文件"  
  112.   
  113. //错误类型  
  114. #define FLOAT_ERROR "float表示错误"  
  115. #define FLOAT_ERROR_NUM 1  
  116. #define DOUBLE_ERROR "double表示错误"  
  117. #define DOUBLE_ERROR_NUM 2  
  118. #define NOTE_ERROR "注释没有结束符"  
  119. #define NOTE_ERROR_NUM 3  
  120. #define STRING_ERROR "字符串常量没有结束符"  
  121. #define STRING_ERROR_NUM 4  
  122. #define CHARCONST_ERROR "字符常量没有结束符"  
  123. #define CHARCONST_ERROR_NUM 5  
  124. #define CHAR_ERROR "非法字符"  
  125. #define CHAR_ERROR_NUM 6  
  126. #define LEFT_BRA_ERROR "'('没有对应项"  
  127. #define LEFT_BRA_ERROR_NUM 7  
  128. #define RIGHT_BRA_ERROR "')'没有对应项"  
  129. #define RIGHT_BRA_ERROR_NUM 8  
  130. #define LEFT_INDEX_ERROR "'['没有对应项"  
  131. #define LEFT_INDEX_ERROR_NUM 9  
  132. #define RIGHT_INDEX_ERROR "']'没有对应项"  
  133. #define RIGHT_INDEX_ERROR_NUM 10  
  134. #define L_BOUNDER_ERROR "'{'没有对应项"  
  135. #define L_BOUNDER_ERROR_NUM 11  
  136. #define R_BOUNDER_ERROR "'}'没有对应项"  
  137. #define R_BOUNDER_ERROR_NUM 12  
  138. #define PRE_PROCESS_ERROR "预处理错误" //头文件或者宏定义错误  
  139. #define PRE_PROCESS_ERROR_NUM  13  
  140.   
  141. #define _NULL "无"  

main.cpp:
  1. //main.cpp  
  2.   
  3. #include <iostream>  
  4. #include <fstream>  
  5. #include <stdio.h>  
  6. #include <stdlib.h>  
  7. #include <string.h>  
  8. #include <iomanip>  
  9. #include "mapping.h"  
  10.   
  11. using namespace std;  
  12.   
  13. const char * key[] = {"auto","break","case","char","const","continue","default","do","double",  
  14.                       "else","enum","extern","float","for","goto","if","int","long","register",  
  15.                       "return","short","signed","sizeof","static","struct","switch","typedef",  
  16.                       "union","unsigned","void","volatile","while"  
  17.                      };//C语言的关键字  
  18. int leftSmall = 0;//左小括号  
  19. int rightSmall = 0;//右小括号  
  20. int leftMiddle = 0;//左中括号  
  21. int rightMiddle = 0;//右中括号  
  22. int leftBig = 0;//左大括号  
  23. int rightBig = 0;//右大括号  
  24. int lineBra[6][1000] = {0};//括号和行数的对应关系,第一维代表左右6种括号  
  25. int static_iden_number = 0;//模拟标志符的地址,自增  
  26. //Token节点  
  27. struct NormalNode  
  28. {  
  29.     char content[30];//内容  
  30.     char describe[30];//描述  
  31.     int type;//种别码  
  32.     int addr;//入口地址  
  33.     int line;//所在行数  
  34.     NormalNode * next;//下一个节点  
  35. };  
  36.   
  37. NormalNode * normalHead;//首结点  
  38.   
  39. //错误节点  
  40. struct ErrorNode  
  41. {  
  42.     char content[30];//错误内容  
  43.     char describe[30];//错误描述  
  44.     int type;  
  45.     int line;//所在行数  
  46.     ErrorNode * next;//下一个节点  
  47. };  
  48.   
  49. ErrorNode * errorHead;//首节点  
  50.   
  51. //标志符节点  
  52. struct IdentiferNode  
  53. {  
  54.     char content[30];//内容  
  55.     char describe[30];//描述  
  56.     int type;//种别码  
  57.     int addr;//入口地址  
  58.     int line;//所在行数  
  59.     IdentiferNode * next;//下一个节点  
  60. };  
  61. IdentiferNode * idenHead;//首节点  
  62.   
  63.   
  64. void initNode()  
  65. {  
  66.     normalHead = new NormalNode();  
  67.     strcpy(normalHead->content,"");  
  68.     strcpy(normalHead->describe,"");  
  69.     normalHead->type = -1;  
  70.     normalHead->addr = -1;  
  71.     normalHead->line = -1;  
  72.     normalHead->next = NULL;  
  73.   
  74.     errorHead = new ErrorNode();  
  75.     strcpy(errorHead->content,"");  
  76.     strcpy(errorHead->describe,"");  
  77.     errorHead->line = -1;  
  78.     errorHead->next = NULL;  
  79.   
  80.     idenHead = new IdentiferNode();  
  81.     strcpy(idenHead->content,"");  
  82.     strcpy(idenHead->describe,"");  
  83.     idenHead->type = -1;  
  84.     idenHead->addr = -1;  
  85.     idenHead->line = -1;  
  86.     idenHead->next = NULL;  
  87. }  
  88.   
  89. void createNewNode(char * content,char *descirbe,int type,int addr,int line)  
  90. {  
  91.     NormalNode * p = normalHead;  
  92.     NormalNode * temp = new NormalNode();  
  93.   
  94.     while(p->next!=NULL)  
  95.     {  
  96.         p = p->next;  
  97.     }  
  98.   
  99.     strcpy(temp->content,content);  
  100.     strcpy(temp->describe,descirbe);  
  101.     temp->type = type;  
  102.     temp->addr = addr;  
  103.     temp->line = line;  
  104.     temp->next = NULL;  
  105.   
  106.     p->next = temp;  
  107. }  
  108. void createNewError(char * content,char *descirbe,int type,int line)  
  109. {  
  110.     ErrorNode * p = errorHead;  
  111.     ErrorNode * temp = new ErrorNode();  
  112.   
  113.     strcpy(temp->content,content);  
  114.     strcpy(temp->describe,descirbe);  
  115.     temp->type = type;  
  116.     temp->line = line;  
  117.     temp->next = NULL;  
  118.     while(p->next!=NULL)  
  119.     {  
  120.         p = p->next;  
  121.     }  
  122.     p->next = temp;  
  123. }  
  124. //返回值是新的标志符的入口地址  
  125. int createNewIden(char * content,char *descirbe,int type,int addr,int line)  
  126. {  
  127.     IdentiferNode * p = idenHead;  
  128.     IdentiferNode * temp = new IdentiferNode();  
  129.     int flag = 0;  
  130.     int addr_temp = -2;  
  131.     while(p->next!=NULL)  
  132.     {  
  133.         if(strcmp(content,p->next->content) == 0)  
  134.         {  
  135.             flag = 1;  
  136.             addr_temp = p->next->addr;  
  137.         }  
  138.         p = p->next;  
  139.     }  
  140.     if(flag == 0)  
  141.     {  
  142.         addr_temp = ++static_iden_number;//用自增来模拟入口地址  
  143.     }  
  144.     strcpy(temp->content,content);  
  145.     strcpy(temp->describe,descirbe);  
  146.     temp->type = type;  
  147.     temp->addr = addr_temp;  
  148.     temp->line = line;  
  149.     temp->next = NULL;  
  150.     p->next = temp;  
  151.     return addr_temp;  
  152. }  
  153.   
  154. void printNodeLink()  
  155. {  
  156.     NormalNode * p = normalHead;  
  157.     p = p->next;  
  158.     cout<<"************************************分析表******************************"<<endl<<endl;  
  159.     cout<<setw(30)<<"内容"<<setw(10)<<"描述"<<"\t"<<"种别码"<<"\t"<<"地址"<<"\t"<<"行号"<<endl;  
  160.     while(p!=NULL)  
  161.     {  
  162.         if(p->type == IDENTIFER)  
  163.         {  
  164.             cout<<setw(30)<<p->content<<setw(10)<<p->describe<<"\t"<<p->type<<"\t"<<p->addr<<"\t"<<p->line<<endl;  
  165.         }  
  166.         else  
  167.         {  
  168.             cout<<setw(30)<<p->content<<setw(10)<<p->describe<<"\t"<<p->type<<"\t"<<"\t"<<p->line<<endl;  
  169.         }  
  170.         p = p->next;  
  171.     }  
  172.     cout<<endl<<endl;  
  173. }  
  174. /* 
  175. 错误种类: 
  176. 1.float表示错误 
  177. 2.double表示错误 
  178. 3.注释没有结束符 
  179. 4.字符串常量没有结束符 
  180. 5.字符常量没有结束符 
  181. 6.非法字符 
  182. 7.'('没有对应项 
  183. 8.预处理错误 
  184. */  
  185. void printErrorLink()  
  186. {  
  187.     ErrorNode * p = errorHead;  
  188.     p = p->next;  
  189.     cout<<"************************************错误表******************************"<<endl<<endl;  
  190.     cout<<setw(10)<<"内容"<<setw(30)<<"描述"<<"\t"<<"类型"<<"\t"<<"行号"<<endl;  
  191.     while(p!=NULL)  
  192.     {  
  193.         cout<<setw(10)<<p->content<<setw(30)<<p->describe<<"\t"<<p->type<<"\t"<<p->line<<endl;  
  194.         p = p->next;  
  195.     }  
  196.     cout<<endl<<endl;  
  197. }  
  198. //标志符表,有重复部分,暂不考虑  
  199. void printIdentLink()  
  200. {  
  201.     IdentiferNode * p = idenHead;  
  202.     p = p->next;  
  203.     cout<<"************************************标志符表******************************"<<endl<<endl;  
  204.     cout<<setw(30)<<"内容"<<setw(10)<<"描述"<<"\t"<<"种别码"<<"\t"<<"地址"<<"\t"<<"行号"<<endl;  
  205.     while(p!=NULL)  
  206.     {  
  207.         cout<<setw(30)<<p->content<<setw(10)<<p->describe<<"\t"<<p->type<<"\t"<<p->addr<<"\t"<<p->line<<endl;  
  208.         p = p->next;  
  209.     }  
  210.     cout<<endl<<endl;  
  211. }  
  212. int mystrlen(char * word)  
  213. {  
  214.     if(*word == '\0')  
  215.     {  
  216.         return 0;  
  217.     }  
  218.     else  
  219.     {  
  220.         return 1+mystrlen(word+1);  
  221.     }  
  222. }  
  223. //预处理,处理头文件和宏定义  
  224. void preProcess(char * word,int line)  
  225. {  
  226.     const char * include_temp = "include";  
  227.     const char * define_temp = "define";  
  228.     char * p_include,*p_define;  
  229.     int flag = 0;  
  230.     p_include = strstr(word,include_temp);  
  231.     if(p_include!=NULL)  
  232.     {  
  233.         flag = 1;  
  234.         int i;  
  235.         for(i=7;;)  
  236.         {  
  237.             if(*(p_include+i) == ' ' || *(p_include+i) == '\t')  
  238.             {  
  239.                 i++;  
  240.             }  
  241.             else  
  242.             {  
  243.                 break;  
  244.             }  
  245.         }  
  246.         createNewNode(p_include+i,HEADER_DESC,HEADER,-1,line);  
  247.     }  
  248.     else  
  249.     {  
  250.         p_define = strstr(word,define_temp);  
  251.         if(p_define!=NULL)  
  252.         {  
  253.             flag = 1;  
  254.             int i;  
  255.             for(i=7;;)  
  256.             {  
  257.                 if(*(p_define+i) == ' ' || *(p_define+i) == '\t')  
  258.                 {  
  259.                     i++;  
  260.                 }  
  261.                 else  
  262.                 {  
  263.                     break;  
  264.                 }  
  265.             }  
  266.             createNewNode(p_define+i,CONSTANT_DESC,MACRO_VAL,-1,line);  
  267.         }  
  268.     }  
  269.     if(flag == 0)  
  270.     {  
  271.         createNewError(word,PRE_PROCESS_ERROR,PRE_PROCESS_ERROR_NUM,line);  
  272.     }  
  273. }  
  274.   
  275. void close()  
  276. {  
  277.     delete idenHead;  
  278.     delete errorHead;  
  279.     delete normalHead;  
  280. }  
  281.   
  282. int seekKey(char * word)  
  283. {  
  284.     for(int i=0; i<32; i++)  
  285.     {  
  286.         if(strcmp(word,key[i]) == 0)  
  287.         {  
  288.             return i+1;  
  289.         }  
  290.     }  
  291.     return IDENTIFER;  
  292. }  
  293.   
  294. void scanner()  
  295. {  
  296.     char filename[30];  
  297.     char ch;  
  298.     char array[30];//单词长度上限是30  
  299.     char * word;  
  300.     int i;  
  301.     int line = 1;//行数  
  302.   
  303.   
  304.     FILE * infile;  
  305.     printf("请输入要进行语法分析的C语言程序:\n");  
  306.     scanf("%s",filename);  
  307.     infile = fopen(filename,"r");  
  308.     while(!infile)  
  309.     {  
  310.         printf("打开文件失败!\n");  
  311.         return;  
  312.     }  
  313.     ch = fgetc(infile);  
  314.     while(ch!=EOF)  
  315.     {  
  316.   
  317.         i = 0;  
  318.         //以字母或者下划线开头,处理关键字或者标识符  
  319.         if((ch>='A' && ch<='Z') || (ch>='a' && ch<='z') || ch == '_')  
  320.         {  
  321.             while((ch>='A' && ch<='Z')||(ch>='a' && ch<='z')||(ch>='0' && ch<='9') || ch == '_')  
  322.             {  
  323.                 array[i++] = ch;  
  324.                 ch = fgetc(infile);  
  325.             }  
  326.             word = new char[i+1];  
  327.             memcpy(word,array,i);  
  328.             word[i] = '\0';  
  329.             int seekTemp = seekKey(word);  
  330.             if(seekTemp!=IDENTIFER)  
  331.             {  
  332.                 createNewNode(word,KEY_DESC,seekTemp,-1,line);  
  333.             }  
  334.             else  
  335.             {  
  336.                 int addr_tmp = createNewIden(word,IDENTIFER_DESC,seekTemp,-1,line);  
  337.                 createNewNode(word,IDENTIFER_DESC,seekTemp,addr_tmp,line);  
  338.             }  
  339.             fseek(infile,-1L,SEEK_CUR);//向后回退一位  
  340.         }  
  341.         //以数字开头,处理数字  
  342.         else if(ch >='0' && ch<='9')  
  343.         {  
  344.             int flag = 0;  
  345.             int flag2 = 0;  
  346.             //处理整数  
  347.             while(ch >='0' && ch<='9')  
  348.             {  
  349.                 array[i++] = ch;  
  350.                 ch = fgetc(infile);  
  351.             }  
  352.             //处理float  
  353.             if(ch == '.')  
  354.             {  
  355.                 flag2 = 1;  
  356.                 array[i++] = ch;  
  357.                 ch = fgetc(infile);  
  358.                 if(ch>='0' && ch<='9')  
  359.                 {  
  360.                     while(ch>='0' && ch<='9')  
  361.                     {  
  362.                         array[i++] = ch;  
  363.                         ch = fgetc(infile);  
  364.                     }  
  365.                 }  
  366.                 else  
  367.                 {  
  368.                     flag = 1;  
  369.                 }  
  370.   
  371.                 //处理Double  
  372.                 if(ch == 'E' || ch == 'e')  
  373.                 {  
  374.                     array[i++] = ch;  
  375.                     ch = fgetc(infile);  
  376.                     if(ch == '+' || ch == '-')  
  377.                     {  
  378.                         array[i++] = ch;  
  379.                         ch = fgetc(infile);  
  380.                     }  
  381.                     if(ch >='0' && ch<='9')  
  382.                     {  
  383.                         array[i++] = ch;  
  384.                         ch = fgetc(infile);  
  385.                     }  
  386.                     else  
  387.                     {  
  388.                         flag = 2;  
  389.                     }  
  390.                 }  
  391.   
  392.             }  
  393.             word = new char[i+1];  
  394.             memcpy(word,array,i);  
  395.             word[i] = '\0';  
  396.             if(flag == 1)  
  397.             {  
  398.                 createNewError(word,FLOAT_ERROR,FLOAT_ERROR_NUM,line);  
  399.             }  
  400.             else if(flag == 2)  
  401.             {  
  402.                 createNewError(word,DOUBLE_ERROR,DOUBLE_ERROR_NUM,line);  
  403.             }  
  404.             else  
  405.             {  
  406.                 if(flag2 == 0)  
  407.                 {  
  408.                     createNewNode(word,CONSTANT_DESC,INT_VAL,-1,line);  
  409.                 }  
  410.                 else  
  411.                 {  
  412.                     createNewNode(word,CONSTANT_DESC,FLOAT_VAL,-1,line);  
  413.                 }  
  414.             }  
  415.             fseek(infile,-1L,SEEK_CUR);//向后回退一位  
  416.         }  
  417.         //以"/"开头  
  418.         else if(ch == '/')  
  419.         {  
  420.             ch = fgetc(infile);  
  421.             //处理运算符"/="  
  422.             if(ch == '=')  
  423.             {  
  424.                 createNewNode("/=",OPE_DESC,COMPLETE_DIV,-1,line);  
  425.             }  
  426.             //处理"/**/"型注释  
  427.             else if(ch == '*')  
  428.             {  
  429.                 ch =  fgetc(infile);  
  430.                 while(1)  
  431.                 {  
  432.                     while(ch != '*')  
  433.                     {  
  434.                         if(ch == '\n')  
  435.                         {  
  436.                             line++;  
  437.                         }  
  438.                         ch = fgetc(infile);  
  439.                         if(ch == EOF)  
  440.                         {  
  441.                             createNewError(_NULL,NOTE_ERROR,NOTE_ERROR_NUM,line);  
  442.                             return;  
  443.                         }  
  444.                     }  
  445.                     ch = fgetc(infile);  
  446.                     if(ch == '/')  
  447.                     {  
  448.                         break;  
  449.                     }  
  450.                     if(ch == EOF)  
  451.                     {  
  452.                         createNewError(_NULL,NOTE_ERROR,NOTE_ERROR_NUM,line);  
  453.                         return;  
  454.                     }  
  455.                 }  
  456.                 createNewNode(_NULL,NOTE_DESC,NOTE1,-1,line);  
  457.             }  
  458.             //处理"//"型注释  
  459.             else if(ch == '/')  
  460.             {  
  461.                 while(ch!='\n')  
  462.                 {  
  463.                     ch = fgetc(infile);  
  464.                     if(ch == EOF)  
  465.                     {  
  466.                         createNewNode(_NULL,NOTE_DESC,NOTE2,-1,line);  
  467.                         return;  
  468.                     }  
  469.                 }  
  470.                 line++;  
  471.                 createNewNode(_NULL,NOTE_DESC,NOTE2,-1,line);  
  472.                 if(ch == EOF)  
  473.                 {  
  474.                     return;  
  475.                 }  
  476.             }  
  477.             //处理除号  
  478.             else  
  479.             {  
  480.                 createNewNode("/",OPE_DESC,DIV,-1,line);  
  481.             }  
  482.         }  
  483.         //处理常量字符串  
  484.         else if(ch == '"')  
  485.         {  
  486.             createNewNode("\"",CLE_OPE_DESC,DOU_QUE,-1,line);  
  487.             ch = fgetc(infile);  
  488.             i = 0;  
  489.             while(ch!='"')  
  490.             {  
  491.                 array[i++] = ch;  
  492.                 if(ch == '\n')  
  493.                 {  
  494.                     line++;  
  495.                 }  
  496.                 ch = fgetc(infile);  
  497.                 if(ch == EOF)  
  498.                 {  
  499.                     createNewError(_NULL,STRING_ERROR,STRING_ERROR_NUM,line);  
  500.                     return;  
  501.                 }  
  502.             }  
  503.             word = new char[i+1];  
  504.             memcpy(word,array,i);  
  505.             word[i] = '\0';  
  506.             createNewNode(word,CONSTANT_DESC,STRING_VAL,-1,line);  
  507.             createNewNode("\"",CLE_OPE_DESC,DOU_QUE,-1,line);  
  508.         }  
  509.         //处理常量字符  
  510.         else if(ch == '\'')  
  511.         {  
  512.             createNewNode("\'",CLE_OPE_DESC,SIN_QUE,-1,line);  
  513.             ch = fgetc(infile);  
  514.             i = 0;  
  515.             while(ch!='\'')  
  516.             {  
  517.                 array[i++] = ch;  
  518.                 if(ch == '\n')  
  519.                 {  
  520.                     line++;  
  521.                 }  
  522.                 ch = fgetc(infile);  
  523.                 if(ch == EOF)  
  524.                 {  
  525.                     createNewError(_NULL,CHARCONST_ERROR,CHARCONST_ERROR_NUM,line);  
  526.                     return;  
  527.                 }  
  528.             }  
  529.             word = new char[i+1];  
  530.             memcpy(word,array,i);  
  531.             word[i] = '\0';  
  532.             createNewNode(word,CONSTANT_DESC,CHAR_VAL,-1,line);  
  533.             createNewNode("\'",CLE_OPE_DESC,SIN_QUE,-1,line);  
  534.         }  
  535.         else if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n')  
  536.         {  
  537.             if(ch == '\n')  
  538.             {  
  539.                 line++;  
  540.             }  
  541.         }  
  542.         else  
  543.         {  
  544.             if(ch == EOF)  
  545.             {  
  546.                 return;  
  547.             }  
  548.             //处理头文件和宏常量(预处理)  
  549.             else if(ch == '#')  
  550.             {  
  551.                 while(ch!='\n' && ch!=EOF)  
  552.                 {  
  553.                     array[i++] = ch;  
  554.                     ch = fgetc(infile);  
  555.                 }  
  556.                 word = new char[i+1];  
  557.                 memcpy(word,array,i);  
  558.                 word[i] = '\0';  
  559.                 preProcess(word,line);  
  560.   
  561.                 fseek(infile,-1L,SEEK_CUR);//向后回退一位  
  562.             }  
  563.             //处理-开头的运算符  
  564.             else if(ch == '-')  
  565.             {  
  566.                 array[i++] = ch;  
  567.                 ch = fgetc(infile);  
  568.                 if(ch >='0' && ch<='9')  
  569.                 {  
  570.                     int flag = 0;  
  571.                     int flag2 = 0;  
  572.                     //处理整数  
  573.                     while(ch>='0' && ch<='9')  
  574.                     {  
  575.                         array[i++] = ch;  
  576.                         ch = fgetc(infile);  
  577.                     }  
  578.                     //处理float  
  579.                     if(ch == '.')  
  580.                     {  
  581.                         flag2 = 1;  
  582.                         array[i++] = ch;  
  583.                         ch = fgetc(infile);  
  584.                         if(ch>='0' && ch<='9')  
  585.                         {  
  586.                             while(ch>='0' && ch<='9')  
  587.                             {  
  588.                                 array[i++] = ch;  
  589.                                 ch = fgetc(infile);  
  590.                             }  
  591.                         }  
  592.                         else  
  593.                         {  
  594.                             flag = 1;  
  595.                         }  
  596.                         //处理Double  
  597.                         if(ch == 'E' || ch == 'e')  
  598.                         {  
  599.                             array[i++] = ch;  
  600.                             ch = fgetc(infile);  
  601.                             if(ch == '+' || ch == '-')  
  602.                             {  
  603.                                 array[i++] = ch;  
  604.                                 ch = fgetc(infile);  
  605.                             }  
  606.                             if(ch >='0' && ch<='9')  
  607.                             {  
  608.                                 array[i++] = ch;  
  609.                                 ch = fgetc(infile);  
  610.                             }  
  611.                             else  
  612.                             {  
  613.                                 flag = 2;  
  614.                             }  
  615.                         }  
  616.                     }  
  617.                     word = new char[i+1];  
  618.                     memcpy(word,array,i);  
  619.                     word[i] = '\0';  
  620.                     if(flag == 1)  
  621.                     {  
  622.                         createNewError(word,FLOAT_ERROR,FLOAT_ERROR_NUM,line);  
  623.                     }  
  624.                     else if(flag == 2)  
  625.                     {  
  626.                         createNewError(word,DOUBLE_ERROR,DOUBLE_ERROR_NUM,line);  
  627.                     }  
  628.                     else  
  629.                     {  
  630.                         if(flag2 == 0)  
  631.                         {  
  632.                             createNewNode(word,CONSTANT_DESC,INT_VAL,-1,line);  
  633.                         }  
  634.                         else  
  635.                         {  
  636.                             createNewNode(word,CONSTANT_DESC,FLOAT_VAL,-1,line);  
  637.                         }  
  638.                     }  
  639.                     fseek(infile,-1L,SEEK_CUR);//向后回退一位  
  640.                 }  
  641.                 else if(ch == '>')  
  642.                 {  
  643.                     createNewNode("->",OPE_DESC,ARROW,-1,line);  
  644.                 }  
  645.                 else if(ch == '-')  
  646.                 {  
  647.                     createNewNode("--",OPE_DESC,SELF_SUB,-1,line);  
  648.                 }  
  649.                 else if(ch == '=')  
  650.                 {  
  651.                     createNewNode("--",OPE_DESC,SELF_SUB,-1,line);  
  652.                 }  
  653.                 else  
  654.                 {  
  655.                     createNewNode("-",OPE_DESC,SUB,-1,line);  
  656.                     fseek(infile,-1L,SEEK_CUR);  
  657.                 }  
  658.             }  
  659.             //处理+开头的运算符  
  660.             else if(ch == '+')  
  661.             {  
  662.                 ch = fgetc(infile);  
  663.                 if(ch == '+')  
  664.                 {  
  665.                     createNewNode("++",OPE_DESC,SELF_ADD,-1,line);  
  666.                 }  
  667.                 else if(ch == '=')  
  668.                 {  
  669.                     createNewNode("+=",OPE_DESC,COMPLETE_ADD,-1,line);  
  670.                 }  
  671.                 else  
  672.                 {  
  673.                     createNewNode("+",OPE_DESC,ADD,-1,line);  
  674.                     fseek(infile,-1L,SEEK_CUR);  
  675.                 }  
  676.             }  
  677.             //处理*开头的运算符  
  678.             else if(ch == '*')  
  679.             {  
  680.                 ch = fgetc(infile);  
  681.                 if(ch == '=')  
  682.                 {  
  683.                     createNewNode("*=",OPE_DESC,COMPLETE_MUL,-1,line);  
  684.                 }  
  685.                 else  
  686.                 {  
  687.                     createNewNode("*",OPE_DESC,MUL,-1,line);  
  688.                     fseek(infile,-1L,SEEK_CUR);  
  689.                 }  
  690.             }  
  691.             //处理按^开头的运算符  
  692.             else if(ch == '^')  
  693.             {  
  694.                 ch = fgetc(infile);  
  695.                 if(ch == '=')  
  696.                 {  
  697.                     createNewNode("^=",OPE_DESC,COMPLETE_BYTE_XOR,-1,line);  
  698.                 }  
  699.                 else  
  700.                 {  
  701.                     createNewNode("^",OPE_DESC,BYTE_XOR,-1,line);  
  702.                     fseek(infile,-1L,SEEK_CUR);  
  703.                 }  
  704.             }  
  705.             //处理%开头的运算符  
  706.             else if(ch == '%')  
  707.             {  
  708.                 ch = fgetc(infile);  
  709.                 if(ch == '=')  
  710.                 {  
  711.                     createNewNode("%=",OPE_DESC,COMPLETE_MOD,-1,line);  
  712.                 }  
  713.                 else  
  714.                 {  
  715.                     createNewNode("%",OPE_DESC,MOD,-1,line);  
  716.                     fseek(infile,-1L,SEEK_CUR);  
  717.                 }  
  718.             }  
  719.             //处理&开头的运算符  
  720.             else if(ch == '&')  
  721.             {  
  722.                 ch = fgetc(infile);  
  723.                 if(ch == '=')  
  724.                 {  
  725.                     createNewNode("&=",OPE_DESC,COMPLETE_BYTE_AND,-1,line);  
  726.                 }  
  727.                 else if(ch == '&')  
  728.                 {  
  729.                     createNewNode("&&",OPE_DESC,AND,-1,line);  
  730.                 }  
  731.                 else  
  732.                 {  
  733.                     createNewNode("&",OPE_DESC,BYTE_AND,-1,line);  
  734.                     fseek(infile,-1L,SEEK_CUR);  
  735.                 }  
  736.             }  
  737.             //处理~开头的运算符  
  738.             else if(ch == '~')  
  739.             {  
  740.                 ch = fgetc(infile);  
  741.                 if(ch == '=')  
  742.                 {  
  743.                     createNewNode("~=",OPE_DESC,COMPLETE_COMPLEMENT,-1,line);  
  744.                 }  
  745.                 else  
  746.                 {  
  747.                     createNewNode("~",OPE_DESC,COMPLEMENT,-1,line);  
  748.                     fseek(infile,-1L,SEEK_CUR);  
  749.                 }  
  750.             }  
  751.             //处理!开头的运算符  
  752.             else if(ch == '!')  
  753.             {  
  754.                 ch = fgetc(infile);  
  755.                 if(ch == '=')  
  756.                 {  
  757.                     createNewNode("!=",OPE_DESC,NOT_EQUAL,-1,line);  
  758.                 }  
  759.                 else  
  760.                 {  
  761.                     createNewNode("!",OPE_DESC,NOT,-1,line);  
  762.                     fseek(infile,-1L,SEEK_CUR);  
  763.                 }  
  764.             }  
  765.             //处理<开头的运算符  
  766.             else if(ch == '<')  
  767.             {  
  768.                 ch = fgetc(infile);  
  769.                 if(ch == '<')  
  770.                 {  
  771.                     createNewNode("<<",OPE_DESC,LEFT_MOVE,-1,line);  
  772.                 }  
  773.                 else if(ch == '=')  
  774.                 {  
  775.                     createNewNode("<=",OPE_DESC,LES_EQUAL,-1,line);  
  776.                 }  
  777.                 else  
  778.                 {  
  779.                     createNewNode("<",OPE_DESC,LES_THAN,-1,line);  
  780.                     fseek(infile,-1L,SEEK_CUR);  
  781.                 }  
  782.             }  
  783.             //处理>开头的运算符  
  784.             else if(ch == '>')  
  785.             {  
  786.                 ch = fgetc(infile);  
  787.                 if(ch == '>')  
  788.                 {  
  789.                     createNewNode(">>",OPE_DESC,RIGHT_MOVE,-1,line);  
  790.                 }  
  791.                 else if(ch == '=')  
  792.                 {  
  793.                     createNewNode(">=",OPE_DESC,GRT_EQUAL,-1,line);  
  794.                 }  
  795.                 else  
  796.                 {  
  797.                     createNewNode(">",OPE_DESC,GRT_THAN,-1,line);  
  798.                     fseek(infile,-1L,SEEK_CUR);  
  799.                 }  
  800.             }  
  801.             //处理|开头的运算符  
  802.             else if(ch == '|')  
  803.             {  
  804.                 ch = fgetc(infile);  
  805.                 if(ch == '|')  
  806.                 {  
  807.                     createNewNode("||",OPE_DESC,OR,-1,line);  
  808.                 }  
  809.                 else  
  810.                 {  
  811.                     createNewNode("|",OPE_DESC,BYTE_OR,-1,line);  
  812.                     fseek(infile,-1L,SEEK_CUR);  
  813.                 }  
  814.             }  
  815.             else if(ch == '=')  
  816.             {  
  817.                 ch = fgetc(infile);  
  818.                 if(ch == '=')  
  819.                 {  
  820.                     createNewNode("==",OPE_DESC,EQUAL,-1,line);  
  821.                 }  
  822.                 else  
  823.                 {  
  824.                     createNewNode("=",OPE_DESC,ASG,-1,line);  
  825.                     fseek(infile,-1L,SEEK_CUR);  
  826.                 }  
  827.             }  
  828.             else if(ch == '(')  
  829.             {  
  830.                 leftSmall++;  
  831.                 lineBra[0][leftSmall] = line;  
  832.                 createNewNode("(",CLE_OPE_DESC,LEFT_BRA,-1,line);  
  833.             }  
  834.             else if(ch == ')')  
  835.             {  
  836.                 rightSmall++;  
  837.                 lineBra[1][rightSmall] = line;  
  838.                 createNewNode(")",CLE_OPE_DESC,RIGHT_BRA,-1,line);  
  839.             }  
  840.             else if(ch == '[')  
  841.             {  
  842.                 leftMiddle++;  
  843.                 lineBra[2][leftMiddle] = line;  
  844.                 createNewNode("[",CLE_OPE_DESC,LEFT_INDEX,-1,line);  
  845.             }  
  846.             else if(ch == ']')  
  847.             {  
  848.                 rightMiddle++;  
  849.                 lineBra[3][rightMiddle] = line;  
  850.                 createNewNode("]",CLE_OPE_DESC,RIGHT_INDEX,-1,line);  
  851.             }  
  852.             else if(ch == '{')  
  853.             {  
  854.                 leftBig++;  
  855.                 lineBra[4][leftBig] = line;  
  856.                 createNewNode("{",CLE_OPE_DESC,L_BOUNDER,-1,line);  
  857.             }  
  858.             else if(ch == '}')  
  859.             {  
  860.                 rightBig++;  
  861.                 lineBra[5][rightBig] = line;  
  862.                 createNewNode("}",CLE_OPE_DESC,R_BOUNDER,-1,line);  
  863.             }  
  864.             else if(ch == '.')  
  865.             {  
  866.                 createNewNode(".",CLE_OPE_DESC,POINTER,-1,line);  
  867.             }  
  868.             else if(ch == ',')  
  869.             {  
  870.                 createNewNode(",",CLE_OPE_DESC,COMMA,-1,line);  
  871.             }  
  872.             else if(ch == ';')  
  873.             {  
  874.                 createNewNode(";",CLE_OPE_DESC,SEMI,-1,line);  
  875.             }  
  876.             else  
  877.             {  
  878.                 char temp[2];  
  879.                 temp[0] = ch;  
  880.                 temp[1] = '\0';  
  881.                 createNewError(temp,CHAR_ERROR,CHAR_ERROR_NUM,line);  
  882.             }  
  883.         }  
  884.         ch = fgetc(infile);  
  885.     }  
  886. }  
  887. void BraMappingError()  
  888. {  
  889.     if(leftSmall != rightSmall)  
  890.     {  
  891.         int i = (leftSmall>rightSmall) ? (leftSmall-rightSmall) : (rightSmall - leftSmall);  
  892.         bool  flag = (leftSmall>rightSmall) ? true : false;  
  893.         if(flag)  
  894.         {  
  895.             while(i--)  
  896.             {  
  897.                 createNewError(_NULL,LEFT_BRA_ERROR,LEFT_BRA_ERROR_NUM,lineBra[0][i+1]);  
  898.             }  
  899.         }  
  900.         else  
  901.         {  
  902.             while(i--)  
  903.             {  
  904.                 createNewError(_NULL,RIGHT_BRA_ERROR,RIGHT_BRA_ERROR_NUM,lineBra[1][i+1]);  
  905.             }  
  906.         }  
  907.     }  
  908.     if(leftMiddle != rightMiddle)  
  909.     {  
  910.         int i = (leftMiddle>rightMiddle) ? (leftMiddle-rightMiddle) : (rightMiddle - leftMiddle);  
  911.         bool flag = (leftMiddle>rightMiddle) ? true : false;  
  912.         if(flag)  
  913.         {  
  914.             while(i--)  
  915.             {  
  916.                 createNewError(_NULL,LEFT_INDEX_ERROR,LEFT_INDEX_ERROR_NUM,lineBra[2][i+1]);  
  917.             }  
  918.         }  
  919.         else  
  920.         {  
  921.             while(i--)  
  922.             {  
  923.                 createNewError(_NULL,RIGHT_INDEX_ERROR,RIGHT_INDEX_ERROR_NUM,lineBra[3][i+1]);  
  924.             }  
  925.         }  
  926.     }  
  927.     if(leftBig != rightBig)  
  928.     {  
  929.         int i = (leftBig>rightBig) ? (leftBig-rightBig) : (rightBig - leftSmall);  
  930.         bool flag = (leftBig>rightBig) ? true : false;  
  931.         if(flag)  
  932.         {  
  933.             while(i--)  
  934.             {  
  935.                 createNewError(_NULL,L_BOUNDER_ERROR,L_BOUNDER_ERROR_NUM,lineBra[4][i+1]);  
  936.             }  
  937.         }  
  938.         else  
  939.         {  
  940.             while(i--)  
  941.             {  
  942.                 createNewError(_NULL,R_BOUNDER_ERROR,R_BOUNDER_ERROR_NUM,lineBra[5][i+1]);  
  943.             }  
  944.         }  
  945.     }  
  946. }  
  947.   
  948. int main()  
  949. {  
  950.     initNode();  
  951.     scanner();  
  952.     BraMappingError();  
  953.     printNodeLink();  
  954.     printErrorLink();  
  955.     printIdentLink();  
  956.     close();  
  957.     return 0;  
  958. }  


测试的C文件:test.c(一个错误很多的C程序)

  1. #include          <stdio.h>  
  2. #include "my.h"  
  3. #define max 90  
  4. #de some  
  5.   
  6. int char main()  
  7. {  
  8.     8888char yn;  
  9.     do  
  10.     {  
  11.     int 9801;  
  12.     float 9.;  
  13.     double 9.ef;  
  14.     float -9.876;  
  15.     double hello.8.9;  
  16.     float 7.9e-5;  
  17.     int e-5;  
  18.     a /= 6;  
  19.         init(); /*初始化*/  
  20.         scanner();//扫描源程序//  
  21.         printf("Are You continue(y/n)\n");  
  22.         yn=getch();  
  23.     if(a == 7)  
  24.     {  
  25.           
  26.     }  
  27.     else  
  28.     {  
  29.           
  30.     }  
  31. @  
  32.   
  33.     }  
  34.     while(yn=='y'||yn=='Y');  
  35.       
  36.     return 0;  
  37. [hello  
  38.       
  39.   
  40.   
  41.   
  42. //  
  43.   
  44. //  
  45. //  
  46.       
  47.     printf("hello");  
  48.     /*我是头猪  
  49.       

程序运行结果:


  1. 请输入要进行语法分析的C语言程序:  
  2. test.c  
  3. ************************************分析表******************************  
  4.   
  5.                           内容      描述        种别码  地址    行号  
  6.                      <stdio.h>    头文件        130             1  
  7.                         "my.h"    头文件        130             2  
  8.                         max 90      常量        55              3  
  9.                            int    关键字        17              6  
  10.                           char    关键字        4               6  
  11.                           main    标志符        40      1       6  
  12.                              (    限界符        100             6  
  13.                              )    限界符        101             6  
  14.                              {    限界符        104             7  
  15.                           8888      常量        51              8  
  16.                           char    关键字        4               8  
  17.                             yn    标志符        40      2       8  
  18.                              ;    限界符        110             8  
  19.                             do    关键字        8               9  
  20.                              {    限界符        104             10  
  21.                            int    关键字        17              11  
  22.                           9801      常量        51              11  
  23.                              ;    限界符        110             11  
  24.                          float    关键字        13              12  
  25.                              ;    限界符        110             12  
  26.                         double    关键字        9               13  
  27.                              f    标志符        40      3       13  
  28.                              ;    限界符        110             13  
  29.                          float    关键字        13              14  
  30.                         -9.876      常量        53              14  
  31.                              ;    限界符        110             14  
  32.                         double    关键字        9               15  
  33.                          hello    标志符        40      4       15  
  34.                              .    限界符        106             15  
  35.                            8.9      常量        53              15  
  36.                              ;    限界符        110             15  
  37.                          float    关键字        13              16  
  38.                         7.9e-5      常量        53              16  
  39.                              ;    限界符        110             16  
  40.                            int    关键字        17              17  
  41.                              e    标志符        40      5       17  
  42.                             -5      常量        51              17  
  43.                              ;    限界符        110             17  
  44.                              a    标志符        40      6       18  
  45.                             /=    运算符        87              18  
  46.                              6      常量        51              18  
  47.                              ;    限界符        110             18  
  48.                           init    标志符        40      7       19  
  49.                              (    限界符        100             19  
  50.                              )    限界符        101             19  
  51.                              ;    限界符        110             19  
  52.                             无      注释        120             19  
  53.                        scanner    标志符        40      8       20  
  54.                              (    限界符        100             20  
  55.                              )    限界符        101             20  
  56.                              ;    限界符        110             20  
  57.                             无      注释        121             21  
  58.                         printf    标志符        40      9       21  
  59.                              (    限界符        100             21  
  60.                              "    限界符        112             21  
  61.        Are You continue(y/n)\n      常量        54              21  
  62.                              "    限界符        112             21  
  63.                              )    限界符        101             21  
  64.                              ;    限界符        110             21  
  65.                             yn    标志符        40      2       22  
  66.                              =    运算符        72              22  
  67.                          getch    标志符        40      10      22  
  68.                              (    限界符        100             22  
  69.                              )    限界符        101             22  
  70.                              ;    限界符        110             22  
  71.                             if    关键字        16              23  
  72.                              (    限界符        100             23  
  73.                              a    标志符        40      6       23  
  74.                             ==    运算符        80              23  
  75.                              7      常量        51              23  
  76.                              )    限界符        101             23  
  77.                              {    限界符        104             24  
  78.                              }    限界符        105             26  
  79.                           else    关键字        10              27  
  80.                              {    限界符        104             28  
  81.                              }    限界符        105             30  
  82.                              }    限界符        105             33  
  83.                          while    关键字        32              34  
  84.                              (    限界符        100             34  
  85.                             yn    标志符        40      2       34  
  86.                             ==    运算符        80              34  
  87.                              '    限界符        111             34  
  88.                              y      常量        52              34  
  89.                              '    限界符        111             34  
  90.                             ||    运算符        83              34  
  91.                             yn    标志符        40      2       34  
  92.                             ==    运算符        80              34  
  93.                              '    限界符        111             34  
  94.                              Y      常量        52              34  
  95.                              '    限界符        111             34  
  96.                              )    限界符        101             34  
  97.                              ;    限界符        110             34  
  98.                         return    关键字        20              36  
  99.                              0      常量        51              36  
  100.                              ;    限界符        110             36  
  101.                              [    限界符        102             37  
  102.                          hello    标志符        40      4       37  
  103.                             无      注释        121             43  
  104.                             无      注释        121             45  
  105.                             无      注释        121             46  
  106.                         printf    标志符        40      9       47  
  107.                              (    限界符        100             47  
  108.                              "    限界符        112             47  
  109.                          hello      常量        54              47  
  110.                              "    限界符        112             47  
  111.                              )    限界符        101             47  
  112.                              ;    限界符        110             47  
  113.   
  114.   
  115. ************************************错误表******************************  
  116.   
  117.       内容                          描述        类型    行号  
  118.   #de some                    预处理错误        13      4  
  119.         9.                 float表示错误        1       12  
  120.        9.e                double表示错误        2       13  
  121.          @                      非法字符        6       31  
  122.         无                注释没有结束符        3       49  
  123.         无                 '['没有对应项        9       37  
  124.         无                 '{'没有对应项        11      7  
  125.   
  126.   
  127. ************************************标志符表******************************  
  128.   
  129.                           内容      描述        种别码  地址    行号  
  130.                           main    标志符        40      1       6  
  131.                             yn    标志符        40      2       8  
  132.                              f    标志符        40      3       13  
  133.                          hello    标志符        40      4       15  
  134.                              e    标志符        40      5       17  
  135.                              a    标志符        40      6       18  
  136.                           init    标志符        40      7       19  
  137.                        scanner    标志符        40      8       20  
  138.                         printf    标志符        40      9       21  
  139.                             yn    标志符        40      2       22  
  140.                          getch    标志符        40      10      22  
  141.                              a    标志符        40      6       23  
  142.                             yn    标志符        40      2       34  
  143.                             yn    标志符        40      2       34  
  144.                          hello    标志符        40      4       37  
  145.                         printf    标志符        40      9       47  
  146.   
  147.   
  148.   
  149. Process returned 0 (0x0)   execution time : 5.629 s  
  150. Press any key to continue. 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值