3

私は LFS を読んでいて、他の場所よりも前に見たバイソンに出くわしたので、それについてもう少し学ぶ必要があると思いました。UC Riverside CS 部門からこのページを見つけましたが、サンプル コードが機能していません。誰が何が悪いのか知っていますか?便宜上、コードを貼り付けました:

calc.lexファイル:

/* Mini Calculator */
/* calc.lex */

%{
#include "heading.h"
#include "tok.h"
int yyerror(char *s);
int yylineno = 1;
%}

digit       [0-9]
int_const   {digit}+

%%

{int_const} { yylval.int_val = atoi(yytext); return INTEGER_LITERAL; }
"+"     { yylval.op_val = new std::string(yytext); return PLUS; }
"*"     { yylval.op_val = new std::string(yytext); return MULT; }

[ \t]*      {}
[\n]        { yylineno++;   }

.       { std::cerr << "SCANNER "; yyerror(""); exit(1);    }

calc.yファイル:

/* Mini Calculator */
/* calc.y */

%{
#include "heading.h"
int yyerror(char *s);
int yylex(void);
%}

%union{
  int       int_val;
  string*   op_val;
}

%start  input 

%token  <int_val>   INTEGER_LITERAL
%type   <int_val>   exp
%left   PLUS
%left   MULT

%%

input:      /* empty */
        | exp   { cout << "Result: " << $1 << endl; }
        ;

exp:        INTEGER_LITERAL { $$ = $1; }
        | exp PLUS exp  { $$ = $1 + $3; }
        | exp MULT exp  { $$ = $1 * $3; }
        ;

%%

int yyerror(string s)
{
  extern int yylineno;  // defined and maintained in lex.c
  extern char *yytext;  // defined and maintained in lex.c

  cerr << "ERROR: " << s << " at symbol \"" << yytext;
  cerr << "\" on line " << yylineno << endl;
  exit(1);
}

int yyerror(char *s)
{
  return yyerror(string(s));
}

エラーメッセージは次のとおりです。

$ make
bison -d -v calc.y
cp calc.tab.c bison.c
cmp -s calc.tab.h tok.h || cp calc.tab.h tok.h
g++ -g -Wall -ansi -pedantic -c bison.c -o bison.o
calc.tab.c: In function ‘int yyparse()’:
calc.tab.c:1381: warning: deprecated conversion from string constant to ‘char*’
calc.tab.c:1524: warning: deprecated conversion from string constant to ‘char*’
flex calc.lex
cp lex.yy.c lex.c
g++ -g -Wall -ansi -pedantic -c lex.c -o lex.o
calc.lex:8: error: redefinition of ‘int yylineno’
lex.yy.c:349: error: ‘int yylineno’ previously defined here
calc.lex: In function ‘int yylex()’:
calc.lex:23: warning: deprecated conversion from string constant to ‘char*’
lex.yy.c: At global scope:
lex.yy.c:1105: warning: ‘void yyunput(int, char*)’ defined but not used
make: *** [lex.o] Error 1
4

1 に答える 1

3

問題は、C コードを C++ コンパイラでコンパイルしていることです。flex で C++ を生成する場合は、そのためのコマンド ライン オプションがあります。

スキャナーが生成したコードは、yylineno既に の定義を提供します。

C では、以下が許容されます。

int yylineno;         /* tentative definition */
int yylineno = 1;     /* definition */

C++ では、そうではありません。

int yylineno;         /* definition */
int yylineno = 1;     /* another definition: duplicate, error! */

-ansiまた、 gcc オプションは C 方言に適用されることに注意してください。

文字列定数に関する警告も C++ が原因です。C++ では、文字列リテラル likeは、 ではなく , に"abc"評価されます。const char *char *

最後に、flex によって生成されたスキャナーには、更新するコードが自動的に含まれないことに注意してくださいyylineno。でオンになってい%option yylinenoます。Flex の GNU Info マニュアルを確認してください。

于 2013-10-08T19:18:40.113 に答える