Typedef issue with bison and flex - c

In my parser, I have
%union {
SYMTABLE *p_entry ;
QUAD *p_quad ;
} ;
Now, SYMTABLE is the typedef for a struct. The struct and typedef are in an included file. There are no issues with this.
QUAD is the typedef for a struct (typedef struct quad QUAD). The struct and typedef are in an included file.
There is no problem doing:
bison -d parser.y
gcc parser.tab.c -c
My lexer needs yylval, so in the declarations part I have
#include "parser.tab.h" /* bison generated header file */
extern YYSTYPE yylval ;
When I do
flex scanner.lex
gcc lex.yy.c -c
GCC complains
In file included from scanner.lex:16:
parser.y:30: error: syntax error before "QUAD"
parser.y:30: warning: no semicolon at end of struct or union
parser.y:32: error: syntax error before '}' token
parser.y:32: warning: data definition has no type or storage class
parser.tab.h:121: error: syntax error before "yylval"
parser.tab.h:121: warning: data definition has no type or storage class
If I go back to my parser.y file and replace QUAD with struct quad in ONLY the yylval %union, the problem goes away. I want to say this is a silly typedef mistake, but the bison generated file compiles just fine. I have included the header file for my QUAD typedef and struct quad in my scanner.
It seems this is the only place where the issues occurs, so I could just replace QUAD with struct quad, but this is inconsistent with the SYMTABLE.

my test.l:
%{
#include "bla.h"
#include "test.tab.h" /* bison generated header file */
extern YYSTYPE yylval ;
%}
%%
\n printf("nl");
. printf("c");
%%
my test.y:
%{
#include "bla.h"
%}
%union {
SYMTABLE *p_entry ;
QUAD *p_quad ;
};
%%
input:
| input;
%%
my bla.h:
typedef void *SYMTABLE;
typedef void *QUAD;
my build:
freundt#segen:pts/21:~/temp> bison -d test.y
test.y: conflicts: 1 shift/reduce
test.y:13.3-7: warning: rule useless in parser due to conflicts: input: input
freundt#segen:pts/21:~/temp> flex test.l
freundt#segen:pts/21:~/temp> icc lex.yy.c -c
freundt#segen:pts/21:~/temp>

Related

error: conflicting types for ‘yylval’ extern YYSTYPE yylval

I'm trying to run this:
stark.lex
%{
#include <stdio.h>
#include "y.tab.h"
#ifndef YYSTYPE
#define YYSTYPE char*
#endif
#define INTEGER 288
extern YYSTYPE yylval;
%}
%%
[0-9]+ yylval=strdup(yytext);return NUMBER;
...
(\)){1} yylval=strdup(yytext);return EBRACKET;
\n
[ \t]+ ;
%%
int yywrap()
{return 1;}
stark.y
%{
#include <stdio.h>
#include <string.h>
#ifndef YYSTYPE
#define YYSTYPE char*
#endif
#define INTEGER 288
extern YYSTYPE yylval;
extern FILE* yyin;
void yyerror (const char *str);
int yylex(void);
%}
%token NUMBER IDENTIFIER KEY_VAR OPERATION SEMICOLON COMMA SIGN MINUS OBRACKET EBRACKET BG ND PLUS
%left PLUS MINUS
%left OPERATION
%left UNARY
%%
...
int main()
{yyin = fopen("prog.txt","r");
yyparse();
fclose(yyin);
return 0; }
with command:
yacc -d stark.y && lex stark.lex && gcc lex.yy.c y.tab.c
But i'm getting this error:
stark.lex:15:16: error: conflicting types for ‘yylval’
extern YYSTYPE yylval;
^~~~~~
In file included from stark.lex:5:0:
y.tab.h:88:16: note: previous declaration of ‘yylval’ was here
extern YYSTYPE yylval;
It worked last winter and i can't undestand why it doesn't work now. I'm using lex and yacc on ubuntu.
If you're going to use #define to redefine YYSTYPE, then you need to do it before you #include <y.tab.h>. Otherwise, y.tab.h will make YYSTYPE a type alias (typedef) for int. Since both y.tab.h and y.tab.c also declare yylval (as extern YYSTYPE), there is actually no need for you to declare it anywhere, but you still need to put the #define before the #include.
If you use bison, there are much better (and more convenient) ways to declare of YYSTYPE. The best one is to put
%define api.value.type { char* }
into your .y file, for example just before the %token declaration. Then you can remove the #define YYSTYPE from both files, as well as the extern YYSTYPE yylval; declarations, since bison will put an appropriate typedef into the header file.
You really should compile your project with
gcc -Wall lex.yy.c y.tab.c
Then gcc will warn you about many mistakes. Both bison and flex will produce warning-free code, provided you put the following into your lex file:
%option noinput nounput
I usually recommend using %option noyywrap as well, since that will allow you to avoid having to write a dummy yywrap implementation.

