0

コードのコンパイルに問題があります。

main() が yacc パーサーと同じファイルにある場合は機能しますが、main() を別のファイルに配置すると機能しません。

これは私の Flex ファイルです: (lex1.ll)

%{
#include <stdio.h>
#include "yac1.tab.hh"

    extern "C"
    {
        int yylex(void);
    }

int line_num = 1;       
%}
alpha [A-Za-z]
digit [0-9]
%%


"DELETE ALL"    return DELALL;
[ \t] ;
INSERT      return INSERT;
DELETE      return DELETE;
FIND        return FIND;

[0-9]+\.[0-9]+ { yylval.fval = atof(yytext); return FLOAT;   }
[0-9]+         { yylval.ival = atoi(yytext); return INT;     }
[a-zA-Z0-9_]+  { yylval.sval = strdup(yytext);return STRING; }

\n             { ++line_num; return ENDL; }
. ;
%%

これは私の Bison ファイルです: (yac1.yy)

%{
#include <stdio.h>
#include <stdlib.h>

int intval;

void yyerror(const char *s)
{
    fprintf(stderr, "error: %s\n", s);
}

extern "C"
{
        int yyparse(void);
        int yylex(void);  
        int yywrap()
        {
                return 1;
        }

}
%}

%token INSERT DELETE DELALL FIND ENDL
%union {
    int ival;
    float fval;
    char *sval;
}

%token <ival> INT
%token <fval> FLOAT
%token <sval> STRING
%%

S:T {printf("INPUT ACCEPTED....\n");exit(0);};

T:      INSERT val  {printf("hey insert FOUND\n");} 
      | DELETE val
      | DELALL ENDL
      | FIND val
;

val :   INT ENDL  {printf("hey %d\n",$1);intval=$1; }   
      |
    FLOAT ENDL
      |
    STRING ENDL  {printf("hey %s\n",$1);}   

;

%%
/*
It works if I uncomment this block of code
int main()
{
    while(1){
        printf("Enter the string");
        yyparse();
    }
}
*/

これが私のメインプログラムです: (testlex.cc)

#include <stdio.h>
#include "lexheader.h"
#include "yac1.tab.hh"

extern int intval;
main()
{

/*
char * line = "INSERT 54\n";
YY_BUFFER_STATE bp = yy_scan_string( line ); 
yy_switch_to_buffer(bp); 
yyparse(); 
yy_delete_buffer(bp);     
printf ("hello %d",intval);

*/
printf("Enter the query:");

//while(1)
printf ("%d\n",yyparse());

}

そして、これは私のメイクファイルです

parser: lex1.ll yac1.yy testlex.cc
    bison -d yac1.yy
    flex --header-file="lexheader.h" lex1.ll
    g++ -o parser yac1.tab.cc lex.yy.c testlex.cc -lfl

clean:

    rm -rf *.o parser

コンパイルすると、このエラーが発生します。

bison -d yac1.yy
flex --header-file="lexheader.h" lex1.ll
g++ -o parser yac1.tab.cc lex.yy.c testlex.cc -lfl
testlex.cc: In function ‘int main()’:
testlex.cc:21:24: error: ‘yyparse’ was not declared in this scope
make: *** [parser] Error 1

PS: g++ でコンパイルする必要があります。gcc を使用すると、コードが動作します。

この点でどんな助けでも大歓迎です。

ありがとう。

4

2 に答える 2

2

GNU Bison のドキュメントを読みましたか? 完全な例を含むC++パーサーに関する章があります(あなたのものと非常に似ています)。

この回答yyparseで 提案されているように明示的に宣言することもできますが、実際の C++ パーサーを作成する方がおそらく優れています。

あなたMakefileはあまり良くありません。あなたは次のようなものを持つことができます

  LEX= flex
  YACC= bison
  LIBES= -lfl
  CXXFLAGS= -Wall
  parser: lex1.o yac1.tab.o lex.yy.o testlex.o
          $(LINKER.cc) -o $@ $^ $(LIBES)
  lex1.cc: lex1.ll
          $(LEX) --header-file="lexheader.h" $< -o $@
  yac1.tag.cc: yac1.yy
          $(YACC) -d $<

GNU makeのドキュメントも読んでください。をデバッグするためにremake asを使用したい場合があります。remake -xMakefile

于 2013-08-03T08:31:29.393 に答える
1

ファイルで関数を宣言する必要があります。yyparsetestlex.cc

int yyparse();

これは関数プロトタイプと呼ばれるもので、関数が存在し、呼び出すことができることをコンパイラに伝えます。


ソースをもう少し詳しく調べたところ、既存のプロトタイプが機能しなかった理由がわかりました。それは、それを宣言したextern "C"が、ファイルを C++ ソースとしてコンパイルしたためです。関数は古い C スタイルの関数であるextern "C"とコンパイラに伝えましたが、C++ コンパイラでソースをコンパイルし続けました。yyparseこれにより、名前の不一致が発生しました。

于 2013-08-03T08:31:21.333 に答える