四则表达式的编译过程及生成汇编代码

1、前序

这是编译原理的实验,自认为是上大学以来做过的最难的一个实验。所以写篇博客记录一下。

实验用到的基础知识:C语言、数据结构、汇编(只需简单的了解)。

开发工具:VC

 

2、问题描述

编译整数四则运算表达式,将整数四则运算表达式翻译为汇编语言代码。

消除左递归后的文法:

E→TE'

E'→+TE' |ε

T→FT'

T'→*FT' |ε

F→(E) | i

消除左递归后的翻译模式:

E ::=     T    {E'.i:=T.nptr}

E'    {E.nptr:=E'.s}

E'::=      + T  {E'1.i:=mknode(‘+’,E'.i,T.nptr)}

E'1   {E'.s:=E1.s}

E'::=       - T   {E'1.i:=mknode(‘-’,E'.i,T.nptr)}

E'1   {E'.s:=E1.s}

E'::=      ε     {E'.s:= E'.i}

T ::=      F    {T'.i:=F.nptr}

T'    {T.nptr:=T'.s}

T'::=      * F  {T'1.i:=mknode(‘*’,T'.i,F.nptr)}

T'1   {T'.s:=T1.s}

T'::=      / F   {T'1.i:=mknode(‘/’,T'.i,F.nptr)}

T'1   {T'.s:=T1.s}

T' ::= ε  {T'.s:= T'.i}

F ::= (E) {F.nptr:=E.nptr}

F ::= num {F.nptr:=mkleaf(num,num.val)}

 

3、全局定义

test.c文件

[cpp] view plain copy
 
  1. #ifndef TEST_C  
  2. #define TEST_C  
  3.   
  4. /** 
  5.   * 全局变量和全局函数文件 
  6.   **/  
  7. #include<stdio.h>  
  8. #include<ctype.h>  
  9. #include<string.h>  
  10. #include<stdlib.h>  
  11.   
  12. /************************* 以下是全局变量(函数)的定义 *******************/  
  13.   
  14. //输入的表达式最大长度,可以看做是缓冲区的长度  
  15. #define MAX_EXPRESSION_LENGTH 50  
  16.   
  17. //存放输入的表达式  
  18. char expression[MAX_EXPRESSION_LENGTH];  
  19.   
  20. //表达式字符数组的下标  
  21. int expression_index=0;  
  22.   
  23. //存放一个单词符号  
  24. char strToken[MAX_EXPRESSION_LENGTH/2];  
  25.   
  26. //判断是否是数字  
  27. int isNum(char * strToken)  
  28. {  
  29.     int i=0;  
  30.     while(strToken[i]){  
  31.         if(!isdigit(strToken[i]))  
  32.             break;  
  33.         i++;  
  34.     }  
  35.     return strToken[i]==0;  
  36. }  
  37.   
  38. //错误处理程序  
  39. void error(char* errerMessage)  
  40. {  
  41.     printf("\nERROR:%s\n",errerMessage);  
  42.     exit(0);  
  43. }  
  44. /************************* 以上是全局变量(函数)的定义 ******************/  
  45.   
  46. #endif  


 

4、词法分析

词法分析的要求是:接受一个表达式,输出该表达式中的各类单词符号

一般有两种方法来进行词法分析,一种是用状态图来实现,一种是用状态转换表。下面采用状态图实现

首先定义单词符号的种类和所属类型

typedef enum Symbol { ERR = -1, END, NUM, PLUS, MINUS, TIMES, SLASH, LPAREN, RPAREN } Symbol;

 

然后转态转换图如下所示:

 

test1.c文件用代码表示如下:

