制作一个简单的计算器

摘要: 本文通过制作一个简单的命令行计算器来学习flex/bison编译工具的使用。

1. 目标

  • 支持命令行输入表达式进行计算
  • 支持整数加减乘除四则运算
  • 支持绝对值运算
  • 支持括号运算

2. 使用工具

  • flex
  • bison
  • gcc

3. 源码

3.1 calc.l

%{
#include "calc.tab.h"
extern void yyerror(char* msg, ...);
%}

%%

" + "        { printf("ADD\n");  return ADD; }
" - "        { printf("SUB\n");  return SUB; }
" * "        { printf("MUL\n");  return MUL; }
" / "        { printf("DIV\n");  return DIV; }

"|"          { printf("ABS\n");  return ABS; }
[-+][0-9]+   { yylval = atoi(yytext);  printf("NUMBER %d\n", yylval); return NUMBER; }
[0-9]+       { yylval = atoi(yytext);  printf("NUMBER %d\n", yylval); return NUMBER; }

\n           { printf("EOL\n");  return EOL; }
[ \t]        { printf("SPA\n");              }
"("          { printf("LFT\n"); return LB;   }
")"          { printf("RGT\n"); return RB;   }
.            { yyerror("invalid character: %c!", *yytext); }

%%

3.2 calc.y

%{
#include <stdio.h>
#include "calc.tab.h"

extern int yylex(void);
extern void yyerror(char* msg);
%}

%token NUMBER
%token ADD SUB MUL DIV ABS LB RB
%token EOL

%%

prog:   exp EOL { printf("==> RESULT = %d\n",$1); }
      ;

exp:    exp ADD term { $$ = $1 + $3; printf("==> %d + %d = %d \n", $1, $3, $$); }
      | exp SUB term { $$ = $1 - $3; printf("==> %d - %d = %d \n", $1, $3, $$); }
      | term;

term:   term MUL factor { $$ = $1 * $3; printf("==> %d * %d = %d \n", $1, $3, $$); }
      | term DIV factor { $$ = $1 / $3; printf("==> %d / %d = %d \n", $1, $3, $$); }
      | factor

factor: NUMBER          { $$ = $1; }
      | ABS exp ABS     { $$ = $2 >= 0 ? $2: -$2; }
      | LB exp RB       { $$ = $2; }
      ;

%%

int main(int argc,char **argv)
{
    printf("Please enter a mathematics expression: ");
    yyparse();
	return 0;
}


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

3.3 makefile

cat makefile
calc : calc.tab.c calc.yy.c
	gcc -o calc calc.tab.c calc.yy.c -lfl

calc.tab.c : calc.y
	bison -d calc.y

calc.yy.c : calc.l
	flex -o calc.yy.c calc.l

4. 测试

命令行输入:./calc

测试用例1:

Please enter a mathematics expression: 1 + 2 * 3 + 4 * | 5 - 78| * 3
NUMBER 1
ADD
NUMBER 2
MUL
NUMBER 3
==> 2 * 3 = 6
ADD
==> 1 + 6 = 7
NUMBER 4
MUL
ABS
SPA
NUMBER 5
SUB
NUMBER 78
ABS
==> 5 - 78 = -73
==> 4 * 73 = 292
MUL
NUMBER 3
==> 292 * 3 = 876
EOL
==> 7 + 876 = 883
==> RESULT = 883

测试用例2:

1 - 2 * 3 / (1 + 2) + (1 - 2 + (|3 - 4| * 3))
NUMBER 1
SUB
NUMBER 2
MUL
NUMBER 3
==> 2 * 3 = 6
DIV
LFT
NUMBER 1
ADD
NUMBER 2
RGT
==> 1 + 2 = 3
==> 6 / 3 = 2
ADD
==> 1 - 2 = -1
LFT
NUMBER 1
SUB
NUMBER 2
ADD
==> 1 - 2 = -1
LFT
ABS
NUMBER 3
SUB
NUMBER 4
ABS
==> 3 - 4 = -1
MUL
NUMBER 3
==> 1 * 3 = 3
RGT
RGT
==> -1 + 3 = 2
EOL
==> -1 + 2 = 1
==> RESULT = 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农心语

您的鼓励是我写作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值