How to compile a yacc file that contains a header file [duplicate]

I wrote bison code header:
%{
#include "foo.h"
%}
And I defined a struct named 'Foo' in header. I'd like to use it as token type in Bison.
%define api.value.type union
%token <Foo*> bar
Then I use -d option to generate bison.tab.h file.
bison -d bison.y
But there is no #include foo.h in bison.tab.h, and it use struct Foo to define the union YYSTYPE.
//bison.tab.h
union YYSTPE {
Foo* bar;
...
};
It caused error when compile this program: error: ‘Foo’ does not name a type
Is there a way to include header file in bison.tab.h or another solution of this case?
For includes that should appear in both the .c and the .h file (before the definition for the %union), you should use %code requires { ... }. %{ ... } inserts code in the .c file only.
For more information on the various %code options, you can look at the "Prologue Alternatives" chapter of the Bison docs.
I needed to use 2.3 bison version, which doesn't have %code directive, so I just added a command which insert my include into top of bison output header, when I compile program
echo #include \"my_include.hpp\" | cat - ${BISON_HEADER_OUTPUT} > tmp && mv tmp ${BISON_HEADER_OUTPUT}

Using union in yacc file

I'm trying to develop a basic compiler and I'm using a union for yylval as follows:
%{
#include <string.h>
#include <stdio.h>
struct info {
int line;
/* details unimportant */
};
%}
%union{
char *str;
struct info *ptr;
}
In my lexer definition, I have
%{
#include "parse.tab.h"
%}
But when I compile the generated lexer, I get the following errors:
y.tab.h: unknown type name 'YYSTYPE'.
error: request for a member str in something not a structure or a union.
Do I need to #define YYSTYPE as well?
(I edited the original question to insert enough information from the source files to make the question answerable. Any mistakes in the transcription are my fault and I apologize -- Rici.)
No. If you use a %union declaration, you must not #define YYSTYPE; the bison manual makes this clear.
However, any necessary declarations -- in this case, the declaration of struct info -- must be included in your lexer description file (parse.l) as well. The two generated files are independent of each other, so the fact that struct info is declared in the parser does not make the definition automatically available to the lexer.
In order to avoid repeating the declarations, it is usually a good idea to put them in a separate header file:
file: info.h (added)
#ifndef INFO_H_HEADER_
#define INFO_H_HEADER_
struct info {
int line;
/* details unimportant */
};
// ...
#endif
file: parse.y (now #include's info.h instead of the in-line struct declaration)
%{
#include <stdio.h>
#include <string.h>
#include "info.h"
%}
%union{
char *str;
struct info *ptr;
}
file: parse.l (also #includes info.h)
%{
#include <stdio.h>
#include <string.h>
/* This must come *before* including parse.tab.h */
#include "info.h"
#include "parse.tab.h"
%}
The following is an example of how I use YYSTYPE:
typedef union { // base type filled by lexical analyzer
struct {
int numtype; // classval (type; selects into union below)
union {
int ival; // integer value
long lval; // long value
double dval; // double
} val;
} numval;
unsigned char *sval; // string value
} lex_baseval;
typedef struct { // type returned by lexical analyzer
int lineno;
lex_baseval lexval;
} YYSTYPE;
#define YYSTYPE YYSTYPE
The problem with your linked code is that the %union is inside the %{...%} at the top of your .y file -- which means that yacc just copies it verbatim to the y.tab.c file and does not actually process it.
This manifests most obviously as a syntax error on %union when you try to compile y.tab.c, but also means there's no YYSTYPE definition in y.tab.h, as yacc didn't see the %union so didn't create one.

Why does G_DEFINE_INTERFACE trigger an "expected declaration specifiers" compiler error?

As part of getting familiar with GObject I'm trying to create a "Hello, world" interface following the example in the reference manual. Here's what I have in hello_world_if.h:
#ifndef __HELLO_WORLD_IF_H__
#define __HELLO_WORLD_IF_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define TYPE_HELLO_WORLD_IF (hello_world_if_get_type())
#define HELLO_WORLD_IF(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_HELLO_WORLD_IF, HelloWorldIf))
#define IS_HELLO_WORLD_IF(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_HELLO_WORLD_IF))
#define HELLO_WORLD_IF_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), TYPE_HELLO_WORLD_IF, HelloWorldIfInterface))
typedef struct _HelloWorldIf HelloWorldIf; /* dummy object */
typedef struct _HelloWorldIfInterface HelloWorldIfInterface;
struct _HelloWorldIfInterface {
GTypeInterface parent;
gchar *(*get_hello)(HelloWorldIf *self);
};
GType hello_world_if_get_type(void);
gchar *hello_world_if_get_hello(HelloWorldIf *self);
G_END_DECLS
#endif /* __HELLO_WORLD_IF_H__ */
and in hello_world_if.c:
#include "hello_world_if.h"
G_DEFINE_INTERFACE(HelloWorldIf, hello_world_if, 0);
static void
hello_world_if_default_init(gpointer g_class) {
/* Add properties and signals to the interface here */
}
gchar *
hello_world_if_get_hello(HelloWorldIf *self) {
g_return_if_fail(IS_HELLO_WORLD_IF(self));
HELLO_WORLD_IF_GET_INTERFACE(self)->get_hello(self);
}
But this doesn't compile:
$ make
gcc -g -pthread -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -c -o hello_world_if.o hello_world_if.c
hello_world_if.c:3: error: expected declaration specifiers or ‘...’ before ‘hello_world_if’
hello_world_if.c:3: error: expected declaration specifiers or ‘...’ before numeric constant
hello_world_if.c:3: warning: data definition has no type or storage class
make: *** [hello_world_if.o] Error 1
From reading other answers here it seems this "expected declaration specifiers" message often means a necessary header file hasn't been included or has been included too late. But I'm not sure how that could be the case here. (Specifically, adding #include <glib.h> or #include <glib-object.h> to the C file doesn't change anything.)
I must be missing something simple but I just don't see it. Help?
Turns out there's a simple explanation: The G_DEFINE_INTERFACE macro was added in GLib 2.24.0, but I'm using version 2.22.5 (the standard on CentOS 6.3). I'll need to either build and install a newer version of GLib or dig up older reference documentation—the website doesn't go back further than 2.26.1.

Makefile for sql parser... writing dependencies

I'm implementing a sql parser in lex and yacc,
in that I use a symbol table which I kept in a separate .h file (sql.h) and in this header file I have some functions declarations.
The definitions of these functions are kept in a .c file (sql.c). Now I have included sql.h in sql.c,
I refer to the symbols and functions from sql.h in both my lex file(1.l) and yacc file(1.y).
The problem is that I'm not able to write a proper makefile for this.
I'm getting errors like multiple declarations.
Where do I include which file and how to write dependencies?
Please help. I have searched for a solution but I'm not getting it.....
Update:
I compile the code like this:
lex 1.l
yacc -d 1.y
gcc lex.yy.c y.tab.c sql.c -ll -ly
I get the following errors after the third command of 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;
And the definitions of the functions declared in sql.h
1.l file:
%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
#include "sql.h"
int lineno=1;
void makeTable(struct sym_table *, int);
%}
..... and othr lex file
1.y
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int lineno;
extern void yyerror(char *);
#include "sql.h"
%}
.... and other yacc file data
Can you suggest me some other way to get around this?
Please post your Makefile. As far as i understand there's also a problem with code, not only with Makefile. Or it could be that you try to make 1.o from 1.l and different 1.o from 1.y.
Normally the dependencies should look something like:
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
Probably you will also need to depend on tokens' declaration file.
EDIT:
Ah, so probably you need to put the definition of that table into one file, and the declaration into the header. You must first understand the difference between declaration and definition in C. For example if you have the following files:
aaa.h
int arr[]={1};
aaa.c
#include "aaa.h"
bbb.c
#include "aaa.h"
And then you try to cc -o aaa aaa.c bbb.c, you get the multiple definition error. That means, that the actual array must be in one file, and in the header it should be something like extern int arr[];
Update:
You should remove setting to NULL in sql.h. It's only a declaration there, that there is such and such variable somewhere. The actual value is to be assigned in sql.c.
extern struct sym_table *SQL = NULL;
extern struct sym_select *SQL_SEL = NULL;
Remove the initialization = NULL from the header file.

Resources