您尚未登录。

楼主 #1 2018-05-04 21:09:04

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

写一个简单的编译器-flex&yacc

先贴代码吧:
1,pre_compiler.l

%{
#include <stdio.h>
#include <string.h>
#include "pre_compiler.tab.h"
#define YY_SKIP_YYWRAP
extern int yylval;

int yylex(void);

typedef struct {
	char name[128];
	int init;
	int value;
}var_store;
static var_store var_store_buf[8192];
static int var_store_cnt = 0;

static void exp_store_print(FILE* file, int index) {
	fprintf(file, (const char*)"%s\n", (const char*)var_store_buf[index].name);
}

static int exp_store0(int num) {
	sprintf((char*)var_store_buf[var_store_cnt].name, (const char*)"%d", num);
	var_store_buf[var_store_cnt].init = 0;
	var_store_buf[var_store_cnt++].value = 0;
	return var_store_cnt - 1;
}

static int exp_store1(const char* str, int a) {
	char* p_a;
	if ((a < 0) || (a >= var_store_cnt)) {
		return -1;
	}
	p_a = (char*)var_store_buf[a].name;
	sprintf((char*)var_store_buf[var_store_cnt].name, str, p_a);
	var_store_buf[var_store_cnt].init = 0;
	var_store_buf[var_store_cnt++].value = 0;
	return var_store_cnt - 1;
}

static int exp_store2(const char* str, int a, int b) {
	char* p_a;
	char* p_b;
	if ((a < 0) || (a >= var_store_cnt) || (b < 0) || (b >= var_store_cnt)) {
		return -1;
	}
	p_a = (char*)var_store_buf[a].name;
	p_b = (char*)var_store_buf[b].name;
	sprintf((char*)var_store_buf[var_store_cnt].name, str, p_a, p_b);
	var_store_buf[var_store_cnt].init = 0;
	var_store_buf[var_store_cnt++].value = 0;
	return var_store_cnt - 1;
}

static int exp_store3(const char* str, int a, int b, int c) {
	char* p_a;
	char* p_b;
	char* p_c;
	if ((a < 0) || (a >= var_store_cnt) || (b < 0) || (b >= var_store_cnt) || (c < 0) || (c >= var_store_cnt)) {
		return -1;
	}
	p_a = (char*)var_store_buf[a].name;
	p_b = (char*)var_store_buf[b].name;
	p_c = (char*)var_store_buf[c].name;
	sprintf((char*)var_store_buf[var_store_cnt].name, str, p_a, p_b, p_c);
	var_store_buf[var_store_cnt].init = 0;
	var_store_buf[var_store_cnt++].value = 0;
	return var_store_cnt - 1;
}

static void var_store_init(void) {
	for (var_store_cnt = 4095; ; var_store_cnt--) {
		strcpy((char*)var_store_buf[var_store_cnt].name, (const char*)"");
		var_store_buf[var_store_cnt].value = 0;
		var_store_buf[var_store_cnt].init = 0;
		if (0 == var_store_cnt) {
			break;
		}
	}
}

static int var_store_read(int index) {
	if ((index >= 0) && (index < var_store_cnt) && var_store_buf[index].init) {
		return var_store_buf[index].value;
	}
	return 0;
}

static void var_store_write(int index, int value) {
	if ((index >= 0) && (index < var_store_cnt)) {
		var_store_buf[index].value = value;
		var_store_buf[index].init = -1;
	}
}

static int var_store_find(const char* name) {
	int i;
	for (i = 0; i < var_store_cnt; i++) {
		if (0 == strcmp((const char*)var_store_buf[i].name, name)) {
			return i;
		}
	}
	strcpy((char*)var_store_buf[var_store_cnt].name, name);
	var_store_buf[var_store_cnt].init = 0;
	var_store_buf[var_store_cnt++].value = 0;
	return var_store_cnt - 1;
}

static int is_var_inited(int index) {
	return var_store_buf[index].init;
}

static int bin2num(const char* bin) {
	int num;
	if ('0' != *bin++) {
		return 0;
	}
	if ('b' != *bin++) {
		return 0;
	}
	for (num = 0; *bin; bin++) {
		num <<= 1;
		if ('1' == *bin) {
			num |= 1;
		}
	}
	return num;
}

%}

