0

我在 lex 和 yacc 中实现了一个 sql 解析器,因为我使用了一个符号表,它保存在一个单独的 .h 文件 (sql.h) 中,并且在这个头文件中我有一些函数声明。这些函数的定义保存在 .c 文件 (sql.c) 中。现在我在 sql.c 中包含了 sql.h,我在 lex 文件 (1.l) 和 yacc 文件 (1.y) 中都引用了 sql.h 中的符号和函数。

问题是我无法为此编写适当的makefile。我收到诸如多个声明之类的错误。我在哪里包含哪个文件以及如何编写依赖项?请帮忙。我一直在寻找解决方案,但我没有得到它......

更新:

我像这样编译代码:

法 1.l
yacc -d 1.y
gcc lex.yy.c y.tab.c sql.c -ll -ly

在 gcc 的第三个命令之后出现以下错误:

在 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

请发布您的 Makefile。据我了解,代码也存在问题,而不仅仅是Makefile。或者可能是您尝试1.o从.1.l1.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

可能您还需要依赖令牌的声明文件。

编辑:啊,所以可能您需要将该表的定义放入一个文件中,并将声明放入标题中。您必须首先了解C中声明和定义之间的区别。例如,如果您有以下文件:

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

aaa.c
#包括“aaa.h”

bbb.c
#include "aaa.h"

然后你尝试cc -o aaa aaa.c bbb.c,你得到多重定义错误。这意味着,实际的数组必须在一个文件中,并且在标题中它应该类似于extern int arr[];

更新:

您应该在 sql.h 中删除设置为 NULL。那里只是一个声明,某处有这样那样的变量。实际值将在 sql.c 中分配。

于 2011-02-27T13:32:18.957 回答
0
extern struct sym_table *SQL = NULL;
extern struct sym_select *SQL_SEL = NULL;

= NULL从头文件中删除初始化。

于 2011-03-01T12:11:22.250 回答