[cpp] view plain copy
 
  1. #ifndef TEST1_C  
  2. #define TEST1_C  
  3.   
  4. /** 
  5.   * 采用状态图进行词法分析以及测试词法分析 
  6.   * 
  7.   **/  
  8.   
  9. #include"test.c"  
  10.   
  11. //枚举类型  
  12. typedef enum Symbol { ERR = -1, END, NUM, PLUS, MINUS, TIMES,   
  13. SLASH, LPAREN, RPAREN } Symbol;  
  14.   
  15. //获取一个单词符号,该单词符号存放在strToken中。返回该单词符号的枚举类型  
  16. Symbol getToken();  
  17.   
  18. //根据传入的枚举类型输出对应的单词符号  
  19. void printToken(Symbol i);  
  20.   
  21. //测试词法分析  
  22. void testLexAnalyse();  
  23.   
  24. //获取一个单词符号,该单词符号存放在strToken中。返回该单词符号的枚举类型  
  25. Symbol getToken()  
  26. {  
  27.     char ch;  
  28.     int state=0;//每次都是从状态0开始  
  29.     int j=0;  
  30.     //表达式遍历完成,单词符号为'#'  
  31.     if(expression[expression_index]=='\0'){  
  32.         strToken[0]='#';  
  33.         strToken[1]='\0';  
  34.         return END;  
  35.     }  
  36.     while(1){  
  37.         switch(state){  
  38.         case 0:  
  39.             //读取一个字符  
  40.             ch=strToken[j++]=expression[expression_index++];  
  41.             if(isspace(ch)){  
  42.                 j--;//注意退格  
  43.                 state=0;      
  44.             }  
  45.             else if(isdigit(ch))  
  46.                 state=1;                 
  47.             else if(ch=='+')  
  48.                 state=2;                 
  49.             else if(ch=='-')  
  50.                 state=3;                 
  51.             else if(ch=='*')  
  52.                 state=4;              
  53.             else if(ch=='/')  
  54.                 state=5;                 
  55.             else if(ch=='(')  
  56.                 state=6;                 
  57.             else if(ch==')')  
  58.                 state=7;  
  59.             else   
  60.                 return ERR;  
  61.             break;  
  62.   
  63.         case 1:  
  64.             ch=strToken[j++]=expression[expression_index++];  
  65.             if(isdigit(ch))  
  66.                 state=1;  
  67.             else{  
  68.                 expression_index--;  
  69.                 strToken[--j]=0;  
  70.                 return NUM;  
  71.             }  
  72.             break;  
  73.   
  74.         case 2:  
  75.             strToken[j]=0;            
  76.             return PLUS;  
  77.         case 3:  
  78.             strToken[j]=0;  
  79.             return MINUS;  
  80.         case 4:  
  81.             strToken[j]=0;  
  82.             return TIMES;  
  83.         case 5:  
  84.             strToken[j]=0;  
  85.             return SLASH;  
  86.         case 6:  
  87.             strToken[j]=0;  
  88.             return LPAREN;  
  89.         case 7:  
  90.             strToken[j]=0;  
  91.             return RPAREN;               
  92.         }  
  93.     }  
  94. }  
  95.   
  96. //根据传入的枚举类型输出对应的单词符号  
  97. void printToken(Symbol i){  
  98.     switch(i){  
  99.     case -1:printf("ERR\n");break;  
  100.     case 0:printf("END\n");break;  
  101.     case 1:printf("NUM    %s\n",strToken);break;  
  102.     case 2:printf("PLUS   %s\n",strToken);break;  
  103.     case 3:printf("MINUS  %s\n",strToken);break;  
  104.     case 4:printf("TIMES  %s\n",strToken);break;  
  105.     case 5:printf("SLASH  %s\n",strToken);break;  
  106.     case 6:printf("LPAREN %s\n",strToken);break;  
  107.     case 7:printf("RPAREN %s\n",strToken);break;  
  108.     }  
  109. }  
  110.   
  111. //测试词法分析  
  112. void testLexAnalyse()  
  113. {  
  114.    Symbol tokenStyle;//单词符号类型  
  115.    expression_index=0;  
  116.    puts("\n词法分析结果如下:");  
  117.    while(1){  
  118.        tokenStyle=getToken();  
  119.        printToken(tokenStyle);  
  120.        if(tokenStyle == ERR){        
  121.            error("词法分析错误!");  
  122.        }   
  123.        if(tokenStyle == END){  
  124.            break;  
  125.        }  
  126.    }  
  127. }  
  128.   
  129.    
  130. //主函数  
  131. int main()  
  132. {  
  133.     gets(expression);  
  134.     testLexAnalyse();  
  135.     return 0;  
  136. }  
  137.    
  138. #endif  


运行结果

 

5、语法分析

要求:接受一个表达式,分析该表达式,并根据输入正确与否给出相应信息

主要是根据无左递归文法写出对应的各个子程序

test2.c

