프로그래밍[Univ]/프로그래밍 언어론

[Lex&Yacc] C언어를 기반으로한 Lex_Yacc 공학계산기...

Cloud Travel 2011. 12. 15. 18:20
calc_lex.l

 /* DEFINITION SECTION */
 
%{
#include "calc_yacc.h"
#include <math.h>


extern double yylval;
%}

WHITE_SPACE [ \t]+
END_MARKER "$"
DOUBLE_VAL ([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) 
%%
 /* RULE SECTION */
 
{DOUBLE_VAL} { yylval = atof(yytext); return NUMBER; }

"+" { return PLUS; }
"-" { return MINUS; } 
"*" { return MULT; }
"/" { return DIV; }
"abs" { return ABS; }
"sqrt" { return SQRT; }
"log" { return LOG; }
"!" { return FAC; }
"^" { return POW; }
"sin" { return SIN; }
"cos" { return COS; }
"tan" { return TAN; }
"mod" { return MOD; }
"div" { return NAMO; }   
"(" { return OPEN; }
")" { return CLOSE; }
"round" { return ROUND; }
"ceil" { return CEIL; }
"fix" { return FIX; } 
"floor" { return FLOOR; }


{WHITE_SPACE} { ; }
{END_MARKER} { return 0;}
\n { return '\n';}
. { return(yytext[0]);}

%% 

------------------------------------------------------------------------------------------
calc_yacc.y
 /* Definition Section */
 
%{
#include <stdio.h>  
#include <math.h>

#define YYSTYPE double            

double absfunction(double i){
if ( i < 0 ) return -i;
else return i;
}

int round(double i){
double a = i;
double b = (int) i;        
if ( i >= 0 ){
if ( a - b >= 0.5 ){
return (int)i + 1;
}else{
return (int) i;
}
}else{
if ( a - b < -0.5 ){
return (int)i -1;
}else{
return (int)i;
}
}
}

int isinteger(double i){
double a = i;
double b = (int) i;
if ( a - b == 0 ) return 1;
else return 0;
}
 
int fac(double num){
int i;
int result = 1;
for ( i = 1 ; i <= num ; i++ ){
result *= i;
}
return result;
}
%}

%token NUMBER
%left PLUS, MINUS
%left MULT, DIV, MOD, NAMO
%left ABS, SQRT, LOG, SIN, COS, TAN
%right POW   
%left FAC
%left ROUND, CEIL, FIX, FLOOR
%left OPEN, CLOSE

%%
 /* Rule Section */
statement :statement expr '\n' { printf(" = %g\n", $2); }
|statement '\n' { printf("Insert Formula.\n"); }
|error '\n' { yyerror("Error! Review Formula!\n"); yyerrok(); }
|{}
;

expr : expr PLUS term { $$ = $1 + $3; }
| expr MINUS term { $$ = $1 - $3; }
     | term
;
term : term MULT oper { $$ = $1 * $3; }
| term DIV oper { 
if ( $3 == 0 ) yyerror("Divide by Zero(0)\n");
else $$ = $1 / $3; 
}
| term MOD oper { 
if ( $3 == 0 ) yyerror("Divide by Zero(0)\n");
else $$ = (int)$1 % (int)$3;
}     
| term NAMO oper {
if ( $3 == 0 ) yyerror("Divide by Zero(0)\n");
else $$ = (int)($1 / $3);
}
| oper
;
oper : ABS ants { $$ = absfunction($3); }
| SQRT ants { $$ = sqrt($3); }
| LOG ants{
if ( $3 <= 0 ) yyerror("Log(n), n is upper than Zero(0)\n");
else $$ = log($3);
}
| SIN ants { $$ = sin($3); }
| COS ants { $$ = cos($3); }
| TAN ants { $$ = tan($3); }
| ants
;
ants : ruds POW ants { $$ = pow($1,$3); }
| ruds FAC {
if ( $1 <= 0 ) yyerror("Factorial(n), n is upper than Zero(0)\n");  
else if ( isinteger($1) == 0 ) yyerror("Factorial(n), n must be inserted integer\n");  
else $$ = fac($1);
}
| ruds
;
ruds : ROUND upup { $$ = round($3); }
| CEIL upup { 
if ( $3 <= 0 ) yyerror("Ceil(n), n is upper than zero(0)\n");
else $$ = ceil($3);
}
| FIX upup { $$ = (int)$3; }
| FLOOR upup { 
if ( $3 >= 0 ) yyerror("Floor(n), n is downer than zero(0)\n");
else $$ = floor($3);
}   
| upup
;
upup : OPEN expr CLOSE { $$ = $2; }
| MINUS expr { $$ = -$2; }
     | NUMBER { $$ = $1; }
;
%% 
-------------------------------------------------------------------