1、1编译技术课程设计文 档学号:_姓名:_ _2015 年 1 月 8 日2一需求说明1文法说明原始文法加法运算符 := +-乘法运算符 := */关系运算符 := =!=字母 := a zA Z数字 := 非零数字非零数字 := 字符 := 加法运算符乘法运算符 字母 数字字符串 := “十进制编码为 32,33,35-126 的 ASCII 字符“程序 := 常量说明 变量说明有返回值函数定义|无返回值函数定义主函数常量说明 := const常量定义; const常量定义;常量定义 := int标识符整数, 标识符整数| char标识符字符,标识符字符无符号整数 := 非零数字数字整数 :=
2、 无符号整数标识符 := 字母字母数字声明头部 := int标识符 | char标识符变量说明 := 变量定义;变量定义;变量定义 := 类型标识符 (标识符|标识符无符号整数 ),(标识符|标识符无符号整数 )/不许在定义变量时赋初值.常量 := 整数| 字符类型标识符 := int | char有返回值函数定义 := 声明头部( 参数) 复合语句无返回值函数定义 := void标识符( 参数) 复合语句复合语句 := 常量说明 变量说明语句列参数 := 参数表参数表 := 类型标识符标识符,类型标识符标识符| 空主函数 := void main() 复合语句表达式 := 项加法运算符项项
3、:= 因子乘法运算符因子因子 := 标识符标识符表达式 整数|字符有返回值函数调用语句| (表达式) 语句 := 条件语句循环语句| 语句列有返回值函数调用语句; |无返回值函数调用语句;赋值语句;读语句;写语句;空; |情况语句返回语句;赋值语句 := 标识符表达式|标识符 表达式 =表达式条件语句 := if (条件 )语句else语句条件 := 表达式关系运算符表达式表达式 /表达式为 0 条件为假,否则为3真循环语句 := while (条件)语句情况语句 := switch (表达式) 情况表 情况表 := 情况子语句情况子语句情况子语句 := case常量:语句有返回值函数调用语句
4、 := 标识符( 值参数表)无返回值函数调用语句 := 标识符( 值参数表)值参数表 := 表达式,表达式 空语句列 := 语句读语句 := scanf (标识符, 标识符)写语句 := printf ( 字符串 ,表达式 )| printf (字符串 )| printf (表达式)返回语句 := return(表达式) 文法解读说明及举例:加法运算符 := +- /*加法运算符由+ 号、- 号组成*/范例:略分析:略乘法运算符 := */*乘法运算符由* 号、 /号组成*/范例:略分析:略关系运算符 := =!=/*关系运算符由、=、!=、= 组成*/范例:略分析:略字母 := azAZ /
5、*字母由下划线与大小写字母组成*/范例:略分析:略4数字 := 非零数字/*数字由 0、*/ 举例:0|1|9,记为 number范例:0分析:数字包含了所有的单个的数字,不同于整数非零数字 := /*非零数字由 19 组成*/分析:非零数字也是单个的数字,但是不含 0。字符 := 加法运算符 乘法运算符字母数字/*字符包含加法运算符、乘法运算符、字母、数字?记为 character*/范例:+,-,*,/等单字符分析:必须添加单引号,必须是单个的!注意和字符串的区分字符串 := “十进制编码为 32,33,35-126 的 ASCII 字符“/*规定合法的字符串,必须要用双引号括起来,记为
6、chstring*/范例:“abc”分析:略程序 := 常量说明变量说明有返回值函数定义 |无返回值函数定义主函数/*程序组成部分包含常量说明、变量说明、有返回值函数定义、无返回值函数定义、主函数,主函数过后整个程序结束*/范例以及说明: const int a=1,b=1;/* 常量说明部分const char c=a; */int a_1; /*变量说明部分char c_1; */ /*在这里定义和说明的常量变量都是全局的*/int fun1(int a, int b)XXXX5return 1;/*有返回值的函数定义必须要有返回值*/ void fun2() /*无返回值的函数定义*/r
7、eturn; Void main() /*/XXXXXReturn ; /虽然从文法上可以推导出 void 可以返回 return 0,不过语法上应该检查对不对分析:不能随便改变顺序,例如把函数的定义放在全局变量或者全局常量的前面的做法是不对的。常量说明,变量说明以及函数定义都可有可无,但是主函数是必要的。常量说明 := const常量定义; const常量定义;/*常量说明的标志是 const *,const int a1=1/分析:可以一个可以多个,不同类型的 const 中间用分号隔开。常量定义 := int标识符整数, 标识符整数| char标识符字符 ,标识符字符/*常量定义为 in
8、t a1=12 或者 char c=a,允许连续定义,如 int a=1,b=2*/无符号整数 := 非零数字数字/*无符号整数举例:10,11,12,13,14 ,不能以 0 开头,前面不能有正负号,不能为 0,usigned interger*/整数 := 无符号整数/*整数在无符号整数前添加正负号,也可以不带+|-,也包含了 0,记为 interger /标识符 := 字母字母数字/*标示符由字母开头,可以纯字母,可以加上数字编号,记为 ident*/声明头部 := int标识符 | char标识符6/*函数定义的声明头部为 int a 开头,但是因为是函数定义所以紧跟在后的是括号(和变
9、量说明部分开始一样,但是要注意区分!)*/变量说明 := 变量定义;变量定义;/*变量说明由一个或多个变量定义组成,多个变量定义之间由分号隔开*/变量定义 := 类型标识符(标识符| 标识符无符号整数),(标识符| 标识符无符号整数 )/*举例:int a1,ax2,ax3,ax4 */分析:允许多个,必须要有标识符。常量 := 整数| 字符/*常量为整数或者字符*/举例:112,a.分析:略类型标识符 := int | char/*类型标识符为 int 或者 char,用在变量定义的开头*/分析:略有返回值函数定义 := 声明头部(参数) 复合语句/*有返回值的函数定义格式为声明头部(参数)
10、复合语句,举例 int function(int a,int b) xxxxx*/分析:有返回值的函数定义,return 的时候必须要有值,因为有值,所以有返回值的函数在被调用的时候也可以作为因子。无返回值函数定义 := void标识符(参数)复合语句/*无返回值的函数定义格式为声明头部(参数)复合语句,举例 void function(int a,int b) xxxxx*/分析:void 函数无返回值,但是从语法上来讲不会报错,应该从语义分析上进行报错。复合语句 := 常量说明变量说明语句列/*复合语句包含 0多个常量说明,0 多个变量说明,语句列,举例:const int a=1, in
11、t b, XXXXX*/分析:其实每一个符合语句就是平时写的程序里面的函数过后的内部的内容,这样一说是不是就好理解得多了呢?7参数 := 参数表/*参数即为参数表*/参数表 := 类型标识符标识符,类型标识符标识符| 空/*参数表举例:int a,int b*/或者就是空,什么都没有分析:主要用在涉及到函数的声明定义以及调用传参里面(所以可以为空)主函数 := void main() 复合语句/*void main() XXXX*/XXXX 即为复合语句分析:主函数是程序必须的元素,整个程序只允许出现一个主函数,并且,如果主函数分析完毕,则整个编译程序分析完毕表达式 := 项加法运算符项/*表
12、达式由项(一个项或者多个项)加上加法运算符组成,前面可以添加正负号*/范例: a+b,a*b+c*d,a+(b+c)分析:每一个表达式其实是有值的,可以用来进行赋值或者进行条件判断项 := 因子乘法运算符因子/*项由因子(一个或者多个)乘除运算符组成*/范例: a*b, a, (a+b)*c ,a/c分析:因子与因子之间的链接符号只能为乘法运算符*或者/因子 := 标识符标识符表达式整数|字符有返回值函数调用语句|(表达式) /*因子包含的内容有:indent,indent表达式,123 等整数,c等字符,call(a) ,(a+b)*/分析:以上的距离分别对应标识符、标识符表达式、 整数、字
13、符、call(a) 、(表达式) 8语句 := 条件语句循环语句| 语句列 有返回值函数调用语句 ; |无返回值函数调用语句;赋值语句;读语句;写语句;空; |情况语句返回语句;/*语句分为条件语句、循环语句、语句列、call(int a);、call(int a);无返回值函数调用语句; 有返回值函数调用语句;、赋值语句;、读语句;、写语句; 、;、情况语句、返回语句;*/ 分析:注意这里是有些语句后面是有分号的,不过条件语句,循环语句循环语句最后是没有分号,不过不保证其内部不出现分号。赋值语句 := 标识符表达式|标识符表达式=表达式/*赋值语句举例:a1= 1+2、a12=1*2 */分
14、析:应该先分析后面的部分,这里应该考虑下计算的先后顺序。条件语句 := if (条件)语句else 语句/*条件语句举例:if(a0) XXX else XXXX*/分析:(a0)即为条件,XXX 为语句部分, XXXX 为 else 后的语句部分,else 及其之后部分为可有可无部分,但是 if 以及(条件) 是必须的条件 := 表达式关系运算符表达式表达式 /表达式为 0 条件为假,否则为真/*a0、a0)Printf(a);分析:略读语句 := scanf (标识符,标识符)/*读语句举例: scanf (a,b,c,d)*/10分析:依次读入值并赋值给对应位置的标志符。写语句 := p
15、rintf ( 字符串,表达式 )| printf (字符串 )| printf (表达式)/*写语句举例:printf (“abc”,1+3)、printf(“abc”)、printf(a+1)*/分析:printf 的工作是打印,可以打印字符串,也可以打印表达式的值。因为表达式可以是项,项可以为标识符,所以可以打印变量的值。返回语句 := return(表达式) /*返回语句举例:return 、return a+b、return 0*/分析:返回语句主要用于函数的定义当中文法改写或者扩充:通过分析文法,可以发现文法中不存在左递归的问题,但是存在回溯的问题(例如在处理变量说明和有返回值函数定义的时候) ,由于改写文法会导致文法的语义连贯性及其差,所以在语法分析的工程中,处理回溯的问题的时候采取的是预读字符的方式。2目标代码说明生成的目标代码为 X86 32 位的汇编程序,可以使用 masm32 编译链接生成可执行文件。3. 优化方案优化:基本块内部的公共子表达式删除(利用 DAG 图) ;数据流分析(通过活跃变量分析,或利用定义-使用链建网等方法建立冲突图) ;全局寄存器分配(启发式着色算法) ;常数合并,当加减乘除运算的两个操作符是常数时,进行常数的合并以及直接赋值二详细设计