[cpp] view plain copy
 
  1. #ifndef TEST_2  
  2. #define TEST_2  
  3.   
  4. /** 
  5.   * 语法分析以及测试语法分析 
  6.   **/  
  7.   
  8. #include"test1.c"  
  9.   
  10. /* 
  11. 消除左递归后的文法: 
  12. E→TE' 
  13. E'→+TE' |ε 
  14. T→FT' 
  15. T'→*FT' |ε 
  16. F→(E) | i 
  17. */  
  18.   
  19. //每个非终结符有对应的子程序函数声明  
  20. void E();  
  21. void E1();  
  22. void T();  
  23. void T1();  
  24. void F();  
  25. //测试语法分析  
  26. void testSyntaxAnalyse();  
  27.   
  28. //每个非终结符有对应的子程序  
  29. void E()  
  30. {  
  31.     T();  
  32.     E1();  
  33. }  
  34. void E1()  
  35. {  
  36.     if(strcmp(strToken,"+")==0 || strcmp(strToken,"-")==0){  
  37.         getToken();  
  38.         T();  
  39.         E1();  
  40.     }  
  41.     //Follow(E1)={#,)}  
  42.     else if(strcmp(strToken,"#")!=0 && strcmp(strToken,")")!=0){  
  43.         error("语法分析错误!");  
  44.     }  
  45. }  
  46. void T()  
  47. {  
  48.     F();  
  49.     T1();  
  50. }  
  51. void T1()  
  52. {  
  53.     if(strcmp(strToken,"*")==0 || strcmp(strToken,"/")==0){  
  54.         getToken();  
  55.         F();  
  56.         T1();  
  57.     }  
  58.     //Follow(T1)={+,#,)},如果考虑-号的话要加上-号  
  59.     else if(strcmp(strToken,"-")!=0 &&strcmp(strToken,"+")!=0 && strcmp(strToken,"#")!=0 && strcmp(strToken,")")!=0){  
  60.         error("语法分析错误!");  
  61.     }  
  62. }  
  63. void F()  
  64. {  
  65.     if(isNum(strToken)){  
  66.         getToken();  
  67.     }  
  68.     else{  
  69.         if(strcmp(strToken,"(")==0){  
  70.              getToken();  
  71.              E();  
  72.              if(strcmp(strToken,")")==0)  
  73.                  getToken();  
  74.              else  
  75.                  error("语法分析错误!");  
  76.         }  
  77.         else   
  78.             error("语法分析错误!");  
  79.     }  
  80. }  
  81.   
  82. //测试语法分析  
  83. void testSyntaxAnalyse()  
  84. {  
  85.    expression_index=0;  
  86.    getToken();  
  87.    E();  
  88.    puts("\n语法分析结果如下:");  
  89.    if(strcmp(strToken,"#")!=0)  
  90.        error("语法分析错误!");  
  91.    else{  
  92.        puts("语法分析正确!");  
  93.    }  
  94. }  
  95.   
  96.   
  97. //主函数  
  98. int main()  
  99. {  
  100.     gets(expression);  
  101.     testLexAnalyse();  
  102.     testSyntaxAnalyse();  
  103.     return 0;  
  104. }  
  105.   
  106. #endif  


运行时要删掉test1.c中的主函数,运行结果

 

 

6、语义分析

要求:需要实现的语义分析程序的功能是,接受一个表达式,分析该表达式,并在分析的过程中建立该表达式的抽象语法树。由于四则运算表达式的抽象语法树可基本上看作是二叉树,因此中序遍历序列应该和输入的表达式一样——除了没有括号之外。可输出中序遍历序列检测程序功能是否正确。如果每个分支节点用一个临时变量标记,则对四则运算表达式的抽象语法树进行后序遍历,可以得到输入表达式所对应的四元式序列

test3.c文件

