编译原理之词法分析和语法分析

来源:互联网 发布:康耐视视觉检测软件 编辑:程序博客网 时间:2024/06/09 20:25

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的。代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码。from sdu


lexAnalysis.h

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * lexAnalysis.h 
  3.  * 
  4.  *  Created on: 2014-12-2 
  5.  *      Author: liuqiushan 
  6.  */  
  7.   
  8. #ifndef LEXANALYSIS_H_  
  9. #define LEXANALYSIS_H_  
  10.   
  11.   
  12. #include <stdio.h>  
  13. #include <stdlib.h>  
  14. #include <string.h>  
  15.   
  16. typedef enum _SYM  
  17. {  
  18.         _CONST,  
  19.         _VAR,  
  20.         _procedure,  
  21.         _begin,  
  22.         _end,  
  23.         _if,  
  24.         _then,  
  25.         _ID, // such as the 'a' in 'var a;'  
  26.         _INT, // such as the '10' in 'const a = 10;'  
  27.         _ASSIGN,// '='  
  28.         _PLUS,// '+'  
  29.         _SUB,// '-'  
  30.         _STAR,// '*'  
  31.         _DIV,// '/'  
  32.         _LESS,// '<'  
  33.         _MORE,// '>'  
  34.         _LESSEQ,// '<='  
  35.         _MOREEQ,// '>='  
  36.         _DH,// ','  
  37.         _MD,// ':='  
  38.         _LEFT,// '('  
  39.         _RIGHT,// ')'  
  40.         _JH,// '#'  
  41.         _FH// ‘;’  
  42. }SYM;  
  43.   
  44. SYM getSYM(char* str);  
  45.   
  46. void appendStr(char* str, char* c, int p_str);  
  47.   
  48. int isABC(char* c);  
  49.   
  50. int isNumber(char* c);  
  51.   
  52. #endif /* LEXANALYSIS_H_ */  


LexAnalysis.c

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * LexAnalysis.c 
  3.  * 
  4.  *  Created on: 2014-12-2 
  5.  *      Author: liuqiushan 
  6.  */  
  7.   
  8. #include "lexAnalysis.h"  
  9.   
  10. SYM getSYM(char* _str)  
  11. {  
  12.     SYM temp = _ID; // default identifier  
  13.     if(!strcasecmp(_str, "CONST"))  
  14.         temp = _CONST;  
  15.     else if(!strcasecmp(_str, "VAR"))  
  16.         temp = _VAR;  
  17.     else if(!strcasecmp(_str, "procedure"))  
  18.             temp = _procedure;  
  19.     else if(!strcasecmp(_str, "begin"))  
  20.                 temp = _begin;  
  21.     else if(!strcasecmp(_str, "end"))  
  22.                 temp = _end;  
  23.     else if(!strcasecmp(_str, "if"))  
  24.                     temp = _if;  
  25.     else if(!strcasecmp(_str, "then"))  
  26.                     temp = _then;  
  27.   
  28.     return temp;  
  29. }  
  30.   
  31. void appendStr(char str[], char* c, int p_str )  
  32. {  
  33.     str[p_str] = *c;  
  34. }  
  35.   
  36. int isABC(char* c)  
  37. {  
  38.     char ch = *c;  
  39.   
  40.     if(ch=='q'||ch=='w'||ch=='e'||ch=='r'||ch=='t'||ch=='y'||ch=='u'||ch=='i'||ch=='o'||ch=='p'||  
  41.                     ch=='a'||ch=='s'||ch=='d'||ch=='f'||ch=='g'||ch=='h'||ch=='j'||ch=='k'||ch=='l'||  
  42.                     ch=='z'||ch=='x'||ch=='c'||ch=='v'||ch=='b'||ch=='n'||ch=='m'||ch=='Q'||ch=='W'||  
  43.                     ch=='E'||ch=='R'||ch=='T'||ch=='Y'||ch=='U'||ch=='I'||ch=='O'||ch=='P'||ch=='A'||  
  44.                     ch=='S'||ch=='D'||ch=='F'||ch=='G'||ch=='H'||ch=='J'||ch=='K'||ch=='L'||ch=='Z'||  
  45.                     ch=='X'||ch=='C'||ch=='V'||ch=='B'||ch=='N'||ch=='M')  
  46.                 return 1;  
  47.             else  
  48.                 return 0;  
  49. }  
  50.   
  51. int isNumber(char* c)  
  52. {  
  53.     char ch = *c;  
  54.   
  55.     if(ch=='1'||ch=='2'||ch=='3'||ch=='4'||ch=='5'||ch=='6'||ch=='7'||ch=='8'||ch=='9'||ch=='0')  
  56.                 return 1;  
  57.             else  
  58.                 return 0;  
  59. }  


