Celem jest stworzenie preprocesora dla języka C, możliwie jak najmniejszego pod względem rozmiaru kodu źródłowego w bajtach , w preferowanym języku. Jego dane wejściowe będą plikiem źródłowym typu C, a dane wyjściowe będą wstępnie przetworzonym kodem źródłowym.
Elementy, które będzie musiał przetworzyć to: Usuwanie komentarzy (linia / blok), #include directives (otwieranie plików we względnych ścieżkach i zastępowanie tekstu w wymaganym punkcie), #define, #undef, #if, #elif, #else, #endif, #ifdef, #ifndef i zdefiniowane (). Inne dyrektywy preprocesora C, takie jak #pragmas lub #errors, można zignorować.
Nie ma potrzeby obliczania wyrażeń arytmetycznych lub operatorów porównania w dyrektywach #if, zakładamy, że wyrażenie będzie miało wartość true, dopóki będzie zawierało liczbę całkowitą inną niż zero (jego główne zastosowanie będzie dotyczyło dyrektywy zdefiniowanej ()). Przykłady możliwych danych wejściowych i wyjściowych (możliwe dodatkowe spacje w plikach wyjściowych zostały przycięte dla lepszego wyglądu, nie ma potrzeby, aby kod to robił). Program zdolny do prawidłowego przetworzenia poniższych przykładów zostanie uznany za wystarczający.
----Input file: foo.c (main file being preprocessed)
#include "bar.h" // Line may or may not exist
#ifdef NEEDS_BAZZER
#include "baz.h"
#endif // NEEDS_BAZZER
#ifdef _BAZ_H_
int main(int argc, char ** argv)
{
/* Main function.
In case that bar.h defined NEEDS_BAZ as true,
we call baz.h's macro BAZZER with the length of the
program's argument list. */
return BAZZER(argc);
}
#elif defined(_BAR_H_)
// In case that bar.h was included but didn't define NEEDS_BAZ.
#undef _BAR_H_
#define NEEDS_BARRER
#include "bar.h"
int main(int argc, char ** argv)
{
return BARRER(argc);
}
#else
// In case that bar.h wasn't included at all.
int main()
{return 0;}
#endif // _BAZ_H_
----Input file bar.h (Included header)
#ifndef _BAR_H_
#define _BAR_H_
#ifdef NEEDS_BARRER
int bar(int * i)
{
*i += 4 + *i;
return *i;
}
#define BARRER(i) (bar(&i), i*=2, bar(&i))
#else
#define NEEDS_BAZZER // Line may or may not exist
#endif // NEEDS_BARRER
#endif // _BAR_H_
----Input file baz.h (Included header)
#ifndef _BAZ_H_
#define _BAZ_H_
int baz(int * i)
{
*i = 4 * (*i + 2);
return *i;
}
#define BAZZER(i) (baz(&i), i+=2, baz(&i))
#endif // _BAZ_H_
----Output file foopp.c (no edits)
int baz(int * i)
{
*i = 4 * (*i + 2);
return *i;
}
int main(int argc, char ** argv)
{
return (baz(&argc), argc+=2, baz(&argc));
}
----Output file foopp2.c (with foo.c's first line removed)
int main()
{return 0;}
----Output file foopp3.c (with bar.h's line "#define NEEDS_BAZZER" removed)
int bar(int * i)
{
*i += 4 + *i;
return *i;
}
int main(int argc, char ** argv)
{
return (bar(&argc), argc*=2, bar(&argc));
}
#if
trzeba wspierać? tzn. czy preprocesor musi obsługiwać wyrażenia za pomocą operacji arytmetycznych, bitowych itp.?Odpowiedzi:
Flex, 1170 + 4 = 1174
1170 znaków w kodzie flex + 4 znaki dla flagi kompilacji. Aby utworzyć plik wykonywalny, uruchom
flex pre.l ; gcc lex.yy.c -lfl
.Wpis przecieka pamięć jak sito i nie zamyka dołączonych plików.Ale w przeciwnym razie powinien być całkowicie funkcjonalny zgodnie ze specyfikacją.Niektóre wyjaśnienia:
a
ib
są temps do przechowywania ciągów z wejścia.a
służy również jako parametr do działaniaf
.v
przechowuje nazwy makr iV
przechowuje wartości „V” makrt
iT
są współczesnymi posiadaczami, kiedy dorastamyv
iV
i
jest narzędziem do tworzenia pętlis
jest „wielkością” tablicy makro
jest liczbą „otwartych”if
wewnątrz fałszywego warunkug()
„zmniejsza tablice makrf()
„f” oznacza makro o tej samej wartościv
coa
d(y)
'zatrzymuje ostatniey
znaki z bieżącego wejściaD
jest wewnątrz „D”F
służy do ignorowania warunku „F”I
jest dla „Ignorowanieelse
/elif
po znalezieniu prawdziwego warunku.EDYCJA 1: wyczyścił wiele wycieków pamięci i zaimplementował zamykanie plików
EDIT2: zmodyfikowano kod, aby lepiej obsługiwał zagnieżdżone makra
EDIT3: szalona ilość gry w golfa
EDIT4: więcej golfa
EDIT5: więcej golfa; Zauważyłem również, że moje wywołanie fclose () powoduje problemy na niektórych komputerach ... patrząc na to.
źródło
#include
coś robię , ale myślę, że jest to związane z błędem w edycji # 5. Nie zastępuje też makr, mimo że z powodzeniem przetwarza bloki # if - chyba że robię coś źle ... ale ogólnie wygląda to bardzo dobrze i daje przybliżone wyobrażenie o tym, co może zrobić leksykon, ponieważ Rozumiem to nawet w formie golfa. Spróbuj sprawdzić, czy błędy można naprawić, jeśli nie jest w porządku, ponieważ kod wyjaśnia się dobrze, prawdopodobnie zostanie wybrana odpowiedź, ponieważ nie ma innych wpisów.