subwf "subwf"
decf "decf"
addwf "addwf"
comf "comf"
incf "incf"
sublw "sublw"
addlw "addlw"
adcwf "adcwf"
sbcwf "sbcwf"
daa "daa"
das "das"
clrf "clrf"
clrw "clrw"
iorwf "iorwf"
andwf "andwf"
xorwf "xorwf"
rrf "rrf"
rlf "rlf"
swapf "swapf"
bcf "bcf"
bsf "bsf"
andlw "andlw"
xorlw "xorlw"
iorlw "iorlw"
decfsz "decfsz"
incfsz "incfsz"
btfsc "btfsc"
btfss "btfss"
goto "goto"
call "call"
return "return"
retfie "retfie"
retlw "retlw"
movwf "movwf"
movf "movf"
movlw "movlw"
nop "nop"
option "option"
tris "tris"
sleep "sleep"
clrwdt "clrwdt"
int "int"

equ "equ"
org "org"
end "end"
label ":"
split ","
note ";"[^\n]*
next_line [\n]
space [ \t]+

plus "+"
minus "-"
times "*"
divide "/"
lp "("
rp ")"

num [0-9]+
hex1 "0x"[0-9a-fA-F]+
hex2 [0-9]+[0-9a-fA-F]*[hH]
bin "0b"[01]+
var [_a-zA-z]+[_a-zA-z0-9]*

%%
{subwf} {
	yylval = var_store_find(yytext);
	return SUBWF;
}
{decf} {
	yylval = var_store_find(yytext);
	return DECF;
}
{addwf} {
	yylval = var_store_find(yytext);
	return ADDWF;
}
{comf} {
	yylval = var_store_find(yytext);
	return COMF;
}
{incf} {
	yylval = var_store_find(yytext);
	return INCF;
}
{sublw} {
	yylval = var_store_find(yytext);
	return SUBLW;
}
{addlw} {
	yylval = var_store_find(yytext);
	return ADDLW;
}
{adcwf} {
	yylval = var_store_find(yytext);
	return ADCWF;
}
{sbcwf} {
	yylval = var_store_find(yytext);
	return SBCWF;
}
{daa} {
	yylval = var_store_find(yytext);
	return DAA;
}
{das} {
	yylval = var_store_find(yytext);
	return DAS;
}
{clrf} {
	yylval = var_store_find(yytext);
	return CLRF;
}
{clrw} {
	yylval = var_store_find(yytext);
	return CLRW;
}
{iorwf} {
	yylval = var_store_find(yytext);
	return IORWF;
}
{andwf} {
	yylval = var_store_find(yytext);
	return ANDWF;
}
{xorwf} {
	yylval = var_store_find(yytext);
	return XORWF;
}
{rrf} {
	yylval = var_store_find(yytext);
	return RRF;
}
{rlf} {
	yylval = var_store_find(yytext);
	return RLF;
}
{swapf} {
	yylval = var_store_find(yytext);
	return SWAPF;
}
{bcf} {
	yylval = var_store_find(yytext);
	return BCF;
}
{bsf} {
	yylval = var_store_find(yytext);
	return BSF;
}
{andlw} {
	yylval = var_store_find(yytext);
	return ANDLW;
}
{xorlw} {
	yylval = var_store_find(yytext);
	return XORLW;
}
{iorlw} {
	yylval = var_store_find(yytext);
	return IORLW;
}
{decfsz} {
	yylval = var_store_find(yytext);
	return DECFSZ;
}
{incfsz} {
	yylval = var_store_find(yytext);
	return INCFSZ;
}
{btfsc} {
	yylval = var_store_find(yytext);
	return BTFSC;
}
{btfss} {
	yylval = var_store_find(yytext);
	return BTFSS;
}
{goto} {
	yylval = var_store_find(yytext);
	return GOTO;
}
{call} {
	yylval = var_store_find(yytext);
	return CALL;
}
{return} {
	yylval = var_store_find(yytext);
	return RETURN;
}
{retfie} {
	yylval = var_store_find(yytext);
	return RETFIE;
}
{retlw} {
	yylval = var_store_find(yytext);
	return RETLW;
}
{movwf} {
	yylval = var_store_find(yytext);
	return MOVWF;
}
{movf} {
	yylval = var_store_find(yytext);
	return MOVF;
}
{movlw} {
	yylval = var_store_find(yytext);
	return MOVLW;
}
{nop} {
	yylval = var_store_find(yytext);
	return NOP;
}
{option} {
	yylval = var_store_find(yytext);
	return OPTION;
}
{tris} {
	yylval = var_store_find(yytext);
	return TRIS;
}
{sleep} {
	yylval = var_store_find(yytext);
	return SLEEP;
}
{clrwdt} {
	yylval = var_store_find(yytext);
	return CLRWDT;
}
{int} {
	yylval = var_store_find(yytext);
	return INT;
}