synAnalysis.h

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  * synAnalysis.h 
  3.  * 
  4.  *  Created on: 2014-12-2 
  5.  *      Author: liuqiushan 
  6.  */  
  7.   
  8. #ifndef SYNANALYSIS_H_  
  9. #define SYNANALYSIS_H_  
  10.   
  11. typedef enum _KIND  
  12. {  
  13.     PRO,//procedure  
  14.     CON,//constant  
  15.     VAR //variable  
  16. }CVPKind;  
  17.   
  18. /* 
  19.  * PL/0 Object Instruction 
  20.  * 
  21.  * There are three domains: 
  22.  * 
  23.  * f is the function code 
  24.  * l is the difference between the declared level and the invoked level of the variable 
  25.  * 
  26.  * ----------------------------- 
  27.  * |           |       |       | 
  28.  * |     f     |   l   |   a   | 
  29.  * |           |       |       | 
  30.  * ----------------------------- 
  31.  */  
  32. typedef enum _FunctionCode  
  33. {  
  34.     LIT,//① LIT: put the constant on the top of the stack, a is the constant  
  35.     LOD,//② LOD: put the variable on the top of the stack, a is the address  
  36.     STO,//③ STO: put the content on the top of the stack into a variable. such as c := b + 10  
  37.     CAL,//④ CAL  
  38.     INT,//⑤ INT: create the data area, and a is the number of the area  
  39.     JMP,//⑥ JMP  
  40.     JPC,//⑦ JPC  
  41.     OPR//⑧ OPR: operation, and the type is delivered by a. And the operation objects are the top of the stack and the next top of the stack  
  42.   
  43. }FunctionCode;  
  44.   
  45. typedef enum _OPR  
  46. {  
  47.     ADD = 1, //+  
  48.     SUB,     //-  
  49.     MUL,     //*  
  50.     DIV,     // /  
  51.     GT,  
  52.     LT,  
  53.     GE,  
  54.     LE,  
  55.     UE,  
  56.     EQ,  
  57.     WRITE,  
  58.     READ,  
  59.     MINUS  
  60. }OPRTYPE;  
  61.   
  62. typedef struct _TableItem  
  63. {  
  64.     char* name;  
  65.     CVPKind kind;  
  66.     int level;  
  67.     char* address;  
  68. }CVPTableItem;  
  69.   
  70. typedef struct _Instruct  
  71. {  
  72.     FunctionCode f;  
  73.     int l;  
  74.     int a;  
  75. }ObjectInstruct;  
  76.   
  77.   
  78. #endif /* SYNANALYSIS_H_ */  


