浮動小数点演算を実行できるフレックス/バイソン計算機を実装しようとしています。私のフレックスコードは次のようになります
%{
#include "calc.tab.h"
#include <stdlib.h>
void yyerror(char *s);
%}
digit [0-9]
integer {digit}+
real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
exp ({integer}|{real})[eE]-?{integer}
%%
({integer}|{real}|{exp}) { yylval = atof(yytext); return NUMBER; }
[-+*/\n] { return *yytext; }
[ \t\v\f\r] { }
. { yyerror("Unknown Character"); }
%%
int yywrap(void)
{
return 1;
}
そして、私のバイソンコードは次のようになります
%{
#include <stdio.h>
typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED
void yyerror(char *s);
extern char *yytext;
extern int yylineno;
%}
%token NUMBER
%left '+' '-'
%left '*' '/'
%%
program: program expr '\n' { printf("%g\n", $2); }
| program '\n'
|
;
expr: expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr { $$ = $1 / $3; }
| NUMBER { $$ = $1; }
;
%%
void yyerror(char *s)
{
fprintf(stderr, "error: %s at %s, line %d\n", s, yytext, yylineno);
}
int main(int argc, char *argv[])
{
yyparse();
return 0;
}
これは正しい出力を生成しません。lexer は文字列を double として解釈し、それらをyylval
変数に適切に格納しますが、パーサーが数値を合計すると、0.0000
. ただし、 1 つの変数のみで構成されるディレクティブyylval
を介して共用体として宣言し、レクサーのこのフィールドに出力を格納し、さらにパーサーで宣言すると、動作するように見えます。%union
double lf_val;
atof
yylval
%token <lf_val> NUMBER
%type <lf_val> expr
しかし、単純なtypedef
ingの方法がうまくいかないのはなぜYYSTYPE
でしょうか? 私も試し#define YYSTYPE double
ました。それもうまくいきませんでした。