Flex i Bison/Konfiguracja make gcc
Wstęp
[edytuj]Żeby zacząć potrzebujemy gcc, make, stdc, flex i bison które na pewno będą zapaczkowane. Nie należy się przejmować świeżością tych programów gdyż nie będziemy używali nowo wprowadzonych funkcji a stabilność osiągneły już dawno. W zupełności wystarczą sprzed roku/dwóch. Potrzebujemy też katalogu z naszymi projektami i ew. ściągniętym manualem oraz podkatalogi na poszczególne lekcje. Zazwyczaj nasze projekty/lekcje będą się składać z plików:
- makefile (dane dla make)
- *.l (dane analizy leksykalnej - flex)
- *.y (dane gramatyki - bison)
- *.c/*.h(dodatkowy kod którego nie chcieliśmy umieszczać w regułach flexa/bisona).
Make
[edytuj]Make dba o to w jaki sposób/kolejności kompilować twój program. Poznając Make nie musisz pamiętać o wywoływaniu flexa, bisona i gcc w odpowiedniej kolejności i z wszystkimi flagami. Po drobnej literówce czy poprawce nie musisz rekompilować całości, make zadba aby zbudować pliki które się zmieniły. I jeszcze jedno: wszystko po "#" do końca lini jest komentarzem.
#przykładowy makefile
#aplikacje (1)
LEX = flex
YACC = bison -y
CC = gcc
#flagi (2)
LFLAGS =
YFLAGS =
#reguły (3)
pierwszy: pierwszy.o
pierwszy.o: pierwszy.c
pierwszy.c: pierwszy.l
- Dobrze jest na początku zdefiniować z jakich programów korzystamy i jak je wywołujemy. Konieczne jeśli korzystamy z reguł wbudowanych.
- Flagi potrzebne przy wywoływaniu, tutaj wpisujemy flagi które chcemy żeby wbudowane reguły je wykorzystały.
- Każda reguła zaczyna się tym co zostanie wyprodukowane potem ":" i lista plików od których zależy. Jeżeli któryś z wymaganych plików został zmodyfikowany od ostatniego wywołania make to reguła zostanie powtórnie wykonana. Używam reguł wbudowanych i je polecam.
Flex
[edytuj]Pierwszy plik flexa (pierwszy.l):
%%
Taki plik jest jak najbardziej poprawnym plikiem analizy leksykalnej. Niestety nie uda nam się skompilować takich danych jako samodzielnego programu gdyż:
- Brakuje funkcji "int yywrap(void)" - jest ona wołana przez flexa gdy skończą się dane wejściowe, jeżeli zwróci wartość różną od 0 to więcej danych wejściowych jest niedostępnych.
- Brakuje też funkcji main.
%%
%%
int yywrap (void) //1
{
return 1;
}
int main (int argc,char **argv) //2
{
return yylex();
}
- Tak właśnie wygląda funkcja yywrap mówiąca "po tym pliku nie ma więcej danych".
- A tak wygląda funckja main, yylex jest główną funkcją analizatora leksykalnego i zwraca 0 przy końcu pliku oraz numer tokena który znalazł (przydatne przy łączeniu z bisonem).
Bison
[edytuj]Uwaga!
|
Tak powinien wyglądać makefile który budowałby połączony program flexa/bisona.
#aplikacje
LEX = flex
YACC = bison -y
CC = gcc
#flagi
LFLAGS =
YFLAGS =
#linkowanie całości
drugi: drugi.o drugi.grm.o drugi.lex.o
#kompilacja
drugi.o: drugi.c
drugi.lex.o: drugi.lex.c drugi.grm.h #dane tokenów terminalnych
drugi.grm.o: drugi.grm.c
drugi.lex.c: drugi.l
drugi.grm.c: drugi.y
Zakończenie
[edytuj]W zależności od tego czy piszemy tylko flexową aplikację czy też coś łączonego takie makefile powiny nam na próby i eksperymenty wystarczyć. Teraz możemy zająć się nauką a make będzie odwalał za nas całą pracę.