SynAnalysis.c

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /* 
  2.  ============================================================================ 
  3.  Name        : SynAnalysis.c 
  4.  Author      : liuqiushan 
  5.  Date        : Dec. 2, 2014 18:16 
  6.  Version     : 1.0 
  7.  Copyright   : Shandong University 
  8.  Description : Syntax Analysis 
  9.  ============================================================================ 
  10.  */  
  11.   
  12. /* 
  13.  * Expression EBNF 
  14.  *-------------------------------------------- 
  15.  *| Expression -> Term { Addop Term }        | 
  16.  *| Addop -> "+" | "-"                       | 
  17.  *| Term -> Factor { Mulop Factor }          | 
  18.  *| Mulop -> "*" | "/"                       | 
  19.  *| Factor -> ID | NUM | "(" Expression ")"  | 
  20.  *-------------------------------------------- 
  21.  */  
  22.   
  23. /* 
  24.  * Pl/0 Statements to be analyzed 
  25.  *-------------------------------------------- 
  26.  *| const a=10                               | 
  27.  *| var b,c                                  | 
  28.  *| procedure p                              | 
  29.  *| begin                                    | 
  30.  *|   c:=b+a                                 | 
  31.  *| end                                      | 
  32.  *-------------------------------------------- 
  33.  */  
  34.   
  35. #include "lexAnalysis.h"  
  36. #include "synAnalysis.h"  
  37.   
  38. // Data Structure  
  39. typedef struct Statement  
  40. {  
  41.     char* _statement;  
  42.     int _length; // the length of the statement  
  43.     int _locate_pointer; // default point to the first character  
  44. }P_Statement;  
  45.   
  46.   
  47. // Methods  
  48. void putsStatements(void);  
  49. void initStatements(void);  
  50. void binding(P_Statement* p_s, char* statement);  
  51. void lexical_Analysis(char* a, int len_a);  
  52. void printLexResults(void);  
  53. SYM getNextSYMToken();  
  54. char* getNextID();  
  55. char* getNextNumber();  
  56. void levelProcess(int level);  
  57. void processConstant(int level);  
  58. int processVariable(int level);  
  59. void processProcedure(int level);  
  60. void strcpyCVPTable(CVPTableItem* cvp, char* name, char* address);  
  61. void printSynResults(void);  
  62. int str2int(char *str);  
  63. void GEN(FunctionCode f, int l, int a);  
  64. void Sentence(int level);  
  65. void EBNFExpression(int level);  
  66. int getIndexCVP(char* id);  
  67. void Term(int level);  
  68. void Factor(int level);  
  69.   
  70.   
  71. /*  Global Variables */  
  72.   
  73. // Information about the statements set  
  74. #define statementNum 6  
  75. char* statements[statementNum] = {  
  76.         "const a=10",  
  77.         "var b,c",  
  78.         "procedure p",  
  79.         "begin",  
  80.         "c:=b+a",  
  81.         "end"  
  82. };  
  83.   
  84.   
  85. // Contain those statements to be analyzed  
  86. P_Statement statementSet[statementNum];  
  87.   
  88. // For lexical analysis  
  89. #define MAX 100  
  90. SYM array_SYM[MAX]; // SYM array for lexical analysis  
  91. int p_a_SYM = 0; // SYM array location pointer  
  92.   
  93. char array_Id[MAX][MAX]; // identifier array for lexical analysis  
  94. int p_a_Id = 0; // identifier array location pointer  
  95.   
  96. char array_Num[MAX][MAX]; // number array for lexical analysis  
  97. int p_a_Num = 0; // number array location pointer  
  98.   
  99. // Token acquired during lexical analysis  
  100. char str[MAX] = ""// current token to be analyzed  
  101. int p_str = 0; // token inner location pointer  
  102.   
  103.   
  104. /* For Syntax Analysis */  
  105. // Token acquired during syntax analysis  
  106. SYM _currentSYMToken;  
  107. int currentPointer = 0;  
  108.   
  109. char* _currentID;  
  110. int currentPointerID = 0;  
  111.   
  112. char* _currentNumber;  
  113. int currentPointerNumber = 0;  
  114.   
  115. int level = 0; //It indicates which level is under processing, and also the level is just the main level.  
  116.   
  117. CVPTableItem cvptable[MAX]; // used to record every element, and we need the table to show which elements (including constant, variable and procedure) are in the program  
  118. int p_table = 0; // the appending pointer of cvptable  
  119.   
  120. int addrVar = 3; // the initial address for the first variable is 3  
  121.   
  122. // the following two are used for the address of procedure. In fact up to now, I do not their meaning.  
  123. int indexW = 0;  
  124. int offset = 1;  
  125.   
  126. ObjectInstruct CODE[MAX]; // recording the generated intermediate code  
  127. int p_code = 0; // the appending pointer of CODE  
  128.   
  129. OPRTYPE type_opr; // Expression operation type  
  130.   
  131. // Main  
  132. int main(void) {  
  133.   
  134.     puts("====================Initial=====================");  
  135.   
  136.     putsStatements(); // print which statements need to be analyzed  
  137.   
  138.     initStatements(); // initial all the statements to be analyzed with the struct P_Statement  
  139.   
  140.     // start lexical analysis  
  141.     puts("================Lexical Analysis================");  
  142.     int i;  
  143.     for (i = 0; i < statementNum; i++) {  
  144.         lexical_Analysis(statementSet[i]._statement, statementSet[i]._length);  
  145.     }  
  146.     array_SYM[p_a_SYM] = -1;// end with -1  
  147.   
  148.     // print the results of lexical analysis  
  149.     printLexResults();  
  150.   
  151.   
  152.     // Now let us start Syntax Analysis, just enjoy it  
  153.     puts("================Syntax Analysis================");  
  154.     _currentSYMToken = getNextSYMToken();  
  155.   
  156.     levelProcess(level);  
  157.   
  158.     //print the results of syntax analysis  
  159.     printSynResults();  
  160.   
  161.     return EXIT_SUCCESS;  
  162. }  
  163.   
  164. // Implementation  
  165.   
  166. void putsStatements(void)  
  167. {  
  168.     puts("Analyzing the following statements: ");  
  169.     puts("");  
  170.     int i;  
  171.     for (i = 0; i < statementNum; i++)  
  172.     {  
  173.         puts(statements[i]);  
  174.     }  
  175. }  
  176.   
  177. void initStatements(void)  
  178. {  
  179.     int i;  
  180.     for (i = 0; i < statementNum; i++)  
  181.         binding(&statementSet[i], statements[i]);  
  182. }  
  183.   
  184. void binding(P_Statement* p_s, char* statement)  
  185. {  
  186.     // calculate the length of statement;  
  187.     int len = strlen(statement);  
  188.   
  189.     p_s->_statement = malloc(len*sizeof(char));  
  190.     strcpy(p_s->_statement, statement);  
  191.     p_s->_length = len;  
  192.     p_s->_locate_pointer = 0;  
  193.   
  194.     // testing  
  195.     // printf("%s\n", p_s->_statement);  
  196.     // printf("%d\n", p_s->_length);  
  197. }  
  198.   
  199. // Lexical Analysis Main Program  
  200. void lexical_Analysis(char* a, int len_a)  
  201. {  
  202.     int i;  
  203.     for (i = 0; i < len_a; i++) {  
  204.         // Only get one character each time  
  205.         if (a[i]==' ')  
  206.             continue;  
  207.         // Finite Automation Method  
  208.         if (isABC(&a[i])) // If the first character is letter  
  209.         {  
  210.             while (isABC(&a[i])||isNumber(&a[i]))  
  211.             {  
  212.                 appendStr(str, &a[i], p_str);  
  213.                 p_str++;  
  214.                 i++;  
  215.                 if (i == len_a)  
  216.                     break;  
  217.             }  
  218.             i--;  
  219.   
  220.             SYM code = getSYM(str);  
  221.   
  222.             //either identifier or keyword  
  223.             if (code == _ID)  
  224.             {  
  225.                 array_SYM[p_a_SYM] = _ID;  
  226.                 p_a_SYM++;  
  227.                 strcpy(array_Id[p_a_Id], str);  
  228.                 p_a_Id++;  
  229.             } else { // keyword or reserved word of Pl/0  
  230.                 array_SYM[p_a_SYM] = code;  
  231.                 p_a_SYM++;  
  232.             }  
  233.   
  234.             // before next one, clean them  
  235.             memset(str, 0, sizeof(str));  
  236.             p_str = 0;  
  237.   
  238.         } else if (isNumber(&a[i])) // If the first character is number  
  239.         {  
  240.             while (isNumber(&a[i]))  
  241.             {  
  242.                 appendStr(str, &a[i], p_str);  
  243.                 p_str++;  
  244.                 i++;  
  245.                 if (i == len_a)  
  246.                     break;  
  247.             }  
  248.             i--;  
  249.   
  250.             array_SYM[p_a_SYM] = _INT;  
  251.             p_a_SYM++;  
  252.             strcpy(array_Num[p_a_Num], str);  
  253.             p_a_Num++;  
  254.   
  255.             // before next one, clean them  
  256.             memset(str, 0, sizeof(str));  
  257.             p_str = 0;  
  258.   
  259.         } else if (a[i] == '=') {  
  260.             array_SYM[p_a_SYM] = _ASSIGN;  
  261.             p_a_SYM++;  
  262.         } else if (a[i] == ',') {  
  263.             array_SYM[p_a_SYM] = _DH;  
  264.             p_a_SYM++;  
  265.         } else if (a[i] == ':') {  
  266.             i++;  
  267.             if (a[i] == '=')  
  268.             {  
  269.                 array_SYM[p_a_SYM] = _MD;  
  270.                 p_a_SYM++;  
  271.             }  
  272.         } else if (a[i] == '+') {  
  273.             array_SYM[p_a_SYM] = _PLUS;  
  274.             p_a_SYM++;  
  275.         }  
  276.   
  277.     }  
  278.   
  279.     // print the results of lexical analysis  
  280.     //printLexResults();  
  281.   
  282. }  
  283.   
  284. void printLexResults(void)  
  285. {  
  286.     int i;  
  287.     puts("============Lexical Analysis Results================");  
  288.     printf("SYM: [ ");  
  289.     for (i = 0; i < p_a_SYM; i++)  
  290.     {  
  291.         switch(array_SYM[i])  
  292.         {  
  293.         case 0: printf("_CONST "); break;  
  294.         case 1: printf("_VAR "); break;  
  295.         case 2: printf("_procedure "); break;  
  296.         case 3: printf("_begin "); break;  
  297.         case 4: printf("_end "); break;  
  298.         case 5: printf("_if "); break;  
  299.         case 6: printf("_then "); break;  
  300.         case 7: printf("_ID "); break;  
  301.         case 8: printf("_INT "); break;  
  302.         case 9: printf("_ASSIGN "); break;  
  303.         case 10: printf("_PLUS "); break;  
  304.         case 11: printf("_SUB "); break;  
  305.         case 12: printf("_STAR "); break;  
  306.         case 13: printf("_DIV "); break;  
  307.         case 14: printf("_LESS "); break;  
  308.         case 15: printf("_MORE "); break;  
  309.         case 16: printf("_LESSEQ "); break;  
  310.         case 17: printf("_MOREEQ "); break;  
  311.         case 18: printf("_DH "); break;  
  312.         case 19: printf("_MD "); break;  
  313.         case 20: printf("_LEFT "); break;  
  314.         case 21: printf("_RIGHT "); break;  
  315.         case 22: printf("_JH "); break;  
  316.         case 23: printf("_FH "); break;  
  317.         }  
  318.     }  
  319.     printf("]\n");  
  320.   
  321.   
  322.     printf("ID: [ ");  
  323.     for (i = 0; i < p_a_Id; i++)  
  324.         printf("%s ", array_Id[i]);  
  325.     printf("]\n");  
  326.   
  327.     printf("NUM: [ ");  
  328.     for (i = 0; i < p_a_Num; i++)  
  329.         printf("%s ", array_Num[i]);  
  330.     printf("]\n");  
  331.   
  332. }  
  333.   
  334. SYM getNextSYMToken()  
  335. {  
  336.     return array_SYM[currentPointer++];  
  337. }  
  338.   
  339. char* getNextID()  
  340. {  
  341.     return array_Id[currentPointerID++];  
  342. }  
  343.   
  344. char* getNextNumber()  
  345. {  
  346.     return array_Num[currentPointerNumber++];  
  347. }  
  348.   
  349. void levelProcess(int level)  
  350. {  
  351.     int countVar = 0; // record the number of variables in one level  
  352.   
  353.     if (_currentSYMToken != -1)  
  354.     {  
  355.         if (_currentSYMToken == _CONST) // Constant  
  356.         {  
  357.             processConstant(level);  
  358.             if ((_currentSYMToken=getNextSYMToken())==-1)  
  359.                 return;  
  360.         }  
  361.         if (_currentSYMToken == _VAR) // variables follow constant in our example  
  362.         {  
  363.             countVar = processVariable(level);  
  364.         }  
  365.         if (_currentSYMToken == _procedure) // procedure follows variables in our example  
  366.         {  
  367.             _currentSYMToken = getNextSYMToken(); // get the identifier of the procedure  
  368.             processProcedure(level);  
  369.         }  
  370.     }  
  371.   
  372.     GEN(INT, 0, 3+countVar); // Create the specified number area. Because we designed addrVar 3, so we plus 3  
  373.     Sentence(level);  
  374.     GEN(OPR, 0, 0); // quit the data area  
  375. }  
  376.   
  377. void processConstant(int level)  
  378. {  
  379.     if ((_currentSYMToken=getNextSYMToken())!=-1&&_currentSYMToken==_ID) // a  
  380.         if ((_currentSYMToken=getNextSYMToken())!=-1&&_currentSYMToken==_ASSIGN) // =  
  381.             if ((_currentSYMToken=getNextSYMToken())!=-1&&_currentSYMToken==_INT) // 10  
  382.                 if ((_currentID=getNextID())!=NULL) // get the identifier  
  383.                     if ((_currentNumber=getNextNumber())!=NULL) // get the number  
  384.                     {  
  385.                         strcpyCVPTable(&cvptable[p_table], _currentID, _currentNumber);  
  386.                         cvptable[p_table].kind = CON;  
  387.                         cvptable[p_table].level = level;  
  388.   
  389.                         // Do not forget to add p_table  
  390.                         p_table++;  
  391.                     }  
  392. }  
  393.   
  394. int processVariable(int level)  
  395. {  
  396.     int count = 0; // record the number of variables  
  397.   
  398.     if ((_currentSYMToken=getNextSYMToken())!=-1&&_currentSYMToken==_ID)  
  399.         if ((_currentID=getNextID())!=NULL) // get the identifier  
  400.         {  
  401.             count++;  
  402.             char str[MAX];  
  403.             sprintf(str, "%d", addrVar);  
  404.             strcpyCVPTable(&cvptable[p_table], _currentID, str);  
  405.             cvptable[p_table].kind = VAR;  
  406.             cvptable[p_table].level = level;  
  407.   
  408.             addrVar++;  
  409.   
  410.             // Do not forget to add p_table  
  411.             p_table++;  
  412.         }  
  413.     // Maybe we could meet such var a,b  
  414.     while((_currentSYMToken=getNextSYMToken())!=-1&&_currentSYMToken==_DH)  
  415.     {  
  416.         if ((_currentSYMToken=getNextSYMToken())!=-1&&_currentSYMToken==_ID)  
  417.             if ((_currentID=getNextID())!=NULL) // get the identifier  
  418.             {  
  419.                 count++;  
  420.                 char str[MAX];  
  421.                 sprintf(str, "%d", addrVar);  
  422.                 strcpyCVPTable(&cvptable[p_table], _currentID, str);  
  423.                 cvptable[p_table].kind = VAR;  
  424.                 cvptable[p_table].level = level;  
  425.   
  426.                 addrVar++;  
  427.   
  428.                 // Do not forget to add p_table  
  429.                 p_table++;  
  430.             }  
  431.     }  
  432.   
  433.     return count;  
  434. }  
  435.   
  436. void processProcedure(int level)  
  437. {  
  438.     if (_currentSYMToken!=-1&&_currentSYMToken==_ID)  
  439.         if ((_currentID=getNextID())!=NULL) // get the identifier of the procedure  
  440.         {  
  441.             char str[MAX];  
  442.             int temp = indexW + offset;  
  443.             sprintf(str, "%d", temp);  
  444.             strcpyCVPTable(&cvptable[p_table], _currentID, str);  
  445.             cvptable[p_table].kind = PRO;  
  446.             cvptable[p_table].level = level;  
  447.   
  448.             // Do not forget to add p_table  
  449.             p_table++;  
  450.         }  
  451.   
  452.     //  IMPORTANT PHASE: SUBLEVEL  
  453.     _currentSYMToken = getNextSYMToken(); // in our example it should be begin  
  454.     levelProcess(level + 1); // Recursive-descent Parsing  
  455.   
  456. }  
  457.   
  458. void strcpyCVPTable(CVPTableItem* cvp, char* name, char* address)  
  459. {  
  460.         int len_N = strlen(name);  
  461.         int len_A = strlen(address);  
  462.   
  463.         cvp->name = (char*)malloc(len_N*sizeof(char));  
  464.         cvp->address = (char*)malloc(len_A*sizeof(char));  
  465.         strcpy(cvp->name, name);  
  466.         strcpy(cvp->address, address);  
  467. }  
  468.   
  469. void printSynResults(void)  
  470. {  
  471.     int i;  
  472.     puts("============Syntax Analysis Results================");  
  473.     puts("The Table of Constant, Variable and Procedure");  
  474.     puts("Name\tKind\tLevel\tAddress\t");  
  475.     for (i = 0; i < p_table; i++)  
  476.     {  
  477.         //printf("%s\t%d\t%d\t%s\n", cvptable[i].name, cvptable[i].kind, cvptable[i].level, cvptable[i].address);  
  478.         printf("%s\t", cvptable[i].name);  
  479.         switch(cvptable[i].kind) {  
  480.         case CON: printf("CON\t"); break;  
  481.         case VAR: printf("VAR\t"); break;  
  482.         case PRO: printf("PRO\t"); break;  
  483.         }  
  484.         printf("%d\t%s\n", cvptable[i].level, cvptable[i].address);  
  485.     }  
  486.   
  487.     puts("");  
  488.     puts("Intermediate Code");  
  489.     puts("No.\tFunction Code\tLevel Difference\tDisplacement");  
  490.     for (i = 0; i < p_code; i++)  
  491.     {  
  492.         printf("%d\t", i);  
  493.         switch(CODE[i].f)  
  494.         {  
  495.         case LIT: printf("LIT\t"); break;  
  496.         case INT: printf("INT\t"); break;  
  497.         case LOD: printf("LOD\t"); break;  
  498.         case STO: printf("STO\t"); break;  
  499.         case CAL: printf("CAL\t"); break;  
  500.         case JMP: printf("JMP\t"); break;  
  501.         case JPC: printf("JPC\t"); break;  
  502.         case OPR: printf("OPR\t"); break;  
  503.         }  
  504.         printf("\t%d\t\t\t%d\n", CODE[i].l, CODE[i].a);  
  505.     }  
  506.   
  507. }  
  508.   
  509. int str2int(char *str)  
  510. {  
  511.     int v = 0;  
  512.     do {  
  513.         v = 10*v+*str-'0';  
  514.         str++;  
  515.     } while((*str>='0')&&(*str<='9'));  
  516.     return v;  
  517. }  
  518.   
  519. // To generate the object instruct  
  520. void GEN(FunctionCode f, int l, int a)  
  521. {  
  522.     CODE[p_code].f = f;  
  523.     CODE[p_code].l = l;  
  524.     CODE[p_code].a = a;  
  525.   
  526.     p_code++;  
  527. }  
  528.   
  529. void Sentence(int level)  
  530. {  
  531.     // Here I just implement begin and Assignment i.e. _MD(:=)  
  532.     if (_currentSYMToken != -1)  
  533.     {  
  534.         if (_currentSYMToken ==_begin)  
  535.         {  
  536.             _currentSYMToken = getNextSYMToken();  
  537.             Sentence(level);// recurse with the sub-sentence of the sentence (i.e. nest), but they are in the same level  
  538.   
  539.             while(_currentSYMToken != -1)  
  540.             {  
  541.                 if (_currentSYMToken == _end)  
  542.                 {  
  543.                     _currentSYMToken = getNextSYMToken(); // in our example, this is the end of SYM table. it should be -1  
  544.                     return;  
  545.                 }  
  546.             }  
  547.         } else if (_currentSYMToken == _ID) // Assignment  
  548.         {  
  549.             _currentID = getNextID(); // I omit the variables valid checking, but we sill need to find it in cvptable  
  550.   
  551.             int cvpIndex = getIndexCVP(_currentID); // Just find its index in cvptable  
  552.   
  553.             if((_currentSYMToken=getNextSYMToken())!=-1&&_currentSYMToken==_MD) // assignment symbol  
  554.             {  
  555.                 _currentSYMToken = getNextSYMToken();  
  556.                 EBNFExpression(level);  
  557.                 GEN(STO, level-cvptable[cvpIndex].level, str2int(cvptable[cvpIndex].address));  
  558.                 return// assignment over  
  559.             }  
  560.         }  
  561.     }  
  562. }  
  563.   
  564. void EBNFExpression(int level)  
  565. {  
  566.     Term(level); // the level + and -  
  567.   
  568.     // Here we implement + and -  
  569.     while((_currentSYMToken=getNextSYMToken())!=-1)  
  570.     {  
  571.         if (_currentSYMToken == _SUB || _currentSYMToken == _PLUS)  
  572.         {  
  573.             if (_currentSYMToken == _SUB)  
  574.                 type_opr = SUB;  
  575.             else  
  576.                 type_opr = ADD;  
  577.   
  578.             _currentSYMToken = getNextSYMToken(); // next term  
  579.             Term(level);  
  580.             GEN(OPR, 0, type_opr);  
  581.         }  
  582.     }  
  583. }  
  584.   
  585. int getIndexCVP(char* id)  
  586. {  
  587.     int i;  
  588.     for (i = 0; i < p_table; i++)  
  589.     {  
  590.         if(!strcmp(cvptable[i].name, id))  
  591.             break;  
  592.     }  
  593.   
  594.     return i;  
  595. }  
  596.   
  597. void Term(int level)  
  598. {  
  599.     Factor(level); // the level of * and /  
  600.   
  601.     // we omit * and /  
  602. }  
  603.   
  604. void Factor(int level)  
  605. {  
  606.     // In fact, we omit '(' and ')', but it is easy to implement it by recursing with EBNFExpression  
  607.     if(_currentSYMToken!=-1&&_currentSYMToken==_ID)  
  608.     {  
  609.         _currentID = getNextID();  
  610.         int cvpIndex = getIndexCVP(_currentID); // Just find its index in cvptable  
  611.   
  612.         if(cvptable[cvpIndex].kind == VAR) // type checking  
  613.         {  
  614.             GEN(LOD, level-cvptable[cvpIndex].level, str2int(cvptable[cvpIndex].address));  
  615.         } else if (cvptable[cvpIndex].kind == CON) {  
  616.             GEN(LIT, 0, str2int(cvptable[cvpIndex].address));  
  617.         }  
  618.     }  
  619. }  


实验结果:

0 0
原创粉丝点击