【PCC】一個用python寫的c語言編譯器


本文2019年首發自本人原獨立站點,后來疲於生活,不想折騰個人獨立站點,將文章搬運自博客園

PCC——python實現編譯器

大學的編譯原理課設,實現源碼到匯編代碼的翻譯,鏈接部分使用gcc的功能。目前支持數組,四則運算,賦值,判斷,輸出,循環語句等。

項目地址:https://github.com/flymysql/Py-Compiler

源碼說明

  1. lexer.py 詞法分析器
  2. get_predict_table.py 生成預測分析表
  3. LR.py 非遞歸的語法分析器
  4. generate.py 中間代碼生成
  5. to_asm.py 匯編代碼生成
  6. pcc.py 入口函數

使用

$ python pcc.py

命令說明

pcc -o (filename) 直接編譯生成可執行程序
pcc -s (filename) 生成匯編源碼
pcc -t (filename) 查看語法樹生成過程
pcc -l (filename) 查看詞法分析
pcc -h 查看幫助
pcc -p 查看本編譯器的預測分析表
pcc -g 查看本編譯器的語法推導
exit 退出

編譯代碼

pcc -o ./test/test.c

聲明語句和賦值語句

int a;
a = 10;
int b = a;
int a = 1 + 2*(3 - 4);

數組

int arr[10];
a[0] = 1;
int b = a[0];

數組下標,即[]中內容也可以用表達式嵌套

int index = 5;
arr[index] = 6;
arr[arr[(index+1)*2-1]] = 7;

輸出語句

目前printf語句的參數最多可以帶三個參數

printf("這是個不帶參數的printf");
printf("這是個參數%d",a);
printf("三個參數:%d,%d,%d",a,b,c);
char c="T";
printf("字符型參數:%c",c);
printf語句的參數也可以是表達式

例子

printf("%d", d + 2*(3+4));

控制語句

目前僅支持if判斷,可嵌套使用

if(a < 2*10){
	a = a + 1;
	if(c < a){
		printf("%d", a*c);
	}
}

while控制語句

這個不多說,也是可嵌套

int i = 1;
printf("正在由pcc編譯器為你打印99乘法表!");
while(i < 10){
	int j = i;
	while(j < 10){
		printf("%d*%d=%d	",i, j, i*j);
		j = j + 1;
	}
	printf("\n");
	i = i +1;
}

舉個栗子(打印99乘法表)

源demo

int main(){
    // 打印99乘法表
    // int a[10];
    int i = 1;
    printf("正在由pcc編譯器為你打印99乘法表!");
    while(i < 10){
        int j = i;
        while(j < 10){
            printf("%d*%d=%d	",i, j, i*j);
            j = j + 1;
        }
        printf("\n");
        i = i +1;
    }
}

舉個栗子(打印斐波那契數列)

c語言源碼

// 蘭州小紅雞的注釋測試
int main(){
    int arr[25];
    int index = 0;
    // 求0~20的斐波那契數列
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    while(index < 10*2 ){
        int b = arr[index];
        arr[index+2]=arr[index+1] + b;
        printf("f(%d)=%d",index,b);
        index = index +1;
    }
    printf("完成斐波那契數列打印!由小雞編譯器提供——pcc");
}

生成的中間代碼(四元式)

(=,0,0,index)
(=,1,0,arr[]0)
(=,2,0,arr[]1)
(=,3,0,arr[]2)
(code_block,0,0,W4)
(j<,index,20,code6)
(j,0,0,block6)
(code_block,0,0,code6)
(=,arr[]index,0,b)
(+,index,1,T0)
(+,arr[]T0,b,T1)
(+,index,2,T2)
(=,T1,0,arr[]T2)
(print,index,b,-1)
(+,index,1,T3)
(=,T3,0,index)
(j,0,0,W4)
(code_block,0,0,block6)
(print,-1,-1,-1)

生成的匯編代碼

	.text
	.section	.rodata
	.comm	T0,4,4
	.comm	T1,4,4
	.comm	T2,4,4
	.comm	T3,4,4
.LC0:
	.string "f(%d)=%d"
.LC1:
	.string "完成斐波那契數列打印!由小雞編譯器提供——pcc"
	.text
	.globl	main
	.type	main, @function
main:

	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$120, %rsp
	movl	$0, -8(%rbp)
	movl	$0, -12(%rbp)
	movl	$1, -112(%rbp)
	movl	$2, -108(%rbp)
	movl	$3, -104(%rbp)
.W5:
	movl	-12(%rbp), %eax
	cmpl	$20, %eax
	jle	.code7
	jmp	.block7
.code7:
	movl	-12(%rbp), %eax
	cltq
	movl	-112(%rbp, %rax, 4), %ecx
	movl	%ecx, -8(%rbp)
	movl	-12(%rbp), %edx
	movl	$1, %eax
	addl	%edx, %eax
	movl	%eax, T0(%rip)
	movl	T0(%rip), %eax
	cltq
	movl	-112(%rbp, %rax, 4), %edx
	movl	-8(%rbp), %eax
	addl	%edx, %eax
	movl	%eax, T1(%rip)
	movl	-12(%rbp), %edx
	movl	$2, %eax
	addl	%edx, %eax
	movl	%eax, T2(%rip)
	movl	T2(%rip), %eax
	cltq
	movl	T1(%rip), %ecx
	movl	%ecx, -112(%rbp, %rax, 4)
	movl	-12(%rbp), %eax
	movl	-8(%rbp), %edx
	movl	%eax, %esi
	leaq	.LC0(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT
	movl	-12(%rbp), %edx
	movl	$1, %eax
	addl	%edx, %eax
	movl	%eax, T3(%rip)
	movl	T3(%rip), %ecx
	movl	%ecx, -12(%rbp)
	jmp	.W5
.block7:
	movl	%eax, %esi
	leaq	.LC1(%rip), %rdi
	movl	$0, %eax
	call	printf@PLT

	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE6:
	.size	main, .-main
	.ident	"PCC: 1.0.0"

其他命令自行發覺hhh


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM