利用 flex 和 bison 写一个计算器

news/2024/5/19 17:00:16 标签: bison, flex, 编译原理

指令

flex -ocalc.c calc.l
bison -ocalc.tab.h calc.y
gcc -o aa calc.c calc.tab.h
aa.exe

calc.l

%{
    /*
     *  一个简单计算器的Lex词法文件
     */
    #include <stdlib.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;
        }

sin {
    return SIN;
    }
cos {
    return COS;
    }
sqrt {
    return SQRT;
}
pow {
    return POW;
}
log {
    return LOG;
}
ln {
    return LN;
}

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

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

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

%%

int yywrap(void)
{
  return 1;
}

calc.y

%token    INTEGER VARIABLE SIN COS SQRT POW LOG LN
%left    '+' '-'
%left    '*' '/'
%left    '^' '['
%left    '&' '|' '{'
%left    '!'
%left    '~'
%left    '%'
%{
    #define YYSTYPE double
    #define  __STDC__   0 
    #define wypi (0.017453292519943)
    #include "math.h"   
    #include <stdio.h>
    #include <stdlib.h>
    void yyerror(char*);
    int yylex(void);
    double sym[26];
%}

%%

program:
    program statement '\n'
    |
    ;
statement:
     expr           {
       printf("%g\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($3,1.0/$1);}
    |expr '&' expr      {$$ = (int)($1)&(int)($3);}
    |expr '|' expr      {$$ = (int)($1)|(int)($3);}
    |POW'('expr','expr')'      {$$ = pow($3,$5);}
    |SQRT'('expr')'      {$$ = sqrt($3);}
    |'{' expr      {$$ =!$2;}
    |SIN'('expr')'      {$$ = sin($3*wypi);}
    |COS'('expr')'      {$$ = cos($3*wypi);}
    |LOG'('expr')'      {$$ = log10($3);}
    |LN'('expr')'      {$$ = log($3);}
    |expr '!'      {
                $$ = 1;
                while($1>1)
                {
                    $$ *=$1;
                    $1--;
                }

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

%%

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


int main(void)
{
    yyparse();
    return 0;
}

http://www.niftyadmin.cn/n/1724645.html

相关文章

微机原理换行代码_微机原理--8种寻址方式

微机原理--8种寻址方式指令和指令系统指令&#xff1a;控制计算机完成某种操作的命令指令系统&#xff1a;处理器能识别的所有指令的集合指令的兼容性&#xff1a;同一系列机的指令是兼容的指令的包含的内容&#xff1a;运算数据的来源运算结果的去向执行的操作指令格式&#x…

python 游戏开发框架_Python开发 基于python实现坦克大战游戏

这篇文章主要为大家详细介绍了基于python实现坦克大战游戏&#xff0c;文中示例代码介绍的非常详细&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可以参考一下本文实例为大家分享了python实现坦克大战游戏的具体代码&#xff0c;供大家参考&#xff0c;具体内容…

怎么删除fiddler注册表_手撕流氓软件 l 如何手动删除卸载不掉的软件?

点击蓝字关注我们~前两天有人说有软件卸载不掉&#xff0c;用360强力卸载也卸载不掉&#xff0c;清理也清理不掉&#xff0c;然后我一看&#xff0c;是个快捷方式&#xff0c;直接删除就好了&#xff0c;这触使我想到了这个话题。今天我就教大家如何手撕鬼子&#xff0c;不&…

becky's blue book planning

2019.1.10 uva 11292 勇者斗恶龙 【easy】 贪心 uva 11729 突击战【easy】 贪心 {此题可以用来作为贪心例题。说明贪心策略的正确性} uva 11300 分金币【easy】 单变量的极值问题 证明过程在此 LA 3708 墓地雕塑【easy】 贪心 2019.1.13 uva 10881 蚂蚁 【mid】 贪心&#xff0…

new thread后会阻塞主程序吗_程序员:有点可惜,朋友去面试竟然栽在了Thread类的源码上...

前言最近一个朋友去XXX公司面试的情况&#xff0c;面试官的一个问题把他打懵了&#xff01;竟然问他&#xff1a;你经常使用Thread创建线程&#xff0c;那你看过Thread类的源码吗&#xff1f;我这个朋友自然是没看过Thread类的源码&#xff0c;然后&#xff0c;就没有然后了&am…

编写python程序、计算账户余额_《易学Python》——第1章 为何学习Python 1.1 学习编程...

本节书摘来自异步社区《易学Python》一书中的第1章&#xff0c;第1.1节&#xff0c;作者[澳]Anthony Briggs&#xff0c;王威&#xff0c;袁国忠 译&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。第1章 为何学习Python本章介绍如下内容&#xff1a;计算机和…

python3解压zip乱码_python解压zip包中文乱码解决方法

乱码得原因&#xff1a;由于ZipFile模块导出遇到中文解码不对&#xff0c;windows上会出现&#xff0c;Linux是否会出现不知道没测试过。解决方式&#xff1a;1. 搞个文件名引射表(不太方便&#xff0c;少量文件夹套用时候还可以)2. 修改源码解码格式(不太方便&#xff0c;自己…

三菱触摸屏通讯错误_一台威纶通触摸屏与多台三菱PLC通讯案例

来源&#xff1a; 八方汇PLC实战编程培训在实际项目应用中&#xff0c;我们经常需要使用一台触摸屏对多台设备进行监控操作。这就是我们常说的一屏多机。它的原理其实非常简单&#xff0c;现在我们就通过一个案例&#xff0c;来演示如何实现威纶通的一屏多机。我们以一台威纶通…