应用 yacc 和lex 实现 语法分析与词法分析 之复杂四则运算

为什么要实现四则运算,看是很傻比,但是只有你明白其中的用处,他才是有用的。呵呵~~~~~

简单四则运算实现:

#include <iostream>
using namespace std;
int fun(const char * pBuffer,const int &iLen)
{
int iEnd = 0;
int num[20];
int iNum = 0 ;
char str[20];
int  iStr = 0 ;
    for(int i = 0;i < iLen ; i++  )
    {
    if(pBuffer[i] >= '0' && pBuffer[i] <= '9')
    {
    num[iNum++] = pBuffer[i] - '0';
    }
    else if(pBuffer[i] == '*')
    {
    num[iNum - 1] = num[iNum - 1] * (pBuffer[i+1] - '0');
    i++;
    }
    else if(pBuffer[i] == '/')
    {
    num[iNum - 1] = num[iNum - 1] / (pBuffer[i+1] - '0');
    i++;
    }
    else
    {
    str[iStr++] = pBuffer[i];
    }
    }
    iEnd = num[0];
    for(int j = 0; j < iStr ; j ++ )
    {
      if(str[j] == '+')
      {
     iEnd = iEnd + num[ j + 1] ;
      }
      if(str[j] == '-')
      {
     iEnd = iEnd - num[ j + 1] ;
      }
    }
return iEnd;
}
int main() {
cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
char a[]="3*3+7+4/3";
int k=fun(a,9);
cout<<k<<endl;
return 0;
}


弊端:

1、表达式只含 +, -, *, / 四则运算符,不含括号 

2、表达式数值只包含个位整数(0-9),且不会出现0作为除数的情况

3、要考虑加减乘除按通常四则运算规定的计算优先级 
4、除法用整数除法,即仅保留除法运算结果的整数部分。比如8/3=2。输入表达式保证无0作为除数情况发生 
5、输入字符串一定是符合题意合法的表达式,其中只包括数字字符和四则运算符字符,除此之外不含其它任何字符,不会出现计算溢出情况 


yacc  lex  是什么,自己去百度吧!你会找到答案的。

math.y文件内容

%{


int yylex(void);
#include"stdio.h"
char *mail;
char *cError;
typedef YY_BUFFER_STATE;


%}


%union
{
    long long   integer;   
    double  ldouble;
}


%token NL LPAR RPAR END
%token <integer>INTEGER 
%token <ldouble>DOUBLE


%type <ldouble> exprreal
%type <integer> exprint


%left OP_ADD OP_SUB
%left OP_MUL OP_DIV
%left OP_MOD
%left OP_NEG
%left CAST_INT CAST_REAL


%%


Program: exprint  {sprintf(mail,"%d",$1);}
        |exprreal {sprintf(mail,"%f",$1);}
;


exprint:CAST_INT LPAR exprint RPAR {$$ = (long long)$3;}
       |     exprint OP_ADD exprint {$$ = $1 + $3;}
| exprint OP_SUB exprint {$$ = $1 - $3;}
| exprint OP_MUL exprint {$$ = $1 * $3;}
| exprint OP_DIV exprint {if($3)$$ = $1 / $3;else {$$=0;sprintf(cError,"%s","/");}}
| exprint OP_MOD exprint {if($3)$$ = $1 % $3;else {$$=0;sprintf(cError,"%s","%");}}
| LPAR exprint RPAR {$$ = $2;}
| INTEGER {$$ = $1;}
;


exprreal:CAST_REAL LPAR exprreal RPAR {$$ = (long double)$3;}
|     exprreal OP_ADD exprreal {$$ = $1 + $3;}
| exprreal OP_SUB exprreal {$$ = $1 - $3;}
| exprreal OP_MUL exprreal {$$ = $1 * $3;}
| exprreal OP_DIV exprreal {if($3)$$ = $1 / $3;else{$$=0;sprintf(cError,"%s","/");}}
|     LPAR exprreal RPAR {$$ = $2;}
|     DOUBLE  {$$ = $1;}
|     exprint OP_ADD   exprreal  { $$ = (double)$1 + $3;}
|     exprint OP_SUB   exprreal  { $$ = (double)$1 - $3;}
|     exprint OP_MUL   exprreal  { $$ = (double)$1 * $3;}
|     exprint OP_DIV   exprreal  {if($3) $$ = (double)$1 / $3;else{$$=0;sprintf(cError,"%s","/");}}    
|     exprreal OP_ADD  exprint   {$$ = $1 + (double)$3;}
|     exprreal OP_SUB  exprint   {$$ = $1 - (double)$3;}
|     exprreal OP_MUL  exprint   {$$ = $1 * (double)$3;}
|     exprreal OP_DIV  exprint   {if($3)$$ = $1 / (double)$3;else{$$=0;sprintf(cError,"%s","/");}}   
|     exprint  OP_ADD  exprint   {$$ = (double)$1 + (double)$3;}
|     exprint OP_SUB   exprint   {$$ = (double)$1 - (double)$3;}
|     exprint OP_MUL   exprint   {$$ = (double)$1 * (double)$3;}
|     exprint OP_DIV exprint{if($3)$$ = (double)$1 / (double)$3;else{$$=0;sprintf(cError,"%s","/");}} 
;


%%
int yyerror(char *s)
{ 
  printf ("%s\n",s);
  return 0;
}
int ZGMCommonFourOperationFunction(const char *str, int len, char *m,char *cErr)
{
 //printf("ZGM Common Four Operation Function !!!\n");
 mail = m;
 cError = cErr;
 YY_BUFFER_STATE state = yy_scan_bytes(str, len); 
 yy_switch_to_buffer(state);
 yyparse();                      
 yy_delete_buffer(state);     
 return 0;
}


math.l文件内容

%{
#include <ctype.h>
#include"y.tab.h"
#include "stdio.h"
#include "string.h"
%}


%%


"+" {return OP_ADD;}
"-" {return OP_SUB;}
"*" {return OP_MUL;}
"/" {return OP_DIV;}
"%" {return OP_MOD;}
"(" {return LPAR;}
")" {return RPAR;}
(int|INT) {return CAST_INT;}
(real|REAL) {return CAST_REAL;}


[0-9]+       {yylval.integer = atoi(yytext); return INTEGER;}


[0-9]*\.[0-9]+    {sscanf(yytext,"%lf",&yylval.ldouble);return DOUBLE;}


"0x"[0-9a-f]+ {sscanf (yytext,"%x",&yylval.integer); return (INTEGER); }

[ \t] ;
\r {return END;}
\n { return END;}

%%

int yywrap()
{
return 1;
}


应用yacc 和 lex 命令编译他们 生成相应的 c 和 h文件。然后将c和h文件 应用 gcc  编译命令生成 对应用 c库,在应用生成的c库中的函数ZGMCommonFourOperationFunction 就可以实现各种复杂的四则运算了。  其中的应用价值,还是很广阔的,你会懂的的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值