4

浮動小数点演算を実行できるフレックス/バイソン計算機を実装しようとしています。私のフレックスコードは次のようになります

%{
#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を介して共用体として宣言し、レクサーのこのフィールドに出力を格納し、さらにパーサーで宣言すると、動作するように見えます。%uniondouble lf_val;atofyylval%token <lf_val> NUMBER%type <lf_val> expr

しかし、単純なtypedefingの方法がうまくいかないのはなぜYYSTYPEでしょうか? 私も試し#define YYSTYPE doubleました。それもうまくいきませんでした。

4

1 に答える 1

5

に関して%codeBison のドキュメントには次のように記載されています。

%code requires [...] is the best place to override Bison's default YYSTYPE
and YYLTYPE definitions.

したがって、bison ファイルの先頭に次を追加するだけです。

%code requires
  {
    #define YYSTYPE double
  }

次の 2 行も削除する必要があります。

typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED

YYSTYPE_IS_DECLARED は、私の知る限り、どこにも文書化されていないため、Bison の内部使用のみであることに注意してください。

単純なプロローグに対するBison の%codeディレクティブの使用に慣れていない場合は、ドキュメントのこのセクションを読むと興味深い%{かもしれません。

于 2013-01-22T17:36:06.297 に答える