0

私は lex と yacc で sql パーサーを実装しています。別の .h ファイル (sql.h) に保存されているシンボル テーブルを使用し、このヘッダー ファイルにはいくつかの関数宣言があります。これらの関数の定義は、.c ファイル (sql.c) に保持されます。これで、sql.c に sql.h を含めました。lex ファイル (1.l) と yacc ファイル (1.y) の両方で、sql.h のシンボルと関数を参照します。

問題は、このための適切なメイクファイルを作成できないことです。複数の宣言などのエラーが発生します。どのファイルをどこにインクルードし、依存関係をどのように記述するか? 助けてください。解決策を検索しましたが、わかりません.....

アップデート:

次のようにコードをコンパイルします。

レックス1.l
yacc -d 1.y
gcc lex.yy.c y.tab.c sql.c -ll -ly

gcc の 3 番目のコマンドの後に、次のエラーが表示されます。

1.l:5 からインクルードされたファイル:
sql.h:17: 警告: 'SQL' が初期化され、'extern' が宣言されました
sql.h:18: 警告: 'SQL_SEL' が初期化され、'extern' が宣言されました
1.l: 関数 'makeTable' 内:
1.l:80: 警告: 互換性のないポインター型からの代入
1.y:7 からインクルードされたファイル:
sql.h:17: 警告: 'SQL' が初期化され、'extern' が宣言されました
sql.h:18: 警告: 'SQL_SEL' が初期化され、'extern' が宣言されました
sql.c:3: エラー: 'SQL' の再定義
sql.h:15: 注: 「SQL」の以前の定義はここにありました
sql.c:4: エラー: 'SQL_SEL' の再定義
sql.h:16: 注: 'SQL_SEL' の以前の定義はここにありました

sql.h:

#ifndef SQL_H
#define SQL_H
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

struct sym_table {
    char *token;
    char *value;
    struct sym_table *next;
};

struct sym_select {
    char **cols;        
};

extern struct sym_table *SQL = NULL;
extern struct sym_select *SQL_SEL = NULL;


void addSymbol(char *, char *);
void print(struct sym_table *);
void showTable(struct sym_table *);
void makeTable(struct sym_table *, int);

sql.c:

#include "sql.h"

struct sym_table *SQL = NULL;
struct sym_select *SQL_SEL = NULL;

そして、sql.h で宣言された関数の定義

1.l ファイル:

%{
    #include <stdio.h>
    #include <stdlib.h>
    #include "y.tab.h"
    #include "sql.h"
    int lineno=1;
    void makeTable(struct sym_table *, int);    
%}

..... およびその他の lex ファイル

1.y

%{
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    extern int lineno;
    extern void yyerror(char *);
    #include "sql.h"
%}

.... およびその他の yacc ファイル データ


これを回避する別の方法を教えてもらえますか?

4

2 に答える 2

0
extern struct sym_table *SQL = NULL;
extern struct sym_select *SQL_SEL = NULL;

= NULLヘッダー ファイルから初期化を削除します。

于 2011-03-01T12:11:22.250 に答える
0

Makefile を投稿してください。私が理解している限りでは、Makefile だけでなく、コードにも問題があります。1.oまたは、から作成しようとしている可能性があり1.lます。1.o1.y

通常、依存関係は次のようになります。

1l.o: 1.l sql.h; # lex invocation
1y.o: 1.y sql.h; # bison invocation
sql.o: sql.c sql.h; # cc invocation
prog: 1l.o 1y.o sql.o; # ld invocation

おそらく、トークンの宣言ファイルにも依存する必要があります。

EDIT:ああ、おそらくそのテーブルの定義を1つのファイルに入れ、宣言をヘッダーに入れる必要があります。まず、 Cにおける宣言と定義の違いを理解する必要があります。たとえば、次のファイルがあるとします。

aaa.h
int arr[]={1};

aaa.c
#include "aaa.h"

bbb.c
#include "aaa.h"

そして、しようとするとcc -o aaa aaa.c bbb.c、複数定義エラーが発生します。つまり、実際の配列は 1 つのファイルにある必要があり、ヘッダーでは次のようにする必要があります。extern int arr[];

アップデート:

sql.h で NULL への設定を削除する必要があります。どこかにそのような変数があるというのは、そこにある宣言にすぎません。実際の値は sql.c で割り当てられます。

于 2011-02-27T13:32:18.957 に答える