Skip to content

Commit

Permalink
Add myc, an interpreter for simple C
Browse files Browse the repository at this point in the history
  • Loading branch information
sheisc committed Sep 4, 2020
1 parent fbcd526 commit 4daa2ec
Show file tree
Hide file tree
Showing 19 changed files with 2,043 additions and 0 deletions.
Binary file added myc/doc/简单C编译器语法图.doc
Binary file not shown.
Binary file added myc/doc/简单C编译器语法图.pdf
Binary file not shown.
Binary file not shown.
Binary file not shown.
54 changes: 54 additions & 0 deletions myc/readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
1.Directory:
---
|
|------src 源代码
|
|
|------doc 相关文档
|
|
|------readme.txt

2. How to use
(1) 在Linux平台上,进入src目录,执行make命令,即可得到myc编译器
make

(2) 运算测试代码

./myc ./test.c

3. 简单C编译器
(1). 实现栈式存储管理,支持函数的递归调用
(2). 支持函数参数的传递
(3). 实现if语句、while语句、赋值语句(尚未支持for语句)
(4). 不要求局部变量都放在函数体的开始处声明,提供了局部变量声明的灵活性。
(5). 只支持int型(尚支持其他数据类型),不支持void,要求所有函数的返回值为int
(6). 允许int型全局变量
(7). 为了简单起见,提供scanf和printf关键字来支持输入输出,如
int a,b ;
scanf(a,b); //从键盘接受一个输入
printf(a+1,b); //输出a+1和b的值
(8). 尚未支持指针
(9). 要求程序提供int型的main函数
(10). 2007年写的旧代码. 采用的是先编译后解释的思想,自定义了类似X86的汇编形式的中间代码
然后在虚拟机上解释执行。
(11). 采用的是基于语法图的自顶向下的分析方法。
expression.cpp实现了表达式的翻译
program_body.cpp实现了整个程序体的翻译
statement.cpp实现了语句的翻译
function_body.cpp实现了函数体的翻译
var_declare.cpp实现了变量声明的翻译
param_declare.cpp实现了函数参数声明的翻译
sym_table.cpp实现了符号表的管理
lex.cpp实现了词法分析器
c.cpp是主程序
virtual_machine.cpp实现了虚拟机
c.h为头文件
(12). 简单C编译器采用的是Wirth先生的PL/0(简化后的Pascal语言编译器)的框架.


sheisc@163.com




49 changes: 49 additions & 0 deletions myc/src/.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
0: SetBx 1 0 0
1: Jmp 0 0 32
2: Init 4 1 0
3: Jeq 3 4 8
4: Jmp 0 0 5
5: Init 4 2 0
6: Jeq 3 4 8
7: Jmp 0 0 12
8: Init 4 1 0
9: Mov 2 4 0
10: Ret 0 0 0
11: Jmp 0 0 31
12: Init 9 1 0
13: Sub 3 9 9
14: Mov 8 9 0
15: Init 6 19 0
16: Init 5 5 0
17: AddBx 5 0 0
18: Call 2 0 0
19: Mov 4 7 0
20: Init 10 2 0
21: Sub 3 10 10
22: Mov 9 10 0
23: Init 7 27 0
24: Init 6 6 0
25: AddBx 6 0 0
26: Call 2 0 0
27: Mov 5 8 0
28: Add 4 5 4
29: Mov 2 4 0
30: Ret 0 0 0
31: Ret 0 0 0
32: Init 4 1 0
33: Mov 3 4 0
34: Init 4 20 0
35: Jlt 3 4 37
36: Jmp 0 0 48
37: Mov 8 3 0
38: Init 6 42 0
39: Init 5 5 0
40: AddBx 5 0 0
41: Call 2 0 0
42: Mov 4 7 0
43: Out 4 0 0
44: Init 4 1 0
45: Add 3 4 4
46: Mov 3 4 0
47: Jmp 0 0 34
48: Ret 0 0 0
11 changes: 11 additions & 0 deletions myc/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#COMPILE.cpp = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
CXX = g++ -Wno-write-strings
OUTPUT_OPTION = -o $@

