n_exp { $$ = $1; } ; factor : INT_VALUE { $$ = newExpNode(IntValueK); $$->value.int_val = $1; $$->type = Int; $$->lineno = lineno; } | REAL_VALUE { $$ = newExpNode(RealValueK); $$->value.real_val = $1; $$->type = Real; $$->lineno = lineno; } | LPAREN exp RPAREN { $$ = $2; } | ID { $$ = newExpNode(IdK); $$->attr.name = $1; /* child[0]为NULL代表该变量不是数组,用作解释时 */ $$->child[0] = NULL; $$->lineno = lineno; } | ID LBRACKET exp RBRACKET { $$ = newExpNode(IdK); $$->attr.name = $1; $$->child[0] = $3; $$->lineno = lineno; } | error { $$ = NULL; } ; bin_exp : /* 关系运算符 */ exp REL_OP exp { $$ = newExpNode(OpK); $$->child[0] = $1; $$->child[1] = $3; $$->attr.op = $2; $$->lineno = lineno; } /* 算数运算符 */ | exp PLUS exp { $$ = newExpNode(OpK); $$->child[0] = $1; $$->child[1] = $3; $$->attr.op = PLUS; $$->lineno = lineno; } | exp SUB exp { $$ = newExpNode(OpK); $$->child[0] = $1; $$->child[1] = $3; $$->attr.op = SUB; $$->lineno = lineno; } | exp MUL exp { $$ = newExpNode(OpK); $$->child[0] = $1; $$->child[1] = $3; $$->attr.op = MUL; $$->lineno = lineno; } | exp DIV exp { $$ = newExpNode(OpK); $$->child[0] = $1; $$->child[1] = $3; $$->attr.op = DIV; $$->lineno = lineno; } | SUB exp %prec UMINUS { $$ = newExpNode(OpK); $$->child[0] = $2; $$->child[1] = NULL; $$->attr.op = UMINUS; $$->lineno = lineno; } ; %% int yyerror(char * message) { fprintf(listing,"Syntax error at line %d: %s\n",lineno,message); fprintf(listing,"Current token: %s",tokenString); printToken(yychar); Error = TRUE; return 0; } /* 与主函数交互的语法分析函数 */ TreeNode * parse(void) { iniLexer(); yyparse(); return savedTree; }
编译也非常简单,
#The makefile for interpreter based on Flex and Bison
CC = gcc
FLAG = -w
interpreter: main.o util.o cmm.tab.o cmm.lex.o symtab.o analyze.o
$(CC) $(FLAG) -o ../bin\&test/interpreter main.o util.o cmm.tab.o cmm.lex.o symtab.o analyze.o
main.o: main.c parse.h analyze.h
$(CC) $(FLAG) -c main.c
cmm.tab.o:cmm.tab.c parse.h
$(CC) $(FLAG) -c cmm.tab.c
cmm.tab.c:cmm.y
bison -d cmm.y
cmm.lex.o:cmm.lex.c cmm.tab.h
$(CC) $(FLAG) -c cmm.lex.c
cmm.lex.c:cmm.l
flex -o cmm.lex.c cmm.l
symtab.o:symtab.c symtab.h globals.h
$(CC) $(FLAG) -c symtab.c
analyze.o:analyze.c globals.h symtab.h analyze.h
$(CC) $(FLAG) -c analyze.c
util.o:util.c
$(CC) $(FLAG) -c util.c
clean:
-rm *.o
最后测试的时候,就是直接利用./interpreter [file_name]就可以了。
有兴趣的同学可以把这个项目下载下来,多看看,了解一下如果利用flex&bison快速实现一个脚本语言。