Chciałem zapoznać się z zagadnieniami lex i yacc i wykorzystać to w Qt Creator. Innymi słowy chciałem napisać sobie jakiś prosty program wykorzystujący kod wygenerowany przez lex i yacc.
Znalazłem prosty przykład: http://www.ii.uni.wroc.pl/~marcinm/dyd/translatory/
Ja użyłem narzędzi z GnuWin32:
http://gnuwin32.sourceforge.net/packages/flex.htm
http://gnuwin32.sourceforge.net/packages/bison.htm
Uruchomiłem Qt Creator, utworzyłem na początek pusty projekt C (teoretycznie nie ma różnicy, czy C, czy C++, ale już przy C pojawił się pierwszy problem).
Na potrzeby moich prób nieco przerobiłem pliki lex i yacc z powyższego przykładu tak, żeby wskazać prawidłowy plik lex i żeby w pliku yacc nie było funkcji main.
Plik lex:
%%
[ \t] ;
[0-9]+"."[0-9]+ { yylval = atof(yytext); return NUM; } ;
\n { return yytext[0]; }
. { return yytext[0]; }
%%
Plik yacc:
%{
#define YYSTYPE double
#include "D:\LexYacc\Calc\calclex.c"
%}
%token NUM
%%
input:
| input line ;
line: exp '\n' { printf("%.10g\n",$1); } ;
exp: NUM { $$ = $1; }
| exp exp '+' { $$ = $1 + $2; }
| exp exp '-' { $$ = $1 - $2; }
| exp exp '*' { $$ = $1 * $2; }
| exp exp '/' { $$ = $1 / $2; }
;
%%
yyerror(s)
char *s;
{
printf("%s\n",s);
}
Pliki przetwarzam na kod C takimi poleceniami:
flex -oD:\LexYacc\Calc\calclex.c -L D:\LexYacc\Calc\Calc.l
bison -o D:\LexYacc\Calc\calcyy.c -l D:\LexYacc\Calc\Calc.y
Potem w QtCreator plik main.c zmieniam na taką postać:
#include <stdio.h>
#include <D:\LexYacc\Calc\calcyy.c>
int main(void)
{
printf("Hello World!\n");
return 0;
}
Co prawda funkcja parsowania nie jest nigdzie wywoływana, to program powinien się skompilować, a nie kompiluje się i pojawiają się takie błędy.
D:\LexYacc\Calc\calclex.c:605: błąd:C2065: 'yylval' : undeclared identifier
D:\LexYacc\Calc\calclex.c:605: błąd:C2065: 'NUM' : undeclared identifier
D:\LexYacc\Calc\calcyy.c:259: błąd:C2040: 'malloc' : 'void *(size_t)' differs in levels of indirection from 'void *(size_t)'
D:\LexYacc\Calc\calcyy.c:266: błąd:C2371: 'free' : redefinition; different basic types
W pliku calcyy.c jest taka treść:
# ifndef YYMALLOC
# define YYMALLOC malloc
# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
|| defined __cplusplus || defined _MSC_VER)
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
Usunąłem dwie linie z powyższego fragmentu:
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
void free (void *); /* INFRINGES ON USER NAME SPACE */
Nie ma błędów dotyczących malloc i free, ale nadal są błędy dotyczące NUM i yylval.
Tak, jakby kompilator analizując plik calclex.c nie widział pliku calcyy.c, żeby sprawdzić, czym jest NUM i czym jest yylval.
Potem pliki calclex.c i calcyy.c przeniosłem do tego samego katalogu, w którym jest plik main.c i we wszystkich include usunąłem ścieżkę dostępu, ale to nie rozwiązało problemu.
Co może być przyczyną problemów?