PL/0
PL/0 to język programowania , pomyślany jako edukacyjny język programowania , który jest podobny do Pascala , języka programowania ogólnego przeznaczenia, ale znacznie prostszy . Służy jako przykład budowy kompilatora . Został pierwotnie wprowadzony w książce Algorithms + Data Structures = Programs autorstwa Niklausa Wirtha w 1976 roku. Zawiera dość ograniczone konstrukcje językowe: nie ma liczb rzeczywistych, bardzo niewiele podstawowych operacji arytmetycznych i żadnych konstrukcji przepływu sterowania innych niż „jeśli” i bloki „while”. Chociaż te ograniczenia sprawiają, że pisanie prawdziwych aplikacji w tym języku jest niepraktyczne, pomaga to kompilatorowi zachować zwartość i prostotę.
Cechy
Wszystkie używane stałe i zmienne muszą być jawnie zadeklarowane.
Jedynymi typami danych są liczby całkowite . Jedynymi operatorami są operatory arytmetyczne i porównania. Istnieje nieparzysta
funkcja, która sprawdza, czy argument jest nieparzysty.
W oryginalnej implementacji przedstawionej przez Wirtha nie ma procedur wejścia i wyjścia . Nowa wartość każdej zmiennej jest drukowana przez kompilator w miarę jej zmian. A więc program:
0 0
var ja , s ; zacznij ja := ; s := ; podczas gdy i < 5 zaczynamy i : = i + 1 ; s := s + ja * i koniec koniec .
daje wyjście:
0 0 1 1 2 5 3 14 4 30 5 55
Jednak większość implementacji ma pojedyncze procedury wejścia i wyjścia.
Struktury sterowania przepływem to konstrukcje if-then
i while-do oraz
procedury zdefiniowane przez użytkownika . Procedury nie mogą akceptować parametrów.
Gramatyka
Poniżej przedstawiono zasady składni języka modelu zdefiniowanego w EBNF :
program = blok "." ; block = [ "const" ident "=" liczba { "," ident "=" liczba } ";" ] [ "var" ident { "," ident } ";" ] { "procedura" ident ";" blok ";" }
oświadczenie ; instrukcja = [ ident ":=" wyrażenie | identyfikator „wywołania” | "?" ident | "!" wyrażenie | instrukcja „rozpocznij” { „;” instrukcja } "koniec" | warunek „jeżeli ” instrukcja „wtedy” | warunek „ dopóki ” „zrób”
oświadczenie ]; warunek = wyrażenie „nieparzyste” | wyrażenie ( "=" | "#" | " <" | "<=" | " >" | ">=" ) wyrażenie ; wyrażenie = [ "+" | "-" ] termin { ( "+" | "-" )
termin }; term = czynnik {( "*" | "/" ) czynnik }; czynnik = ident | liczba | "(" wyrażenie ")" ;
Studentom dość łatwo jest napisać rekurencyjny parser zejścia dla tak prostej składni. Dlatego kompilator PL/0 jest nadal szeroko stosowany na kursach budowy kompilatorów na całym świecie. Ze względu na brak funkcji w oryginalnej specyfikacji, studenci zazwyczaj spędzają większość czasu na rozbudowie języka i jego kompilatora. Zwykle zaczynają się od wprowadzenia REPEAT .. UNTIL
i kontynuują bardziej zaawansowane funkcje, takie jak przekazywanie parametrów do procedur lub struktur danych, takich jak tablice, łańcuchy znaków lub liczby zmiennoprzecinkowe.
Zastosowanie w edukacji
Główny artykuł o kompilatorach honoruje PL/0 [ potrzebne źródło ] za wprowadzenie kilku wpływowych koncepcji (udoskonalanie stopniowe, parsowanie rekurencyjne, EBNF, kod P, diagramy T) w terenie poprzez edukowanie studentów w zakresie korzystania z tych koncepcji. W ciągu ostatnich 3 dekad większość kursów uniwersyteckich na temat budowy kompilatorów, które wykorzystywały PL/0, ściśle podążała za Wirthem w stosowaniu tych technik (patrz odnośniki poniżej). Kilka lat temu kursy uniwersyteckie odeszły od kursu wyznaczonego przez Wirtha, zastępując klasyczną technikę parsowania rekurencyjnego (mimo to klasycznym) uniksopodobnym podejściem wykorzystującym lex i yacc . Dopiero niedawno pojawiła się implementacja ( PL/0 Language Tools ) w ten sposób połączył również nowoczesne koncepcje, takie jak orientacja obiektowa i wzorce projektowe, z nowoczesnym językiem skryptowym ( Python ), umożliwiając studentom zapoznanie się z tekstem źródłowym implementacji we współczesnym stylu programowania.
Budowa kompilatora
W grudniu 1976 roku Wirth napisał małą książeczkę o budowie kompilatora, zawierającą pełny kod źródłowy kompilatora PL/0. Powyższe zasady składni zostały zaczerpnięte z pierwszego wydania książki Wirtha Compilerbau . W późniejszych wydaniach tej książki (pod wpływem prowadzonych badań) Wirth zmienił składnię PL/0. Zmienił pisownię słów kluczowych, takich jak const
i procedure,
na wielkie litery. Ta zmiana sprawiła, że PL / 0 bardziej przypomina Modulę-2 . W tym samym czasie przyjaciel i współpracownik Wirtha, CAR Hoare , pracował nad swoim wpływowym komunikowania się procesów sekwencyjnych , w której użyto wykrzyknika ! a znak zapytania ? oznaczać prymitywy komunikacyjne. Wirth dodał oba symbole do języka PL/0, ale nie wspomniał w książce o ich semantyce.
Przykłady
Poniższy przykład pochodzi z takiego rozszerzonego języka o nazwie PL/0E. Ten program wyświetla kwadraty liczb od 1 do 10. Obecnie większość kursów poświęconych budowie kompilatorów zastąpiła wykrzyknik procedurą WriteLn
.
VAR x , kwadrat ; PROCEDURA kwadrat ; POCZĄTEK kwadrat : = x * x KONIEC ; POCZĄTEK x := 1 ; GDY x < = 10 ROZPOCZNIJ WYWOŁAJ kwadrat ; ! kwadrat ; x := x + 1 KONIEC KONIEC .
Poniższy program wypisuje liczby pierwsze od 1 do 100. Instrukcja zapisu odpowiada znakowi „!” instrukcja w powyższej składni EBNF.
0
stała maks . = 100 ; var arg , ret ; procedura jest pierwsza ; var ja ; rozpocznij ret := 1 ; ja := 2 ; while i < arg zacznij jeśli arg / i * i = arg to zacznij ret : = ; i := argument koniec
; ja := ja + 1 koniec koniec ; liczby pierwsze procedury ; rozpocznij arg := 2 ; while arg < max rozpocznij wywołanie isprime ; _ jeśli ret = 1 to napisz arg ; arg := arg + 1 koniec koniec ; nazywać liczbami pierwszymi .
Poniższy przykład został zaczerpnięty z drugiego wydania książki Wirtha Compilerbau, która ukazała się w 1986 roku w Niemczech.
0
0
VAR x , y , z , q , r , n , fa ; PROCEDURA pomnóż ; VAR a , b ; ROZPOCZNIJ a := x ; b := y ; z := ; GDY b > ZACZNIJ JEŚLI NIEPARZYSTE b TO z : = z + a ;
0
za := 2 * za ; b := b / 2 KONIEC KONIEC ; PROCEDURA podzielić ; VAR w ; ROZPOCZNIJ r := x ; q := ; w := y ; GDY w <= r DO w := 2 * w ; GDY w > y ZACZNIJ q _
:= 2 * q ; w := w / 2 ; JEŻELI w <= r TO ZACZNIJ r := r - w ; q := q + 1 KONIEC KONIEC KONIEC ; PROCEDURA gcd ; VAR fa , g ; POCZĄTEK f := x ; g := y ; CHWILA
f # g ROZPOCZNIJ JEŻELI f < g TO g : = g - f ; JEŻELI g < f TO fa : = f - g KONIEC ; z := f KONIEC ; PROCEDURA fakt ; ROZPOCZNIJ JEŻELI n > 1 TO ZACZNIJ f := n * f ;
n := n - 1 ; WYWOŁAJ fakt KONIEC KONIEC ; POCZĄTEK ? x ; ? y ; CALL pomnóż ; ! z ; ? x ; ? y ; ZADZWOŃ podziel ; ! q ; ! r ; ? x ; ? y ; ZADZWOŃ gcd ; ! z
; ? n ; f := 1 ; ZADZWOŃ fakt ; ! f KONIEC .
Oberon-0
W trzecim i ostatnim wydaniu swojej książki o budowie kompilatorów Wirth zastąpił PL/0 Oberonem-0. Język Oberon-0 jest znacznie bardziej złożony niż PL/0. Na przykład Oberon-0 oferuje tablice, rekordy, deklaracje typów i parametry procedur. Wydawca książek Wirtha (Addison-Wesley) zdecydował o wycofaniu wszystkich swoich książek, ale Wirth opublikował poprawione wydania swojej książki począwszy od 2004 r. Od sierpnia 2017 r. Najnowsza dostępna wersja pochodzi z maja 2017 r.
Zobacz też
Notatki
- Liffick, Blaise W., Ed (1979), Bajtowa księga Pascala , ISBN 0-07-037823-1
- Wirth, Niklaus (1975), algorytmy + struktury danych = programy , ISBN 0-13-022418-9
- Wirth, Niklaus (1986), Compilerbau , BG Teubner, Stuttgart ISBN 3-519-32338-9
Linki zewnętrzne
- Kompilator (plik .pas) z pierwszego wydania książki Compilerbau , napisany w Pascalu
- Kolejna kopia kompilatora na stronie Pascal dla małych maszyn
- Interpreter z książki "Algorytmy + Struktury Danych = Programy", napisany w Pascalu
- Opracowanie kompilatora w stylu PL/0 w oparciu o „Konstrukcję kompilatora” napisaną w Mocce (Modula-2 dla systemu Linux)
- Artykuł wyjaśniający użycie PL/0 na Uniwersytecie w Rochester
- Strona główna podręcznika PL / 0 „Algorytmy + Struktury danych = Programy” [1]
- http://sourceforge.net/projects/pl0-compiler (napisany w C/C++, wykorzystuje framework QT)
- https://modernc.org/pl0 (napisany w Go, działa w terminalu, na wielu platformach)
- https://github.com/dodobyte/plzero (bardzo mały kompilator tworzy plik wykonywalny systemu Windows)
- https://github.com/MarcRochkind/pl0compiler (kompilator dla IBM 701 napisany w C; generuje asembler 701)
- Kategoria:PL/0 Zadania zaimplementowane w PL/0 na stronie rosettacode.org