1

今、私は他のものを手に入れています。を実行するbison -d calc.yと、コンソールに多くのソースコードが表示されます (多くのm4_define) が、ファイルは生成されません。今私のコードは次のようになります:

%{
#define YYSTYPE double
#include <math.h>
%}
%token NUM
%%
input:    /* empty */
        | input line
;

line:     '\n'
        | exp '\n'  { printf ("\t%.10g\n", $1); }
;

exp:      NUM             { $$ = $1;         }
        | exp exp '+'     { $$ = $1 + $2;    }
        | exp exp '-'     { $$ = $1 - $2;    }
        | exp exp '*'     { $$ = $1 * $2;    }
        | exp exp '/'     { $$ = $1 / $2;    }
      /* Exponentiation */
        | exp exp '^'     { $$ = pow ($1, $2); }
      /* Unary minus    */
        | exp 'n'         { $$ = -$1;        }
;
%%

/* Lexical analyzer returns a double floating point 
   number on the stack and the token NUM, or the ASCII
   character read if not a number.  Skips all blanks
   and tabs, returns 0 for EOF. */

#include <ctype.h>
#include <stdio.h>

yylex ()
{
  int c;

  /* skip white space  */
  while ((c = getchar ()) == ' ' || c == '\t')  
    ;
  /* process numbers   */
  if (c == '.' || isdigit (c))                
    {
      ungetc (c, stdin);
      scanf ("%lf", &yylval);
      return NUM;
    }
  /* return end-of-file  */
  if (c == EOF)                            
    return 0;
  /* return single chars */
  return c;                                
}

yyerror (s)  /* Called by yyparse on error */
     char *s;
{
  printf ("%s\n", s);
}

main ()
{
  yyparse ();
}

元の質問

独自の開発言語を作成しようとしていますが、開始するのが非常に難しく、開始すると多くのエラーが発生し、解決方法がわかりません。これは私のコードです:

#include <ctype.h>
#include <stdio.h>

yylex ()
{
  int c;

  /* skip white space  */
  while ((c = getchar ()) == ' ' || c == '\t')  
    ;
  /* process numbers   */
  if (c == '.' || isdigit (c))                
    {
      ungetc (c, stdin);
      scanf ("%lf", &yylval);
      return NUM;
    }
  /* return end-of-file  */
  if (c == EOF)                            
    return 0;
  /* return single chars */
  return c;                                
}

main ()
{
  yyparse ();
}

calc.y ソース コード ファイル:

%token NUM
%%
input:
        | input line
;

line:     '\n'
        | exp '\n'  { printf ("\t%.10g\n", $1); }
;

exp:      NUM             { $$ = $1;         }
        | exp exp '+'     { $$ = $1 + $2;    }
        | exp exp '-'     { $$ = $1 - $2;    }
        | exp exp '*'     { $$ = $1 * $2;    }
        | exp exp '/'     { $$ = $1 / $2;    }
      /* Exponentiation */
        | exp exp '^'     { $$ = pow ($1, $2); }
      /* Unary minus    */
        | exp 'n'         { $$ = -$1;        }
;
%%

そして今、コンパイラログ:

C:\Documents and Settings\Nathan Campos\Desktop>gcc calc.tab.c -lm -o rpcalc
calc.tab.c: In function `yylex':
calc.tab.c:15: error: `yylval' undeclared (first use in this function)
calc.tab.c:15: error: (Each undeclared identifier is reported only once
calc.tab.c:15: error: for each function it appears in.)
calc.tab.c:16: error: `NUM' undeclared (first use in this function)

なにが問題ですか?

4

5 に答える 5

6

修正された回答

提供する修正されたコードは、ほぼクリーンにコンパイルされます。使用する前に宣言する必要があります#include <stdio.h>printf()(などの関数のプロトタイプも使用する必要がありますyyerror(const char *str)。通常、コードを21世紀にドラッグします。)

'12+'にも正しく応答します。

単一のファイルでは、''を使用する必要はありませんbison -d

ごみが表示されている場合は、ビルドコマンドとビルド環境を確認する必要があります。


元の回答

どこから始めますか?

推奨事項: Lex and Yacc(ライブラリから)またはFlex and Bison(2009年8月の更新/書き換え-おそらくライブラリにはまだありません)に関するO'Reillyの本を入手してください。より迅速なリソースが必要な場合は、Unixバージョン7のマニュアルまたはGNUBisonのマニュアルをお勧めします。どちらもオンラインで入手できます。特に、LexとYaccに関する第7版のドキュメントを読んでください。元の説明でカバーされていなかったことを実行しようとしているわけではありません(ただし、そこにあるCコードはC89標準よりも10年以上前のものです)。

  • bison -dを使用して、トークン番号を含むヘッダーを生成する必要があります。ソースファイル「zzz.y」の場合、これによりCコード「zzz.tab.c」および「zzz.tab.h」が生成されます。
  • メインプログラムに「zzz.tab.h」を含める必要があります。
  • C99を使用する必要があるため、リターンタイプはオンyylex()とである必要がありmain()ます。
  • 宣言する必要がありますyylval。幸い、Bisonの'zzz.tab.h'ファイルはそれを正しく実行します。見た目ほど単純ではありません。
  • 字句解析プログラム(-3.1416)で負の数を許可することをお勧めします。明示的に正の数(+3.1416)も許可することをお勧めします。
  • おそらく、'$$'とその仲間が、デフォルトのタイプ( )doubleではなくタイプであることを確認する必要があります。int#define YYSTYPE double
于 2009-10-11T16:19:10.483 に答える
2

IIRC、yylvalはBisonによって宣言されていますが、タイプを指定する必要があります。これがないと、コンパイラが混乱し、誤解を招くエラーが発生する可能性があります。

YYSTYPEを定義する必要があります。あなたの場合、あなたは「#defineYYSTYPEdouble」で逃げることができます。これは、文法の上部近くの%{...%}ブロックで行います。

%unionは、YYSTYPEをユニオンとして宣言するためにも使用できます。

これはBisonの手動標準rpcalcの例のように見えるので、「YYSTYPE」と「%union」を簡単に検索できると思います。

于 2009-10-11T16:26:47.643 に答える
1

.y ファイルに次の行を追加します。

void yyerror(char *errorinfo);
int yylex(void);

また、flex によって生成されたトークン タイプを定義する必要があります。

%token NUM

等々。

編集: Flex and Bison (O'Reilly) は優れたリソースです。

于 2009-10-11T16:11:43.447 に答える
0

変数yylval がどこにも宣言されていません。

于 2009-10-11T16:09:43.340 に答える
0

YYSTYPE を #define するのは得策ではありません。私が試したバイソンでは確かにうまくいきません。あなたがすべきことは、あなたが扱う値が double であることを Bison に伝えることです:

%union {
    double dval;
}

%type <dval> exp NUM

Bison は適切な YYSTYPE を生成します。

しかし、チュートリアルか何かを見ることをお勧めします。Thomas Niemann の A Compact Guide to Lex & Yacc は良いガイドで、例と段階的な説明を提供しています。私はコンパイラのコースを教えていますが、私の経験では、試行錯誤が多すぎると、Bison と文法を使い始めるのが難しい場合があります。

于 2009-10-16T05:04:41.050 に答える