编译原理—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
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
lexbison是两个在编译原理中使用的工具,可以帮助开发者构建编译器或解析器。通过结合使用lexbison,我们可以制作一个简单的计算器。 首先,我们需要使用lex来定义我们的词法规则。词法规则会对输入的字符序列进行分类,并且生成对应的标记。比如,我们可以定义一些基本的词法规则,如加号、减号、数字等等。 接下来,我们使用bison来定义我们的语法规则。语法规则会描述输入字符序列如何组成合法的表达式。比如,我们可以定义加法表达式等等。 在我们的语法规则中,可以使用词法的标记进行组合,并且指定操作的优先级和结合性等等。然后,bison将会自动生成解析器代码。 在解析器代码中,我们可以编写相应的语义动作。这样,当解析器通过输入的字符序列来构建语法树时,我们可以在特定的语法规则或标记上执行一些操作,如计算出表达式的结果。 最后,我们可以使用编译器或解释器来编译或解释这些生成的代码。当我们输入一个表达式时,词法分析器会将其转化为字符序列,并且传递给语法分析器。语法分析器根据我们的语法规则来构建语法树,并且执行相应的动作。最终,我们可以得到表达式的计算结果。 通过使用lexbison,我们能够轻松地实现一个简单的计算器,让用户可以输入表达式,并且得到相应的计算结果。当然,对于更复杂的计算器,我们可以进一步扩展词法和语法规则,以支持更多的操作符和函数等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值