编译原理—Lex和Bison实现计算器

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

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

     flex  calc.lex

    bison  -ocalc.c  calc.y

b) 编译运行 calc.c

 文件中内容如下:

编译运行完后:

题目要求:

用 Flex 和 Bison 实现一个功能更为强大的计算器,包含以下运算:

a) 加、减、乘、除运算

b) 乘方、开方运算

c) 位运算     – 与 & 、或 |、非 ~...

d) 阶乘运算 !  

进一步完善计算器功能,实现对以下语法结构的分析。还可以进一步扩充功能。

   12+23*34+sin(45)/cos(56)-67

calc.lex文件

<pre name="code" class="plain">%{
    /*
     *  一个简单计算器的Lex词法文件
     */
    #include <stdlib.h>
    #include <math.h> 
    void yyerror(char*);
  /*  #include "calc.tab.h"  */
%}

%%

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

    /* 整数或浮点数 */
[0-9]+\.?|[0-9]*\.[0-9]+ {
                            yylval = atof(yytext);
                            return INTEGER;
    	                  } 

    /* 运算符 */
[-+()=/*^@&|~!\n]	{return *yytext;}
sin {
     return SIN;
    }
cos {
     return COS;
    }

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

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

%%

int yywrap(void)
{
  return 1;
}
 

calc.y文件

%token    INTEGER VARIABLE SIN COS
%left    '+' '-'
%left    '*' '/'
%left    '&'
%left    '|'
%right    SIN COS
%left    '^' 
%right   '@' '~'
%left    '!'
%{
    #include <math.h>
    #define pi 3.1415926
    #define  __STDC__   0 
    #define YYSTYPE double
    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         {$$ = sqrt($2);}
    |expr '&' expr    {$$ = (int)$1 & (int)$3;}
    |expr '|' expr    {$$ = (int)$1 | (int)$3;}
    |'~' expr         {$$ = ~ (int)$2;}
    |expr '!'         {int i=0;int s=1;for(i=1;i<=$1;i++){s=s*i;} $$ = s;}
    |SIN '('expr ')'  {$$ = sin($3*pi/180.0);}
    |COS '('expr ')'  {$$ = cos($3*pi/180.0);}
    |'('expr')'       {$$ = $2;}
    ;
%%
void yyerror(char* s){fprintf(stderr, "%s\n", s);}
#include "lex.yy.c"
int main(void)
{
    printf("A simple calculator.\n");
    yyparse();
    return 0;
}

运行结果:


  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值