{equ} {
	yylval = var_store_find(yytext);
	return EQU;
}
{org} {
	yylval = var_store_find(yytext);
	return ORG;
}
{end} {
	yylval = var_store_find(yytext);
	return END;
}
{label} {
	return LABEL;
}
{split} {
	return SPLIT;
}
{next_line} {
	return NEXT_LINE;
}
{space} {
}
{note} {
}

{num} {
	sscanf(yytext, "%d", &yylval);
	return NUM;
}
{hex1} {
	sscanf(yytext, "0x%x", &yylval);
	return NUM;
}
{hex2} {
	sscanf(yytext, "%x", &yylval);
	return NUM;
}
{bin} {
	yylval = bin2num(yytext);
	return NUM;
}
{plus} {
	return PLUS;
}
{minus} {
	return MINUS;
}
{times} {
	return TIMES;
}
{divide} {
	return DIVIDE;
}
{lp} {
	return LP;
}
{rp} {
	return RP;
}
{var} {
	yylval = var_store_find(yytext);
	if (is_var_inited(yylval)) {
		yylval = var_store_read(yylval);
		return NUM;
	}
	else {
		return VAR;
	}
}

. {
}

%%

离线

楼主 #2 2018-05-04 21:10:15

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

Re: 写一个简单的编译器-flex&yacc

2,pre_compiler.y

%{
#include <stdio.h>
#define YYSTYPE int
#include "lex.yy.c"
int yyparse(void);
void yyerror(char* s);

static FILE* file_temp = NULL;
static int code_addr = 0;
%}

%token VAR NUM PLUS MINUS TIMES DIVIDE LP RP SPLIT SUBWF DECF ADDWF COMF INCF SUBLW ADDLW ADCWF SBCWF DAA DAS CLRF CLRW IORWF ANDWF XORWF RRF RLF SWAPF BCF BSF ANDLW XORLW IORLW DECFSZ INCFSZ BTFSC BTFSS GOTO CALL RETURN RETFIE RETLW MOVWF MOVF MOVLW NOP OPTION TRIS SLEEP CLRWDT INT EQU ORG END LABEL NEXT_LINE

%%
file: file NEXT_LINE {}
	| codes END {fprintf(file_temp, (const char*)"end\n");}
	;
codes: codes code {}
	| codes pre_code {}
	| codes NEXT_LINE {}
	| code {}
	| pre_code {}
	;
code: code2 exp_var SPLIT exp_var NEXT_LINE {$$ = exp_store3("%s %s, %s", $1, $2, $4); exp_store_print(file_temp, $$);}
	| code1 exp_var NEXT_LINE {$$ = exp_store2("%s %s", $1, $2); exp_store_print(file_temp, $$);}
	| code0 NEXT_LINE {$$ = $1; exp_store_print(file_temp, $$);}
	;
pre_code: VAR EQU exp NEXT_LINE {var_store_write($1, $3);}
	| ORG exp NEXT_LINE {code_addr = $2; fprintf(file_temp, (const char*)"org %d\n", $2);}
	| VAR LABEL NEXT_LINE {var_store_write($1, code_addr);}
	;
code0: DAA {$$ = $1;}
	| DAS {$$ = $1;}
	| CLRW {$$ = $1;}
	| RETURN {$$ = $1;}
	| RETFIE {$$ = $1;}
	| NOP {$$ = $1;}
	| OPTION {$$ = $1;}
	| SLEEP {$$ = $1;}
	| CLRWDT {$$ = $1;}
	| INT {$$ = $1;}
	;
code1: SUBLW {$$ = $1;}
	| ADDLW {$$ = $1;}
	| CLRF {$$ = $1;}
	| ANDLW {$$ = $1;}
	| XORLW {$$ = $1;}
	| IORLW {$$ = $1;}
	| GOTO {$$ = $1;}
	| CALL {$$ = $1;}
	| RETLW {$$ = $1;}
	| MOVWF {$$ = $1;}
	| MOVLW {$$ = $1;}
	| TRIS {$$ = $1;}
	;
code2: SUBWF {$$ = $1;}
	| DECF {$$ = $1;}
	| ADDWF {$$ = $1;}
	| COMF {$$ = $1;}
	| INCF {$$ = $1;}
	| ADCWF {$$ = $1;}
	| SBCWF {$$ = $1;}
	| IORWF {$$ = $1;}
	| ANDWF {$$ = $1;}
	| XORWF {$$ = $1;}
	| RRF {$$ = $1;}
	| RLF {$$ = $1;}
	| SWAPF {$$ = $1;}
	| BCF {$$ = $1;}
	| BSF {$$ = $1;}
	| DECFSZ {$$ = $1;}
	| INCFSZ {$$ = $1;}
	| BTFSC {$$ = $1;}
	| BTFSS {$$ = $1;}
	| MOVF {$$ = $1;}
	;
