编译原理--计算器Flex+Bison实现

一、原创性声明

本程序参考了老师给出的计算器的简单实例其余扩展程序由本人写成,属于原创。

 

二、实验要求

1. 实现以下步骤, 掌握Flex和Bison的工作过程

a) DOS 命令提示符下依次执行以下两行命令

flex  calc.lex

bison  -ocalc.c  calc.y

b) 编译运行 calc.c

 

2. 测试目录SRC_BISON中的范例程序,了解其功能及实现。

 

3. 参考范例程序, 用Flex和Bison实现一个功能更为强大的计算器,包含以下运算:

a) 加、减、乘、除运算

b) 乘方、开方运算

c) 位运算  – 与、或、非...

d) 三角函数运算 – sin、cos...

e) 求阶乘

f) 求模

g) 求log以e为底的对数

h) 求log以10为底的对数

 

 

三、完成情况

l 功能1 : 基本内容

i) 加、减、乘、除运算

j) 乘方、开方运算

k) 位运算  – 与、或、非...

l) 三角函数运算 – sin、cos...

m) 求阶乘

n) 求模

o) 求log以e为底的对数

p) 求log以10为底的对数

² 

² 完成情况: 完成

² Bug:

² 备注:由于许多符号不好标识有的采用字母、有的采用不常用的字符、望见谅。

 

四、实现方案

通过flex和bison的配合使用实现简单的计算器。

五、创新和亮点

可以计算加减乘除以及扩展功能:位运算、三角函数、阶乘、求模、求对数

六、运行结果

 

 

Calc.tab.h:
#ifndef YYSTYPE
#define YYSTYPE int
#endif
#define	INTEGER	258
#define	VARIABLE	259


extern YYSTYPE yylval;

Calc.lex
%{
    /*
     *  一个简单计算器的Lex词法文件
     */
    #include <stdlib.h>
    
    void yyerror(char*);
  /*  #include "calc.tab.h"  */
%}

%%

     /* a-z为变量 */   
[a-z]	{
            yylval = *yytext - 'a';
            return VARIABLE;
    	}

    /* 整数 */
[0-9]+	{
            yylval = atoi(yytext);
            return INTEGER;
    	}

    /* 运算符 */
[-+()=/*^[&|{SCTL~X%\n]	{return *yytext;}

    /* 空白被忽略 */
[ \t]    ;

    /* 其他字符都是非法的 */
.    yyerror("无效的输入字符");

%%

int yywrap(void)
{
  return 1;
}

Calc.y
%token    INTEGER VARIABLE
%left    '+' '-'
%left    '*' '/'
%left    '^' '['
%left    '&' '|' '{'
%left    'S' 'C' 'T'
%left    'L'
%left    '~'
%left    'X'
%left    '%'
%{
    #define YYSTYPE double
    #define  __STDC__   0 
    #define wypi (0.017453292519943)
    #include "calc.tab.h" 
    #include "math.h"	
    void yyerror(char*);
    int yylex(void);
    double sym[26];
%}

%%

program:
    program statement '\n'
    |
    ;
statement:
     expr    		{printf("%f\n", $1);}
     |VARIABLE '=' expr	{sym[(int)$1] = $3;}
     ;
expr:
    INTEGER
    |VARIABLE		{$$ = sym[(int)$1];}
    |expr '+' expr    	{$$ = $1 + $3;}
    |expr '-' expr    	{$$ = $1 - $3;}
    |expr '*' expr    	{$$ = $1 * $3;}
    |expr '/' expr    	{$$ = $1 / $3;}
    |expr '^' expr      {$$ = pow($1,$3);}
    |expr '[' expr      {$$ = pow($3,1.0/$1);}
    |expr '&' expr      {$$ = (int)($1)&(int)($3);}
    |expr '|' expr      {$$ = (int)($1)|(int)($3);}
    |'{' expr      {$$ =!$2;}
    |'S' expr      {$$ = sin($2*wypi);}
    |'C' expr      {$$ = cos($2*wypi);}
    |'T' expr      {$$ = tan($2*wypi);}
    |'L' expr      {$$ = log10($2);}
    |'~' expr      {$$ = log($2);}
    |expr 'X'      {
				$$ = 1;
				while($1>1)
				{
				    $$ *=$1;
				    $1--;
				}

		   }
    |expr '%' expr {
			$$=(int)($1)%(int)($3);
		   }
    |'('expr')'    	{$$ = $2;}
    ;

%%

void yyerror(char* s)
{
    fprintf(stderr, "%s\n", s);
}

#include "lex.yy.c"

int main(void)
{
    printf("A simple calculator.\n");
    printf("+加、-减、*乘、/除\n");
    printf(" ^ 乘方(a^b a的b次方)、[ 开方( a[b 即b开a次方)\n");
    printf("&与、|或、{非\n");
    printf("S (sin)、C (cos)、T (tan):三角函数\n");
    printf("L以10为底的对数、~以e为底的对数\n");
    printf("X求阶乘 \n");
    printf("求模%% \n");
    yyparse();
    return 0;
}


你可能感兴趣的:(Flex)