我在lex和yacc中实现了一个sql解析器, 因为我使用了一个符号表,我保存在一个单独的.h文件(sql.h)中,在这个头文件中我有一些函数声明。 这些函数的定义保存在.c文件(sql.c)中。现在我在sql.c中包含了sql.h, 我在我的lex文件(1.l)和yacc文件(1.y)中引用了sql.h中的符号和函数。
问题是我无法为此编写正确的makefile。 我收到多个声明之类的错误。 我在哪里包含哪个文件以及如何编写依赖项? 请帮忙。我已经找到了解决方案,但我没有得到它......
我编译代码如下:
lex 1.l yacc -d 1.y gcc lex.yy.c y.tab.c sql.c -ll -ly
在gcc的第三个命令后出现以下错误:
In file included from 1.l:5: sql.h:17: warning: ‘SQL’ initialized and declared ‘extern’ sql.h:18: warning: ‘SQL_SEL’ initialized and declared ‘extern’ 1.l: In function ‘makeTable’: 1.l:80: warning: assignment from incompatible pointer type In file included from 1.y:7: sql.h:17: warning: ‘SQL’ initialized and declared ‘extern’ sql.h:18: warning: ‘SQL_SEL’ initialized and declared ‘extern’ sql.c:3: error: redefinition of ‘SQL’ sql.h:15: note: previous definition of ‘SQL’ was here sql.c:4: error: redefinition of ‘SQL_SEL’ sql.h:16: note: previous definition of ‘SQL_SEL’ was here
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);
%}
.....和其他文件
1.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int lineno;
extern void yyerror(char *);
#include "sql.h"
%}
....和其他yacc文件数据
你能建议我用其他方法解决这个问题吗?
答案 0 :(得分:0)
请发布您的Makefile。据我所知,代码也存在问题,不仅仅是Makefile。或者您可能尝试从1.o
1.l
和1.o
1.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 强>
#include“aaa.h”
<强> bbb.c 强>
#include“aaa.h”
然后你尝试cc -o aaa aaa.c bbb.c
,你得到多重定义错误。这意味着,实际数组必须在一个文件中,在标题中应该是extern int arr[];
您应该在sql.h中将设置删除为NULL。它只是一个声明,在某处有这样的变量。实际值将在sql.c中分配。
答案 1 :(得分:0)
extern struct sym_table *SQL = NULL;
extern struct sym_select *SQL_SEL = NULL;
从头文件中删除初始化= NULL
。