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;
}
/* 运算符 */
[-+()=#^!&|~/*%\n] {return *yytext;}
/* 空白被忽略 */
[ \t] ;
/* 其他字符都是非法的 */
. yyerror("无效的输入字符");
%%
int yywrap(void)
{
return 1;
}
calc.yacc
%{
#define YYSTYPE double
#define __STDC__ 0
#include <math.h>
#include<ctype.h>
#include<stdio.h>
void yyerror(char*);
int yylex(void);
double sym[26];
%}
%token INTEGER VARIABLE
%token num
%left '+' '-'
%left '*' '/' '%'
%left '^' '!' '#'
%left '&' '|'
%left '~'
%nonassoc UMINUS
%%
program:
program statement '\n'
|
;
statement:
VARIABLE '=' expr {sym[(int)$1] = $3;}
| expr {printf("%f\n", $1);}
;
expr:
INTEGER
|VARIABLE {$$ = sym[(int)$1];}
|expr '+' expr {$$ = $1 + $3;}
|expr '-' expr {$$ = $1 - $3;}
|expr '*' expr {$$ = $1 * $3;}
|expr '/' expr {$$ = $1 / $3;}
|expr '%' expr {$$ = (int)($1)%(int)($3);}
|expr '^' expr {$$ = pow($1,$3);}
|expr '!' {
$$=1;
while($1>1)
{
$$*=$1;
$1--;
}
}
|'#' expr {$$ = sqrt($2);}
|expr '&' expr {$$ = (int)($1)&(int)($3);}
|expr '|' expr {$$ = (int)($1)|(int)($3);}
|'~' expr {$$ = !$2;}
|'('expr')' {$$ = $2;}
|'-'expr %prec UMINUS {$$=-$2;}
|num
;
%%
void yyerror(char* s)
{
fprintf(stderr, "%s\n", s);
}
#include "lex.yy.c"
#include "math.h"
int main(void)
{
printf("A simple calculator.\n");
yyparse();
return 0;
}
运行截图: