利用 flex 和 bison 写一个计算器

指令

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;
}
全部评论

相关推荐

头像
11-21 11:39
四川大学 Java
是红鸢啊:忘了还没结束,还有字节的5k 违约金
点赞 评论 收藏
分享
像好涩一样好学:这公司我也拿过 基本明确周六加班 工资还凑活 另外下次镜头往上点儿
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务