1. 程式人生 > >編譯原理:用Flex和 Bison實現一個功能更為強大的計算器

編譯原理:用Flex和 Bison實現一個功能更為強大的計算器



Flex Bison實現一個功能更為強大的計算器,包含以下運算:

a)加、減、乘、除運算

b)乘方、開方運算

c)位運算

& 、或 |、非 ~...

d)階乘運算 !對數運算log

1.進一步完善計算器功能,實現對以下語法結構的分析。還可以進一步擴充功能。

12+23*34+sin(45)/cos(56)-67

1.Calc.lex源程式如下:

%{
    /*
     *  一個簡單計算器的Lex詞法檔案
     */
    #include <stdlib.h>
    
    void yyerror(char*);
  /*  #include "calc.tab.h"  */
%}

%%

     /* a-z為變數 */   
[a-z]	{
            yylval = *yytext - 'a';
            return VARIABLE;
    	}

    /* 整數 */
[0-9]+	{
            yylval = atoi(yytext);
            return INTEGER;
    	}

    /* 運算子 */
[-+()=/*^&|~[!SCTL#\n]	{return *yytext;}

    /* 空白被忽略 */
[ \t]    ;

    /* 其他字元都是非法的 */
.    yyerror("無效的輸入字元");

%%

int yywrap(void)
{
  return 1;
}

2calc.y的源程式如下:

%token    INTEGER VARIABLE
%left    '+' '-'
%left    '*' '/'
%left    '^' '['
%left    '!' '&'
%left    '|' '~'
%left    'S' 'C''T'
%left    'L' '#'
%{
    #define YYSTYPE double
    #define w (0.017453292519943)
    #include <math.h>
    #define  __STDC__   0
    void yyerror(char*);
    int yylex(void);
    double sym[26];
%}
%%
program:
    program statement '\n'
    |
    ;
statement:
     expr    {printf("%f\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($1,$3);}
    |expr '[' expr    {$$ = pow($3,1.0/$1);} 
    |expr '!'         {int i,s=1;
                       for(i=1;i<=$1;i++)
                          s=s*i;
                       $$=s;   }
    |expr '&' expr    { $$ = (int)($1)&(int)($3);}
    |expr '|' expr    { $$ = (int)($1)|(int)($3);}
    |'~'expr          { $$ = ~(int)($2);}
    |'S''('expr')'    { $$=sin($3*(w));}
    |'C''('expr')'    { $$=cos($3*(w));}
    |'T''('expr')'    { $$ = tan($3*(w));}
    |'L''('expr')'    { $$ = log($3);}
    |expr '#' expr    { $$ = (int)($1)%(int)($3);}
    |'('expr')'       {$$ = $2;}
    ;
%%
void yyerror(char* s)
{
    fprintf(stderr, "%s\n", s);
}
#include "lex.yy.c"
int main(void)
{
    printf("A simple calculator.\n");
    printf("加(+),減(-),乘(*),除(/),乘方(^),開方([),階乘(!).\n");
    printf("與(&),或(|),非(~)\n");
    printf("S (sin)、C (cos)、T (tan):三角函式\n");
    printf("求對數(L),求模(#)\n");
    printf("START:\n");
    yyparse();
    return 0;
}

心得體會:

經過這次的實驗,我學到了很多新的知識和好的學習方法。第一次實驗做成功了給了我很大的信心,開始很順利,後來遇到文法相關的知識,我就又收到了挫敗。不斷的失敗不斷的重複實驗,不會的問同學內部是怎麼傳值的,看書看相關的文法知識,百度,總之就是不斷重複。終於,修改了很多次,我做出來了。這離不開同學的耐心講解和一直堅持的自己。有時候別人告訴我放棄,可我還是選擇了堅持。我一定要堅守原則堅持下去。或許,有些事開始認為不可能,只有在自己堅持做了,才會取得成果!下次繼續努力吧!