exp_var: exp_var PLUS term_var {$$ = exp_store2("%s + %s", $1, $3);}
	| exp_var MINUS term_var {$$ = exp_store2("%s - %s", $1, $3);}
	| term_var {$$ = $1;}
	;
term_var: term_var TIMES factor_var {$$ = exp_store2("%s * %s", $1, $3);}
    | term_var DIVIDE factor_var {$$ = exp_store2("%s / %s", $1, $3);}
    | factor_var {$$ = $1;}
	;
factor_var: VAR {$$ = $1;}
	| LP exp_var RP {$$ = exp_store1("(%s)", $2);}
	| exp {$$ = exp_store0($1);}
	;
exp: exp PLUS term {$$ = $1 + $3;}
	| exp MINUS term {$$ = $1 - $3;}
	| term {$$ = $1;}
term: term TIMES factor {$$ = $1 * $3;}
    | term DIVIDE factor {$$ = $1 / $3;}
    | factor {$$ = $1;}
factor: NUM {$$ = $1;}
	| LP exp RP {$$ = $2;}
	;
%%
int main(int argc, char *argv[]) {
	file_temp = fopen((const char*)"temp.asm", "w");
	if (NULL == file_temp) {
		return 0;
	}
	var_store_init();
	yyparse();
	fclose(file_temp);
	yyin = fopen((const char*)"temp.asm", "r");
	if (NULL == yyin) {
		return 0;
	}
	file_temp = stdout;
	return yyparse();
}

int yywrap(void) {
	return 1;
}

void yyerror(char* s) {
	printf("error: %s\n", s);
}

离线

楼主 #3 2018-05-04 21:12:06

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

Re: 写一个简单的编译器-flex&yacc

3,将上述文件用flex&yacc工具生成c源码文件,codeblock编译成pre_compiler.exe,一个编译器就做好了

离线

#4 2018-05-04 21:23:41

晕哥
管理员
所在地: 微信 whycan_cn
注册时间: 2017-09-06
已发帖子: 9,234
积分: 9197

Re: 写一个简单的编译器-flex&yacc

请教大神,怎么使用?





离线

楼主 #5 2018-05-04 21:23:51

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

Re: 写一个简单的编译器-flex&yacc

flex&yacc转换出来的c文件:
TIM20180504211430.png

将c文件编译成exe文件:
TIM20180504211512.png

exe文件调用方法:
TIM20180504212029.png

汇编例程源文件demo.asm:
TIM20180504211537.png

pre_compiler.exe将汇编文件demo.asm编译,输出中间文件temp.asm:
TIM20180504211559.png

输出最终文件out.asm:
TIM20180504211630.png

离线

楼主 #6 2018-05-04 21:28:53

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

Re: 写一个简单的编译器-flex&yacc

先上传flex&yacc源文件及转换工具
flex&yacc + pre_compiler

最近编辑记录 xxzouzhichao (2018-05-04 21:29:27)

离线

楼主 #7 2018-05-04 21:33:23

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

Re: 写一个简单的编译器-flex&yacc

再上传codeblock工程文件以及测试汇编代码:
codeblock工程文件及测试demo

离线

楼主 #8 2018-05-04 21:35:34

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

Re: 写一个简单的编译器-flex&yacc

晕哥 说:

请教大神,怎么使用?

详细使用教程已经发上来了

离线

#9 2018-05-04 21:53:14

超级萌新
会员
注册时间: 2018-05-04
已发帖子: 408
积分: 407

Re: 写一个简单的编译器-flex&yacc

请教一下,能不能用gcc, 把 lex.yy.c   pre_compiler.tab.c    pre_compiler.tab.h 生成 pre_compiler.exe ?

离线

楼主 #10 2018-05-04 22:02:16

bunny
会员
注册时间: 2020-05-23
已发帖子: 152
积分: 152

Re: 写一个简单的编译器-flex&yacc

超级萌新 说:

请教一下,能不能用gcc, 把 lex.yy.c   pre_compiler.tab.c    pre_compiler.tab.h 生成 pre_compiler.exe ?

肯定能啊,我就是用的codeblock做的,它就是GCC啊
附个工程截图:
TIM20180504220206.png

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn