语法翻译(3)...

接着上节讲, 我们来看如何在分析中插入合适的代码来生成语法树...

对于抽象语法树的总结 :

下面是作业 :

【抽象语法树】

在这个题目中,你将完整的实现抽象语法树(包括数据结构的定义、语法树的生成等)。首先,请下载我们提供的代码包:

http://staff.ustc.edu.cn/~bjhua/mooc/ast.zip

代码的运行方式是:

首先生成语法分析器:

  $ bison exp.y

然后生成编译器:

  $ gcc main.c exp.tab.c ast.c

最后使用编译器编译某个源文件:

  $ a.exe <test.txt

 

在提供的代码里,我们已经提供了抽象语法树的定义、若干操作、及由bison生成语法树的代码框架。你的任务是:

  1. 进一步完善该代码框架,使其能够分析减法、除法和括号表达式;(你需要修改语法树的定义,修改bison源文件及其它代码)

  2. 重新研究第一次作业中的从Sum编译到Stack的小型编译器代码,把他移植到目前的代码框架中,这样你的编译器能够从文本文件中读入程序,然后输出编译的结果。(注意,你必须扩展你的编译器,让他能够支持减法和除法。)

代码实现 :

 1 %{
 2 #include <stdio.h>
 3 #include "ast.h"
 4   int yylex(); // this function will be called in the parser
 5   void yyerror(char *);
 6 
 7   Exp_t tree;
 8 
 9   %}
10 
11 %union{
12   Exp_t exp;
13  }
14 
15 %type <exp> digit exp program
16 
17 
18 %left '+' '-'
19 %left '*' '/'
20 
21 %start program
22 
23 %%
24 
25 program: exp '\n'{tree = $1;}
26 ;
27 
28 exp: digit     {$$ = $1;}
29 | exp '+' exp  {$$ = Exp_Add_new ($1, $3);}
30 | exp '-' exp  {$$ = Exp_Minus_new ($1, $3);}
31 | exp '*' exp  {$$ = Exp_Times_new ($1, $3);}
32 | exp '/' exp  {$$ = Exp_Divide_new ($1, $3);}
33 ;
34 
35 digit: '0'  {$$ = Exp_Int_new (0);}
36 | '1'       {$$ = Exp_Int_new (1);}
37 | '2'       {$$ = Exp_Int_new (2);}
38 | '3'       {$$ = Exp_Int_new (3);}
39 | '4'       {$$ = Exp_Int_new (4);}
40 | '5'       {$$ = Exp_Int_new (5);}
41 | '6'       {$$ = Exp_Int_new (6);}
42 | '7'       {$$ = Exp_Int_new (7);}
43 | '8'       {$$ = Exp_Int_new (8);}
44 | '9'       {$$ = Exp_Int_new (9);}
45 | '('exp')' {$$ = $2;}
46 ;
47 
48 %%
49 
50 int yylex ()
51 {
52   int c = getchar();
53   return c;
54 }
55 
56 // bison needs this function to report
57 // error message
58 void yyerror(char *err)
59 {
60   fprintf (stderr, "%s\n", err);
61   return;
62 }
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include "ast.h"
 4 
 5 // "constructors"
 6 Exp_t Exp_Int_new (int n)
 7 {
 8   Exp_Int p = malloc (sizeof (*p));
 9   p->kind = EXP_INT;
10   p->n = n;
11   return (Exp_t)p;
12 }
13 
14 Exp_t Exp_Add_new (Exp_t left, Exp_t right)
15 {
16   Exp_Add p = malloc (sizeof (*p));
17   p->kind = EXP_ADD;
18   p->left = left;
19   p->right = right;
20   return (Exp_t)p;
21 }
22 
23 Exp_t Exp_Minus_new (Exp_t left, Exp_t right)
24 {
25   Exp_Add p = malloc (sizeof (*p));
26   p->kind = EXP_MINUS;
27   p->left = left;
28   p->right = right;
29   return (Exp_t)p;
30 }
31 
32 Exp_t Exp_Times_new (Exp_t left, Exp_t right)
33 {
34   Exp_Add p = malloc (sizeof (*p));
35   p->kind = EXP_TIMES;
36   p->left = left;
37   p->right = right;
38   return (Exp_t)p;
39 }
40 
41 Exp_t Exp_Divide_new (Exp_t left, Exp_t right)
42 {
43   Exp_Add p = malloc (sizeof (*p));
44   p->kind = EXP_DIVIDE;
45   p->left = left;
46   p->right = right;
47   return (Exp_t)p;
48 }
49 // all operations on "Exp"
50 void Exp_print (Exp_t exp)
51 {
52   switch (exp->kind){
53   case EXP_INT:{
54     Exp_Int p = (Exp_Int)exp;
55     printf ("%d", p->n);
56     return;
57   }
58   case EXP_ADD:{
59     Exp_Add p = (Exp_Add)exp;
60     printf ("(");
61     Exp_print (p->left);
62     printf (") + (");
63     Exp_print (p->right);
64     printf (")");
65     return;
66   }
67   case EXP_MINUS:{
68     Exp_Minus p = (Exp_Minus)exp;
69     printf ("(");
70     Exp_print (p->left);
71     printf (") - (");
72     Exp_print (p->right);
73     printf (")");
74     return;
75   }
76   case EXP_TIMES:{
77     Exp_Times p = (Exp_Times)exp;
78     printf ("(");
79     Exp_print (p->left);
80     printf (") * (");
81     Exp_print (p->right);
82     printf (")");
83     return;
84   }
85   case EXP_DIVIDE:{
86     Exp_Divide p = (Exp_Divide)exp;
87     printf ("(");
88     Exp_print (p->left);
89     printf (") / (");
90     Exp_print (p->right);
91     printf (")");
92     return;
93   }
94   default:
95     return;
96   }
97 }

 

剩下的两个文件改动不大就不贴代码了...

转载于:https://www.cnblogs.com/nzhl/p/5536617.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值