[cpp] view plain copy
 
  1. #ifndef TEST3_C  
  2. #define TEST3_C  
  3.   
  4. /** 
  5.   * 语义分析以及测试语义分析 
  6.   * 其实这个实验是在test2的代码上进行修改 
  7.   **/  
  8.   
  9. #include"test1.c"  
  10.   
  11. /* 
  12. 消除左递归的翻译模式: 
  13. E ::=   T   {E'.i:=T.nptr} 
  14. E'  {E.nptr:=E'.s} 
  15. E'::=   + T {E'1.i:=mknode('+',E'.i,T.nptr)} 
  16. E'1 {E'.s:=E1.s} 
  17. E'::=   - T {E'1.i:=mknode('-',E'.i,T.nptr)} 
  18. E'1 {E'.s:=E1.s} 
  19. E'::=   ε   {E'.s:= E'.i} 
  20. T ::=   F   {T'.i:=F.nptr} 
  21. T'  {T.nptr:=T'.s} 
  22. T'::=   * F {T'1.i:=mknode('*',T'.i,F.nptr)} 
  23. T'1 {T'.s:=T1.s} 
  24. T'::=   / F {T'1.i:=mknode('/',T'.i,F.nptr)} 
  25. T'1 {T'.s:=T1.s} 
  26. T' ::= ε    {T'.s:= T'.i} 
  27. F ::= (E) {F.nptr:=E.nptr} 
  28. F ::= num {F.nptr:=mkleaf(num,num.val)} 
  29. */  
  30.   
  31. #define MAX_LENGTH 20 //四元式中操作数的最大长度  
  32.   
  33. typedef int ValType;  
  34. //结点类型  
  35. typedef struct ASTNode {  
  36.     Symbol sym;//类型  
  37.     ValType val;//值  
  38.     struct ASTNode * left, *right;//左、右孩子  
  39. }ASTNode, *AST;  
  40.   
  41. //四元式类型定义如下  
  42. typedef struct Quaternion{  
  43.     char op;  
  44.     char arg1[MAX_LENGTH];  
  45.     char arg2[MAX_LENGTH];  
  46.     char result[MAX_LENGTH];  
  47. }Quaternion;  
  48. //四元式数组,存放产生的四元式  
  49. Quaternion quaternion[MAX_LENGTH*2];  
  50. //统计四元式的个数  
  51. int count=0;  
  52.   
  53. //后序遍历抽象语法树时存放操作数和临时变量,这里当作一个栈来使用  
  54. char stack[MAX_LENGTH*2][MAX_LENGTH];  
  55. //stack栈的下标  
  56. int index=0;  
  57.   
  58. //内存中临时数据存储地址的偏移量  
  59. int t=-4;  
  60.   
  61. //函数声明  
  62. ASTNode* E();  
  63. ASTNode* E1(ASTNode* E1_i);  
  64. ASTNode* T();  
  65. ASTNode* T1(ASTNode* T1_i);  
  66. ASTNode* F();  
  67. void error(char* errerMessage);  
  68. ASTNode *mknode(Symbol op, ASTNode *left, ASTNode *right);  
  69. ASTNode *mkleaf(Symbol sym, ValType val);  
  70. void yuyi_analyse();  
  71. void print_node(ASTNode *root);  
  72. void middle_list(ASTNode *root);  
  73. void last_list(ASTNode *root);  
  74. //测试语义分析  
  75. void testYuyiAnalyse();  
  76. //创建运算符结点  
  77. ASTNode *mknode(Symbol op, ASTNode *left, ASTNode *right);  
  78. //创建操作数结点  
  79. ASTNode *mkleaf(Symbol sym, ValType val);  
  80. //输出结点  
  81. void printNode(ASTNode *root);  
  82. //中序遍历二叉树  
  83. void middle_list(ASTNode *root);  
  84. //后序遍历二叉树  
  85. void last_list(ASTNode *root);  
  86.   
  87.   
  88. /* 
  89. E ::=   T   {E'.i:=T.nptr} 
  90. E'  {E.nptr:=E'.s} 
  91. */  
  92. //为右边的每个非终结符定义一个属性,返回E的综合属性  
  93. ASTNode* E()  
  94. {  
  95.     ASTNode * E_nptr;  
  96.     ASTNode * E1_i;  
  97.     E1_i=T();  
  98.     E_nptr=E1(E1_i);  
  99.     return E_nptr;  
  100. }  
  101.   
  102. /* 
  103. E'::=   + T {E'1.i:=mknode('+',E'.i,T.nptr)} 
  104. E'1 {E'.s:=E1.s} 
  105. E'::=   - T {E'1.i:=mknode('-',E'.i,T.nptr)} 
  106. E'1 {E'.s:=E1.s} 
  107. E'::=   ε   {E'.s:= E'.i} 
  108. */  
  109. //返回的是综合属性,传递的是继承属性  
  110. ASTNode * E1(ASTNode *E1_i)  
  111. {  
  112.     ASTNode * E11_i;  
  113.     ASTNode * E1_s;  
  114.     ASTNode * T_nptr;   
  115.     char oper;  
  116.     if(strcmp(strToken,"+")==0 || strcmp(strToken,"-")==0){  
  117.         oper=strToken[0];  
  118.         getToken();  
  119.         T_nptr=T();  
  120.         if(oper=='+')  
  121.             E11_i=mknode(PLUS,E1_i,T_nptr);  
  122.         else  
  123.             E11_i=mknode(MINUS,E1_i,T_nptr);  
  124.   
  125.         E1_s=E1(E11_i);       
  126.     }  
  127.     //Follow(E1)={#,)},可以匹配空串  
  128.     else if(strcmp(strToken,"#")==0 || strcmp(strToken,")")==0){  
  129.         E1_s=E1_i;  
  130.     }else{  
  131.         error("语法分析错误!");  
  132.     }  
  133.     return E1_s;  
  134. }  
  135. /* 
  136. T ::=   F   {T'.i:=F.nptr} 
  137. T'  {T.nptr:=T'.s} 
  138. */  
  139. ASTNode* T()  
  140. {  
  141.     ASTNode * T_nptr;  
  142.     ASTNode * T1_i;  
  143.     T1_i=F();  
  144.     T_nptr=T1(T1_i);  
  145.     return T_nptr;  
  146. }  
  147.   
  148. /* 
  149. T'::=   * F {T'1.i:=mknode('*',T'.i,F.nptr)} 
  150. T'1 {T'.s:=T1.s} 
  151. T'::=   / F {T'1.i:=mknode('/',T'.i,F.nptr)} 
  152. T'1 {T'.s:=T1.s} 
  153. T' ::= ε    {T'.s:= T'.i} 
  154. */  
  155. ASTNode* T1(ASTNode* T1_i)  
  156. {  
  157.     ASTNode* F_nptr;  
  158.     ASTNode* T11_i;  
  159.     ASTNode* T1_s;  
  160.     char oper;  
  161.     if(strcmp(strToken,"*")==0 || strcmp(strToken,"/")==0){  
  162.         oper=strToken[0];  
  163.         getToken();        
  164.         F_nptr=F();  
  165.         if(oper=='*')  
  166.             T11_i=mknode(TIMES,T1_i,F_nptr);  
  167.         else  
  168.             T11_i=mknode(SLASH,T1_i,F_nptr);  
  169.         T1_s=T1(T11_i);       
  170.     }  
  171.     //Follow(T1)={+,#,)},如果考虑-号的话要加上-号  
  172.     else if(strcmp(strToken,"-")==0 || strcmp(strToken,"+")==0 || strcmp(strToken,"#")==0 || strcmp(strToken,")")==0){  
  173.         T1_s=T1_i;   
  174.     }else{  
  175.         error("语法分析错误!");   
  176.     }  
  177.     return T1_s;  
  178. }  
  179. /* 
  180. F ::= (E) {F.nptr:=E.nptr} 
  181. F ::= num {F.nptr:=mkleaf(num,num.val)} 
  182. */  
  183. ASTNode* F()  
  184. {  
  185.     ASTNode* F_nptr;  
  186.     ASTNode* E_nptr;  
  187.     if(isNum(strToken)){  
  188.         F_nptr=mkleaf(NUM,atoi(strToken));  
  189.         getToken();  
  190.     }  
  191.     else{  
  192.         if(strcmp(strToken,"(")==0){  
  193.              getToken();  
  194.              E_nptr=E();  
  195.              if(strcmp(strToken,")")==0)  
  196.                  getToken();  
  197.              else  
  198.                  error("语法分析错误!");  
  199.              F_nptr=E_nptr;  
  200.         }  
  201.         else {  
  202.             error("语法分析错误!");  
  203.         }  
  204.     }  
  205.     return F_nptr;  
  206. }  
  207.   
  208. //创建运算符结点  
  209. ASTNode *mknode(Symbol op, ASTNode *left, ASTNode *right)  
  210. {  
  211.     ASTNode* p=(ASTNode*)malloc(sizeof(ASTNode));  
  212.     p->left=left;  
  213.     p->right=right;  
  214.     p->sym=op;  
  215.     p->val=0;  
  216.     return p;  
  217. }  
  218.   
  219. //创建操作数结点  
  220. ASTNode *mkleaf(Symbol sym, ValType val)  
  221. {  
  222.     ASTNode* p=(ASTNode*)malloc(sizeof(ASTNode));  
  223.     p->sym=sym;  
  224.     p->val=val;  
  225.     p->left=NULL;  
  226.     p->right=NULL;  
  227.     return p;  
  228. }  
  229.   
  230. //输出结点  
  231. void printNode(ASTNode *root)  
  232. {  
  233.     if(root->sym==NUM)  
  234.         printf("%d ",root->val);  
  235.     else if(root->sym==PLUS)  
  236.         printf("+ ");  
  237.     else if(root->sym==MINUS)  
  238.         printf("- ");  
  239.     else if(root->sym==TIMES)  
  240.         printf("* ");  
  241.     else if(root->sym==SLASH)  
  242.         printf("/ ");  
  243. }  
  244.   
  245. //中序遍历二叉树  
  246. void middle_list(ASTNode *root)  
  247. {  
  248.     if(root==NULL)  
  249.         return ;  
  250.     middle_list(root->left);  
  251.     printNode(root);  
  252.     middle_list(root->right);  
  253. }  
  254.   
  255. //后序遍历二叉树  
  256. void last_list(ASTNode *root)  
  257. {  
  258.     char temp[MAX_LENGTH];  
  259.     if(root==NULL)  
  260.         return ;  
  261.     last_list(root->left);  
  262.     last_list(root->right);  
  263.     if(root->sym == NUM){//如果是数字,则直接存入栈中  
  264.         sprintf(temp,"%d\0",root->val);  
  265.         strcpy(stack[index++],temp);  
  266.     }  
  267.     else if(root->sym == PLUS){//如果是+号,产生一个四元式  
  268.         //给四元式赋值  
  269.         quaternion[count].op='+';  
  270.         strcpy(quaternion[count].arg2,stack[--index]);  
  271.         strcpy(quaternion[count].arg1,stack[--index]);  
  272.         sprintf(quaternion[count].result,"t+%d\0",t+=4);  
  273.         strcpy(stack[index++],quaternion[count].result);  
  274.         //输出该四元式  
  275.         printf("%-4c%-8s%-8s%-8s\n",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);  
  276.         count++;  
  277.     }else if(root->sym == MINUS){//如果是+号,产生一个四元式  
  278.         quaternion[count].op='-';  
  279.         strcpy(quaternion[count].arg2,stack[--index]);  
  280.         strcpy(quaternion[count].arg1,stack[--index]);  
  281.         sprintf(quaternion[count].result,"t+%d\0",t+=4);  
  282.         strcpy(stack[index++],quaternion[count].result);  
  283.         printf("%-4c%-8s%-8s%-8s\n",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);  
  284.         count++;  
  285.     }else if(root->sym == TIMES){//如果是*号,产生一个四元式  
  286.         quaternion[count].op='*';  
  287.         strcpy(quaternion[count].arg2,stack[--index]);  
  288.         strcpy(quaternion[count].arg1,stack[--index]);  
  289.         sprintf(quaternion[count].result,"t+%d\0",t+=4);  
  290.         strcpy(stack[index++],quaternion[count].result);  
  291.         printf("%-4c%-8s%-8s%-8s\n",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);  
  292.         count++;  
  293.     }else if(root->sym == SLASH){  
  294.         quaternion[count].op='/';  
  295.         strcpy(quaternion[count].arg2,stack[--index]);  
  296.         strcpy(quaternion[count].arg1,stack[--index]);  
  297.         sprintf(quaternion[count].result,"t+%d\0",t+=4);  
  298.         strcpy(stack[index++],quaternion[count].result);  
  299.         printf("%-4c%-8s%-8s%-8s\n",quaternion[count].op,quaternion[count].arg1,quaternion[count].arg2,quaternion[count].result);  
  300.         count++;  
  301.     }  
  302. }  
  303.   
  304. //测试语义分析  
  305. void testYuyiAnalyse()  
  306. {  
  307.    ASTNode *root;  
  308.    expression_index=0;  
  309.    getToken();  
  310.    root=E();  
  311.    puts("\n语义分析结果如下:");  
  312.    printf("中序遍历:");  
  313.    middle_list(root);  
  314.    putchar('\n');  
  315.    printf("后序遍历得到的四元式:\n");  
  316.    last_list(root);  
  317.    putchar('\n');   
  318. }  
  319.   
  320. //主函数  
  321. int main()  
  322. {  
  323.     gets(expression);  
  324.     testYuyiAnalyse();  
  325.     return 0;  
  326. }  
  327.   
  328. #endif  

