[VC Bison] 超强的多功能计算器

caculator.y

%{

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "calc.h"

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

%}

%union {
double val;
symrec* tptr;
}

%token <val> NUM
%token <tptr> VAR FNCT
%type <val> exp

%right '='
%left '-' '+'
%left '*' '/'
%left NEG
%right '^'

%%

input : /* empty */
 | input line
 ;

line : '/n'
 | exp '/n' {printf("/t%.10g/n", $1);}
 | error '/n' {yyerrok;}
 ;

exp : NUM  {$$ = $1;}
 | VAR  {$$ = $1->value.var;}
 | VAR '=' exp {$$ = $3; $1->value.var = $3;}
 | FNCT '(' exp ')' {$$ = (*($1->value.fnctptr))($3);}
 | exp '+' exp {$$ = $1 + $3;}
 | exp '-' exp {$$ = $1 - $3;}
 | exp '*' exp {$$ = $1 * $3;}
 | exp '/' exp {$$ = $1 / $3;}
 | '-' exp %prec NEG {$$ = -$2;}
 | exp '^' exp {$$ = pow($1, $3);}
 | '(' exp ')' {$$ = $2;}
 ;

%%

#include <ctype.h>
#include <stdlib.h>

int yylex(void)
{
 int c;

 while ((c = getchar()) == ' ' || c == '/t');

 if (c == EOF) return 0;

 /* Number */
 if (c == '.' || isdigit(c)) {
  ungetc(c, stdin);
  scanf("%lf", &yylval);
  return NUM;
 }

 /* Identifier */
 if (isalpha(c)) {
  symrec* s;
  static char* symbuf = NULL;
  static int length = 0;
  int i;

  if (length == 0) {
   length = 40;
   symbuf = malloc(length + 1);
  }

  i = 0;
  do {
   /* Grow buffer if necessary */
   if (i == length) {
    length *= 2;
    symbuf = realloc(symbuf, length + 1);
   }

   /* Add character */
   symbuf[i++] = c;

   /* Get next character */
   c = getchar();
  } while (c != EOF && isalnum(c));

  ungetc(c, stdin);
  symbuf[i] = '/0';

  s = getsym(symbuf);
  if (s == NULL) s = putsym(symbuf, VAR);
  yylval.tptr = s;
  return s->type;
 }

 /* Any other character is its own token */
 return c;
}

int main(void)
{
 init_table();
 yyparse();
 return EXIT_SUCCESS;
}

struct {
 char* fname;
 double (*fnct)();
} arith_fncts[] = {
 "sin", sin,
 "cos", cos,
 "tan", tan,
 "atan", atan,
 "ln", log,
 "exp", exp,
 "sqrt", sqrt,
 0, 0
};

symrec* sym_table = NULL;

void init_table(void)
{
 int i;
 symrec* ptr;
 for (i = 0; arith_fncts[i].fname != NULL; i++) {
  ptr = putsym(arith_fncts[i].fname, FNCT);
  ptr->value.fnctptr = arith_fncts[i].fnct;
 }
}

symrec* putsym(char* sym_name, int sym_type)
{
 symrec* ptr;
 ptr = malloc(sizeof(symrec));
 ptr->name = malloc(strlen(sym_name) + 1);
 strcpy(ptr->name, sym_name);
 ptr->type = sym_type;
 ptr->value.var = 0;
 ptr->next = sym_table;
 sym_table = ptr;
 return ptr;
}

symrec* getsym(char* sym_name)
{
 symrec* ptr;
 for (ptr = sym_table; ptr != NULL; ptr = ptr->next)
  if (strcmp(ptr->name, sym_name) == 0) return ptr;
 return NULL;
}

 

calc.h

#ifndef SEEN_CALC_H
#define SEEN_CALC_H

typedef struct symrec symrec;
struct symrec {
 char* name;
 int type;
 union {
  double var;
  double (*fnctptr)();
 } value;
 symrec* next;
};

extern symrec* sym_table;
extern void init_table(void);
extern symrec* putsym(char* sym_name, int sym_type);
extern symrec* getsym(char* sym_name);

#endif

--------------------------

by caculator.y
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值