myc: expression.o program_body.o statement.o function_body.o var_declare.o \
param_declare.o sym_table.o virtual_machine.o lex.o c.o
$(CXX) $^ -o myc
%.o: %.c
$(CXX) -c $(OUTPUT_OPTION) $<
clean:
rm -rf *.o myc
134 changes: 134 additions & 0 deletions myc/src/c.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c.h"

#define ZCW_DEBUG

//////////////////////////////////////////////////////////////////////
int errorCount = 0;
int ds[DsSize]; //数据段 0号单元不用
Instruction cs[CsSize]; //代码段
int csIndex = 2; //代码段下标 1号预留给(最终会)跳转到main的指令
//0号单元用于存放初始"变址寄存器"的指令
//int dsIndex = 0; //数据段下标
FILE * infile; //输入文件
FILE * outfile; //输出文件


char * instrs[] = {
"Jtrue", //为真则跳转 (InsJtrue, arg1, , dest)
"Jfalse", //为假则跳转 (InsJfalse,arg1, , dest)
"Jmp", //无条件跳转 (InsJmp, , , dest)
"Mov", //数据复制 (InsMov, arg1, ,dest)
"Init", //初始化某单元 (InsInit,arg1,num, )
"Add", //加法 (InsAdd, arg1,arg2,dest)
"Sub", //减法 (InsSub, arg1,arg2,dest)
"Mul", //乘法 (InsMul, arg1,arg2,dest)
"Div", //除法 (InsDiv, arg1,arg2,dest)
"Mod", //取余
"Nop", //空操作 (InsNop, , , )
"Jlt", //判断是否< (InsLt,arg1,arg2,result)
"Jle", //判断是否<= (InsLe,arg1,arg2,result)
"Jgt", //判断是否> (InsGt,arg1,arg2,result)
"Jge", //判断是否>=
"Jeq", //判断是否==
"Jne", //判断是否!=
"Or", //逻辑或运算
"And", //逻辑与运算
"Not", //逻辑非运算
"In", //输入
"Out", //输出
"Uminus", //求相反数
"Call", //过程调用 (InsCall,des, , ,);
"Ret", //过程返回 (InsRet,expr, , );
"SetBx", //设置bx指针,指向活动记录首地址(InsSetBx,addr, , )
"AddBx", //增加bx的值
};
//////////////////////////////////////////////////////////////////////////

void printCsInfo(){
for(int i = 0; i < csIndex; i++){
/*
printf("%s %d %d %d\n",
instrs[cs[i].optr],cs[i].arg1,cs[i].arg2,cs[i].result);
*/
fprintf(outfile,"%d:\t %s %d %d %d\n",
i,instrs[cs[i].optr],cs[i].arg1,cs[i].arg2,cs[i].result);
}
}



/**
* 产生一条四元式指令
*/
void gen(int instrType, int arg1,int arg2,int result){
if(csIndex >= CsSize){
printf("Code Segment overflows.");
exit(1);
}
//
cs[csIndex].optr = instrType;
cs[csIndex].arg1 = arg1;
cs[csIndex].arg2 = arg2;
cs[csIndex].result = result;
csIndex++;
}
/**
* 语法错误处理
*/
void syntaxError(char * info){
errorCount++;
printf("line %d : %s\n",lineNumber,info);
//naive error recovery strategy,but simple :)
//added by zcw, 2010.2.25
exit(1);
}

/**
* main函数
*/
int main(int argc,char * args[]){

if(argc >= 2){
if((infile = fopen(args[1],"r")) == NULL){
printf("can't open file %s .\n",args[1]);
exit(1);
}
else{
char name[80];
strcpy(name,args[1]);
char * dot = strchr(name,'.');
if(dot == NULL){
strcat(name,".s");
}
else{
strcpy(dot,".s");
}
if( (outfile = fopen(name,"w")) == NULL){
fclose(infile);
printf("can't not create file %s.\n",name);
exit(1);
}
}
}
else{
printf("parameter specifying input file needed.\n");
exit(1);
}
getToken();
programBody();
if(token != EOF){
syntaxError("EOF needed.");
}
printCsInfo();
if(errorCount == 0)
interpret();
else
printf("there are %d errors in program.",errorCount);
fclose(infile);
fclose(outfile);
printf("\n");
return 0;
}
Loading

0 comments on commit 4daa2ec

Please sign in to comment.