C-编译器设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程实验报告
(全日制硕士研究生)
课程名称程序语言与编译
实验名称C-编译器设计
专业、班级计算机科学与技术4班学生张洁坤
学号S********
同组学生及学号无
指导教师杨晓波
目录
第1章实验介绍及整体框架 (3)
1.1实验目的: (3)
1.2实验环境: (3)
1.3 C-编译器的整体框架 (3)
第2章词法分析 (4)
2.1 词法分析包括两个类: (4)
2.2 C关键字表: (5)
2.3 标识符词法: (5)
第3章语法分析 (6)
3.1 Class CParser: (6)
3.2 Grammar: (6)
3.3 基本树形结构: (7)
3.4 支持的语句及运算: (8)
第4章建立符号表 (9)
4.1 辅助类: (9)
4.2 主要的类,建立符号表: (9)
第5章类型检测 (10)
第6章代码生成 (11)
6.1 PCode: (11)
6.2 80X86 ASM: (12)
第7章总结 (13)
参考文献 (15)
第1章实验介绍及整体框架
1.1实验目的:
通过实验,加深对所学的关于程序语言与编译的理论知识的理解,增强对所学知识的综合应用能力。
通过本实验,进一步明确编译各阶段之间的关系,掌握词法分析、语法分析、语义分析等实现技术及其实现,熟悉符号表的管理及其在编译过程中的作用,掌握错误处理机制及其应用。
1.2实验环境:
硬件:主机:586以上,配有鼠标,
内存:256MB以上
显示器:VGA或以上
硬盘空间:500MB以上
软件:Microsoft Visual C++ 6.0
1.3 C-编译器的整体框架
输入文件
开始
词法分析语法分析建立符号表类型检查代码生成
结束语法树符号表
第2章词法分析
2.1 词法分析包括两个类:
(1)Class CTokenizer:从一个字符串中(这个把一个文件看作是一个字符串,MFC中CFile->CString)分离出一个一个token,配上简单的类型通过NextToken()返回:
#define TT_EOL '\n'
#define TT_EOF -1
#define TT_INTEGER -2
#define TT_REAL -3
#define TT_WORD -4
#define TT_STRING '"'
#define TT_CHAR '\''
(2)Class CScaner:得到具体的的token类型,定义TokenType如下:
enum TokenType
{
// reserved Keyword
_AUTO, _DOUBLE, _INT, _STRUCT,
_BREAK, _ELSE, _LONG, _SWITCH,
_CASE, _ENUM, _REGISTER, _TYPEDEF,
_CHAR, _EXTERN, _RETURN, _UNION,
_CONST, _FLOAT, _SHORT, _UNSIGNED,
_CONTINUE, _FOR, _SIGNED, _VOID,
_DEFAULT, _GOTO, _SIZEOF, _VOLA TILE,
_DO, _IF, _STATIC, _WHILE,
_READ, _WRITE, _PRINTF,
// operations
ASSIGN, PLUS, MINUS, TIMES, DIV, MOD,
BITWISE_AND, BITWISE_OR, BITWISE_NOT, LOGICAL_NOT, LT, GT,
// interpunctions
LPARAN, RPARAN, LBRACE, RBRACE, LSQUARE, RSQUARE, COMMA, DOT, SEMI, COLON,
// complex operations
EQ/* == */, NEQ/* != */, PLUS_PLUS/* ++ */, MINUS_MINUS/* -- */,
PLUS_ASSIGN/* += */, MINUS_ASSIGN/* -= */, TIMES_ASSIGN/* *= */, DIV_ASSIGN/* /= */,
NGT/* <= */, NLT/* >= */, LOGICAL_AND/* && */, LOGICAL_OR/* || */,
// others
_EOF, _ID, _NUM, _STRING, _CHARACTER, _LABEL, _ERROR, _NONE
};
CScaner通过一个CMap<CString, LPCSTR, enum TokenType, enum TokenType> m_KeyIndex 把CString的关键字和TokenType对应,便于查找和反向查找。
2.2 C关键字表:
auto double int struct
break else long switch
case enum register typedef
char extern return union
Const float short unsigned
Continue for signed void
Default goto sizeof volatile
Do if static while
2.3 标识符词法:
identifier :
nondigit
identifier nondigit
identifier digit
nondigit : one of
_ a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
digit : one of
0 1 2 3 4 5 6 7 8 9
escape:
\n, \r, \b, \0-7
第3章语法分析
3.1 Class CParser:
定义CTreeNode,和Tiny例程类似:
#define MAX_CHILDREN 3
class CTreeNode
{
public:
CTreeNode* child[ MAX_CHILDREN ]; // point to child node
CTreeNode* father; // point to father node
CTreeNode* sibling; // point to sibling node
int lineno;
NodeKind nodekind;
union {
StmtKind stmt;
ExpKind exp;
} kind;
enum TokenType type;
CString szName;
CString szScope; // node function scope
BOOL bArray; // is this an array declaration
int iArraySize; // array size
};
通过文法及相应规则建立语法树。
3.2 Grammar:
1.program->declaration_list
2.declaration_list->declaration_list declaration | declaration
3.declaration->var_declaration | fun_declaration
4.var_declaration->type_specifier ID(, ...)`;` | type_specifier ID `[` NUM `]`(, ...)`;`
5.type_specifier->`int` | `void` | `char`, actually this step is in declaration_list()
6.fun_declaration->type_specifier ID `(` params `)` compound_stmt
7.params->param_list | `void` | empty, `void` is thought as empty
8.param_list->param_list `,` param | param
9.param->type_specifier ID | type_specifier ID `[` `]`
pound_stmt->`{` loal_declarations statement_list `}` | expression_stmt
11.local_declarations->local_declarations var_declaration | var_declaration
12.`read` `(` var `)` `;`
13.`write` `(` expression `)` `;`
14.`printf` `(` `"` STRING `"` `)` `;`
15.expression_stmt->expression `;` | `;`
16.expression->var `=` expression | logic1_expression
17.logic1_expression->logic1_expression `||` logic2_expression | logic2_expression
18.logic2_expression-> logic2_expression `&&` simple_expression | simple_expression
19.simple_expression->additive_expression relop additive_expression | additive_expression
20.relop-> `<=` | `<` | `>` | `>=` | `==` | `!=`
21.additive_expression -> additive_expression addop term | term
22.addop-> `+` | `-`
23.term->term mulop logic3_expression | logic3_expression
24.mulop-> `*` | `/` | `%`
25.logic3_expression-> `!` logic3_expression | factor
26.factor->`(` expression `)` | var | call | NUM
27.var->ID | ID `[` expression `]`
28.call->ID `(` args `)`
29.args->args_list | empty
30.args_list->args_list `,` expression | expression
31.sub_compoundstmt->ID `:` | call `;` | expression_stmt
32.if_stmt->`if` `(` expression `)` compound_stmt
| `if` `(` expression `)` compound_stmt `else` compound_stmt
33.while_stmt->`while` `(` expression `)` compound_stmt
34.for_stmt->`for` `(` var `=` expression `;` expression `;` var `=` expression `)`
compound_stmt
35.goto_stmt->`goto` ID `;`
36.break_stmt->`break` `;`
37.continue_stmt->`continue` `;`
38.return_stmt->`return` `;` | `return` expression `;`
3.3 基本树形结构:
if语句:
while语句:
if语句
表达式语句语句
while语句
表达式语句
for
复合语句:
3.4 支持的语句及运算:
1) 数据类型:int ,char void ,PCode 里支持float ,在80x86 ASM 里不支持 2) 语句:赋值(=),if, while ,for ,return ,break ,continue 3) 数学运算:+,-,*,/
4) 关系运算:= =,>,<,>=,<=,!= 5) 逻辑运算:&&,||,! 6) 支持函数的定义、调用 7) 支持复合语句
8) 注释语句:C 类型的 /* */ 和C++类型的 //
表达式
语句
表达式
for 语句
表达式
语句
复合语句
语句
语句
声明
第4章建立符号表
4.1 辅助类:
(1) Class LineListRec:
主要成员是lineno,记录某个Token(变量或函数名)声明或使用时的行
数。
(2) Class BucketListRec:
主要成员变量:
CString name; // variable name
CString scope; // function scope
enum TokenType t ype;
int memloc;// memory location for variable
BOOL bArray; // for array checking
LineListRec* lineno;
BucketListRec* next;
4.2 主要的类,建立符号表:
(1) Class CSymbolTable:
主要成员变量:BucketListRec* hashTable[SIZE],把Class BucketListRec 类的对象通过hash函数找到位置后插入。
函数PrintSymbalTable(LPCTSTR lpszPathName),输入文件名,通过一个递归函数输出符号表到文件lpszPathName。
(2) Class CFunArgsCheck:
插入函数参数的类型,以备在下一个步骤中做匹配检测。
第5章类型检测
5.1 Class CAnalyzer包括两个部分:
(1) 类型匹配:
函数或变量声明时检测是否已声明,如已声明则抛出错误;函数调用或变量使用时检测是否已声明,如未声明则抛出错误。
(2) 函数调用参数检测:
检测函数调用时传入参数的类型与函数声明时参数的类型是否匹配。
第6章代码生成
6.1 PCode:
程序支持的p-code语句:
lda 取变量地址
lod 取变量值
ldci 取int类型常数
ldcf 取float类型常数
ldcc 取char类型常数
ldc 取bool类型常数
fjp 错误跳跃
tjp 正确跳跃
ujp 无条件跳跃
stn 存储并保留值
sto 存储不保留值
ind 根据堆栈上的地址取值
ixa 根据堆栈上的地址取地址
adi int类型加法
adr float类型加法
sbi int类型减法
sbr float类型减法
mpi int类型乘法
mpr float类型乘法
dvi int类型除法
dvr float类型除法
mod %运算
grt >运算
les <运算
geq >=运算
leq <=运算
equ ==运算
not !运算
neq !=运算
and 位与运算
or 位或运算
mst 标志函数调用的参数的开始
ent 函数定义开始
ret 函数返回
cup 调用函数
lab 标号
rdc 从屏幕读取一个字符
rdi 从屏幕读取一个整数
rdf 从屏幕读取一个浮点数
wrc 输出一个字符到屏幕
wri 输出一个整数到屏幕
wrf 输出一个浮点数到屏幕
部分p-code为自定义,没有解释器。
6.2 80X86 ASM:
支持80x86 asm代码,因此数据多为16位,但支持递归调用,使用较多伪操作,需要MASM 6.0以上版本才能编译通过。
第7章总结
(1)这个程序使用了界面库CJLIB6.0,自己修改了CrystalView的高亮显示方式,仿照emacs,代码生成PCode,便于理解,后又编写了80x86汇编代码的生成。
整个程序具有比较友好的GUI界面,语法支持(基于所要求的)也比较全面。
程序运行界面如图1:
(2)运行成功的样例:
输入程序:
void main()
{
int i, j;
i = j = 1;
}
扫描各行代码:
line: 1 Token Code: 23 void
line: 1 Token Code: 70 main
line: 1 Token Code: 47 (
line: 1 Token Code: 48 )
line: 2 Token Code: 49 {
line: 3 Token Code: 02 int
line: 3 Token Code: 70 i
line: 3 Token Code: 53 ,
line: 3 Token Code: 70 j
line: 3 Token Code: 55 ;
line: 5 Token Code: 70 i
line: 5 Token Code: 35 =
line: 5 Token Code: 70 j
line: 5 Token Code: 35 =
line: 5 Token Code: 71 1
line: 5 Token Code: 55 ;
line: 6 Token Code: 50 }
编译得到符号表:
Scope Variable Name Type Location Line Numbers
------------- ------------- ------ -------- ------------
global main void 0 1
main i int 1 3 5
main j int 2 3 5
对程序进行分析:
Function declaration: void main
Variable declaration: int i
Variable declaration: int j
Op: =
ID: i
Op: =
ID: j
const: 1
编译生成PCode:
start of function 'void main(...)' declaration
ent main
;declaration: int i
;declaration: int j
lda i
lda j
ldci 1
stn
sto
ret
;end of function 'void main(...)' declaration
各行PCode意思可参见第6章。
(3)运行失败的样例:
#include<stdio.h>
#include<conio.h>
void main()
{
printf("Hello World!\n");
}
原因是C-编译不支持包含头文件。
参考文献
[1]Steven S.Muchnick 《Advanced Compiler Design and Implementation》.
[2]陈火旺,《程序设计语言编译原理》。
[3]Alfred V.Aho,Ravi Sethi,Jeffrey D.Ullman,《编译原理》。
[4]John E.Hopcroft,Rajeev Motwani,Jeffrey D.Ullman,《自动机理论、语言和
计算导论》。