用lex和yacc实现的计算器

代码

// calc.lex

 

%{

#include <stdio.h>
#define YYSTYPE    double
#include "calc_y.h"

#define PRINT    printf("%s", yytext)

%}

num        [0-9]
real    {num}+|{num}+"."{num}+
add        "+"
sub        "-"
mul        "*"
div        "/"
eq        "="
lb        "("
rb        ")"
sin        "sin"
cos        "cos"
ln        "ln"
log10    "log10"
tanh    "tanh"
sqrt    "sqrt"
exp        "exp"
abs        "abs"
lr        [/r/n]
space    [ /t]
quit    [q]

%%

{real}    { PRINT; yylval = strtod(yytext, NULL); return REAL; }
{add}    { PRINT; return ADD; }
{sub}    { PRINT; return SUB; }
{mul}    { PRINT; return MUL; }
{div}    { PRINT; return DIV; }
{eq}    { PRINT; return EQ; }
{lb}    { PRINT; return LB; }
{rb}    { PRINT; return RB; }
{sin}    { PRINT; return SIN; }
{cos}    { PRINT; return COS; }
{ln}    { PRINT; return LN; }
{log10}    { PRINT; return LOG10; }
{tanh}    { PRINT; return TANH; }
{sqrt}    { PRINT; return SQRT; }
{exp}    { PRINT; return EXP; }
{abs}    { PRINT; return ABS; }
{lr}    { return LR; }
{quit}    { exit(0); }
{space}    {}
.        {}

%%

int yywrap()
{
    return 1;
}

 

// calc.y

 

%{

#include <stdio.h>
#include <math.h>

#define YYSTYPE    double

extern int yylineno;

%}

%token     REAL EQ LR
%right    SIN COS LN LOG10 TANH SQRT EXP ABS
%left    ADD SUB
%left    MUL DIV
%left    RB
%right    LB
%right    UARY

%%

input:
    |    input line
;

line:    LR
    |    exp LR                { printf("=%f/n", $1); }   
;
   
exp:    REAL                { $$ = $1; }   
    |    exp    ADD exp            { $$ = $1 + $3; }
    |    exp    SUB exp            { $$ = $1 - $3; }
    |    exp    MUL exp            { $$ = $1 * $3; }
    |    exp    DIV exp            { $$ = $1 / $3; }
    |    ADD    exp    %prec UARY    { $$ = $2; }
    |    SUB    exp    %prec UARY    { $$ = -$2; }
    |    LB    exp    RB            { $$ = $2; }
    |    SIN LB exp RB        { $$ = sin($3); }
    |    COS LB exp RB        { $$ = cos($3); }
    |    LN LB exp RB        { $$ = log($3); }
    |    LOG10 LB exp RB        { $$ = log10($3); }
    |    TANH LB exp RB        { $$ = tanh($3); }
    |    SQRT LB exp RB        { $$ = sqrt($3); }
    |    EXP LB exp RB        { $$ = exp($3); }
    |    ABS LB exp RB        { $$ = fabs($3); }
;

%%

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

int yyerror(char *msg)
{
    printf("error: %s in line %d/n", msg, yylineno);
    return 0;
}

// makefile

 

all:calc_y.c calc_l.c
    gcc -g -o calc calc_y.c calc_l.c -lm

calc_l.c:calc.lex calc.y
    flex -o calc_l.c calc.lex

calc_y.c:calc.y
    bison -d -o calc_y.c calc.y
   

clean:
    @rm -f calc *.c *.h
   

// exam.txt

 

10.6/2
3.3*3
10+5
8-3
4*2
1+3*2-5
-1+5
+1+5
5*(3-1)+6
sin(3.1415926/2)
cos(0)
abs(-10.5)
sqrt(16)
ln(5)
log10(10)
exp(5)

 

// 使用方法 1

$ ./calc < exam.txt

 

// 是用方法2

$ ./calc

1+3

1+3=4

q

$

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值