Dlaczego elastyczność Fortha sprawia, że ​​gramatyka jest dla niego nieodpowiednia?

10

Niedawno podjąłem się zadania napisania języka programowania opartego na stosie. Zanim jednak zacząłem projektować swój język, pomyślałem, że dobrym pomysłem byłoby czytanie i eksperymentowanie z istniejącymi językami stosowymi.

To prowadzi mnie do tematu tego postu. Czytałem artykuł w Wikipedii na temat Forth , języka opartego na stosie, który używa wyrażeń w stylu postfiksowym. W artykule widziałem następujące oświadczenie:

Elastyczność Fortha sprawia, że ​​statyczna gramatyka BNF jest nieodpowiednia i nie ma monolitycznego kompilatora. Rozszerzenie kompilatora wymaga tylko napisania nowego słowa, zamiast modyfikacji gramatyki i zmiany podstawowej implementacji.

Z mojego zrozumienia, w języku żargonu Forth, termin „słowo” wydaje się zasadniczo równoznaczny z „podprogramem”. Biorąc to pod uwagę, powyższe stwierdzenie wydaje się dziwne. Dlaczego właśnie możliwość tworzenia nowych funkcji w Forth sprawia, że ​​formalna gramatyka dla Forth jest nieodpowiednia? Dlaczego musiałbyś przepisywać gramatykę dla każdego nowego podprogramu, który zdefiniujesz? W jaki sposób pisanie nowego słowa w środowisku stanowi rozszerzenie kompilatora? Powyższe stwierdzenie wydaje się podobne do stwierdzenia, że ​​gramatyka formalna jest nieodpowiednia dla Pythona, ponieważ można definiować nowe funkcje.

W rzeczywistości postanowiłem napisać gramatykę w stylu BNF dla prostego podzbioru Forth poniżej:

program        ::= stmt+
stmt           ::= func | expr
func           ::= ':' expr+ ';'
expr           ::= INTEGER | word
word           ::= ('+' | '-' | '*' | '/' )

Powyższa gramatyka wydaje się obejmować prawidłowy podzbiór zdań Fortha i nie wydaje się, że trudno jest rozszerzyć ją na wszystkie prawidłowe instrukcje w języku Forth. Ponadto, jeśli parser kompilatora implementuje powyższą gramatykę, nie widzę, jak kiedykolwiek kompilator mógłby zostać rozszerzony. Kompilator po prostu doda nowe słowa do swojego środowiska . Zmienia się tylko środowisko. Wydaje się, że powyższy fragment Wikipedii łączy w sobie kod podkreślający, który tworzy kompilator (który się nie zmienia) ze środowiskiem kompilatora (który się zmienia).

Podsumowując, dlaczego nieumiejętność Fortha w zakresie definiowania nowych słów (podprogramów) jest nieodpowiednia dla gramatyki pisanej?

Christian Dean
źródło
1
„Niewłaściwe” to mocne słowo w tym kontekście. Lepsze słowo byłoby prawdopodobnie „niepotrzebne”.
Robert Harvey
1
Och, dobrze @RobertHarvery. Gdyby tak jednak było, to cytowany przeze mnie fragment miałby zastosowanie do większości języków. Z technicznego punktu widzenia gramatyka nigdy nie jest potrzebna , ale miło jest mieć taką gramatykę - szczególnie w przypadku analizatorów pisma ręcznego.
Christian Dean
Ale w większości języków analizator składni nie jest zwykłą biblioteką wykonawczą, którą można zmienić za pomocą kodu użytkownika, co wpływa na sposób analizowania następnego wiersza.
Jörg W Mittag

Odpowiedzi:

10

„Normalne” słowo jest właściwie tylko podprogramem.

... ale możesz napisać zdefiniowane przez użytkownika słowo , które zmienia sposób działania kompilatora. Na przykład definicja zwykle rozpoczyna się dwukropkiem („:”), a kończy średnikiem („;”). Ale jeśli chcesz, możesz (na przykład) zmienić to, co robi dwukropek, a tym samym zmienić sposób, w jaki definicja słowa jest „kompilowana”, zmieniając w ten sposób sposób działania kompilatora i zmieniając gramatykę rozpoznawanego języka.

Dlatego mówi, że gramatyka jest nieodpowiednia - gramatyka może dosłownie zmieniać się z jednej części programu na inną. Ładowanie słownika może zmienić nie tylko podprogramy, których nazwy są obecnie rozpoznawane, ale także gramatykę analizowaną podczas definiowania nowego słowa.

Jerry Coffin
źródło
2
Czy jesteś pewien, że ta właściwość Fortha naprawdę zmienia gramatykę, a nie tylko semantykę?
Doc Brown
@DocBrown: Większość osób, które używają Fortha, bardzo go lubi, dlatego zazwyczaj dokonują tylko minimalnych zmian niezbędnych do danego zadania. Ktoś, kto był wystarczająco ambitny (i szalony), mógł całkowicie zmienić składnię, jeśli chciał - na przykład używając notacji infix zamiast postfiksów, jeśli bardzo tego chciał.
Jerry Coffin
@DocBrown Jaką gramatykę mógłbyś napisać, co pozwoliłoby mi napisać interpreter języka C w Forth, a następnie nagle przełączyć się na C w środku programu?
user253751
@immibis: cóż, moje pytanie brzmi - czy Forth naprawdę pozwala na coś takiego? Z tego powiązanego artykułu nie jest to dla mnie z natury jasne.
Doc Brown,
@DocBrown Tak to robi. Możesz uruchomić swój kod w czasie kompilacji, co oznacza, że ​​jeśli chcesz, możesz w pełni przejąć kompilator. Zasadniczo możesz uruchomić kompilator / interpreter C w środku kompilatora / interpretera Forth. (czy chcesz w końcu wrócić do Forth, czy nie, zależy od ciebie)
253751
3

W Forth możesz uruchomić kod w czasie kompilacji.

W szczególności możesz uruchomić kod, który zużywa słowa z danych wejściowych. Na przykład, możesz napisać kompilator C w Forth, a następnie wywołać go w czasie kompilacji, a następnie napisać resztę swojego programu w C.

Częściej można definiować słowa, które odczytują argumenty z kodu źródłowego. Tradycyjnie czytałbyś słowa w taki sam sposób jak kompilator, ale nie jest to wymagane.

Na przykład ."słowo (które wypisuje ciąg) nie odczytuje się do następnej spacji, odczytuje do następnej ". Jeśli spróbujesz parsować kod : PRINTHELLO ." Hello ; : func2 world!" ;bez specjalnego przypadku .", okaże się, że nie jest on poprawnie parsowany.

Można oczywiście dodać szczególny przypadek dla ."do gramatyki, ale gramatyka nadal będzie nieprawidłowy, jeśli programista definiuje swoje własne słowo jak ."- na przykład tutaj jest jeden: : MY_PRINT POSTPONE ." ; IMMEDIATE. To słowo jest równoważne z ."; Mogę pisać, MY_PRINT Hello ; world! "a twoja gramatyka musi być w stanie to przeanalizować. Powodzenia z tym.

użytkownik253751
źródło