运行结果

 

7、代码生成

要求:以实验3的语义分析程序的四元式输出作为输入,输出汇编语言程序。

test4.c

[cpp] view plain copy
 
  1. #ifndef TEST4_C  
  2. #define TEST4_C  
  3.   
  4. /** 
  5.   * 生产汇编代码 
  6.   **/  
  7. #include"test3.c"  
  8.   
  9. //传人一个四元式,输出对应的汇编代码  
  10. void print_code(Quaternion qua)  
  11. {  
  12.     putchar('\n');  
  13.     /* 
  14.      mov eax, 3 
  15.      add eax, 4 
  16.      mov t+0, eax 
  17.     */  
  18.     if(qua.op == '+'){  
  19.         printf("        mov eax,%s\n",qua.arg1);  
  20.         printf("        add eax,%s\n",qua.arg2);  
  21.         printf("        mov %s,eax\n",qua.result);  
  22.     }else if(qua.op == '-'){  
  23.         printf("        mov eax,%s\n",qua.arg1);  
  24.         printf("        sub eax,%s\n",qua.arg2);  
  25.         printf("        mov %s,eax\n",qua.result);  
  26.     }  
  27.     /* 
  28.     mov eax, 2 
  29.     mov ebx, t+0 
  30.     mul ebx 
  31.     mov t+4, eax 
  32.     */  
  33.     else if(qua.op == '*'){  
  34.         printf("        mov eax,%s\n",qua.arg1);  
  35.         printf("        mov ebx,%s\n",qua.arg2);  
  36.         printf("        mul ebx\n");  
  37.         printf("        mov %s,eax\n",qua.result);  
  38.     }else if(qua.op == '/'){//除法的时候不考虑余数  
  39.         printf("        mov eax,%s\n",qua.arg1);  
  40.         printf("        mov ebx,%s\n",qua.arg2);  
  41.         printf("        div ebx\n");  
  42.         printf("        mov %s,eax\n",qua.result);  
  43.     }  
  44. }  
  45.   
  46. //输出全部汇编代码  
  47. void testCode()  
  48. {  
  49.     int i=0;  
  50.     puts("生成的汇编代码如下:\n");  
  51.     puts(".386");  
  52.     puts(".MODEL FLAT");  
  53.     puts("ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD");  
  54.     puts("INCLUDE io.h            ; header file for input/output");  
  55.     puts("cr      EQU     0dh     ; carriage return character");  
  56.     puts("Lf      EQU     0ah     ; line feed");  
  57.     puts(".STACK  4096            ; reserve 4096-byte stack");  
  58.     puts(".DATA                   ; reserve storage for data");  
  59.     puts("t       DWORD   40 DUP (?)");  
  60.     puts("label1   BYTE    cr, Lf, \"The result is \"");  
  61.     puts("result     BYTE    11 DUP (?)");  
  62.     puts("        BYTE    cr, Lf, 0");  
  63.     puts(".CODE                           ; start of main program code");  
  64.     puts("_start:");  
  65.     //遍历实验3中的四元式,输出对应的汇编代码  
  66.     for(;i<count;i++)  
  67.         print_code(quaternion[i]);  
  68.     puts("        dtoa    result, eax     ; convert to ASCII characters");  
  69.     puts("        output  label1          ; output label and sum");  
  70.     puts("        INVOKE  ExitProcess, 0  ; exit with return code 0");  
  71.     puts("PUBLIC _start                   ; make entry point public");  
  72.     puts("END                             ; end of source code");  
  73. }  
  74.   
  75. //主函数  
  76. int main()  
  77. {  
  78.     gets(expression);  
  79.     testLexAnalyse();  
  80.     testYuyiAnalyse();  
  81.     testCode();  
  82.     return 0;  
  83. }  
  84.   
  85. #endif  


 

 

运行结果

 

 8、源代码下载地址

http://download.csdn.net/detail/touch_2011/3852940

posted @ 2017-05-30 15:39  天涯海角路  阅读(1169)  评论(0)    收藏  举报