标签:
接着上节讲, 我们来看如何在分析中插入合适的代码来生成语法树...
对于抽象语法树的总结 :
下面是作业 :
【抽象语法树】
在这个题目中,你将完整的实现抽象语法树(包括数据结构的定义、语法树的生成等)。首先,请下载我们提供的代码包:
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生成语法树的代码框架。你的任务是:
进一步完善该代码框架,使其能够分析减法、除法和括号表达式;(你需要修改语法树的定义,修改bison源文件及其它代码)
重新研究第一次作业中的从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 }
剩下的两个文件改动不大就不贴代码了...
标签:
原文地址:http://www.cnblogs.com/nzhl/p/5536617.html