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 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
  1. Dobrze jest na początku zdefiniować z jakich programów korzystamy i jak je wywołujemy. Konieczne jeśli korzystamy z reguł wbudowanych.
  2. Flagi potrzebne przy wywoływaniu, tutaj wpisujemy flagi które chcemy żeby wbudowane reguły je wykorzystały.
  3. 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.

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();
    }
  1. Tak właśnie wygląda funkcja yywrap mówiąca "po tym pliku nie ma więcej danych".
  2. 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).

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ę.

Następny rozdział: Flex_wprowadzenie