Czy słowa kluczowe muszą być zarezerwowane?

Czy można nadać zmiennej nazwę taką samą jak któreś ze słów kluczowych używanego języka programowania? Zapewne większość z osób, słysząc takie pytanie, odpowie nań przecząco. W końcu niezależnie czy piszesz w Pythonie i spróbujesz napisać for = 42, czy może jesteś programistą C++ i w swoim kodzie umieścisz int if = 1.0; albo posługujesz się na co dzień JavaScriptem i postanowisz dodać linijkę var else = "foo";, to żaden kompilator ani interpreter nie pozwoli na takie zachowanie. Ale czy na pewno jest to żelazna zasada, od której w rozległym świecie języków programowania nie ma żadnych wyjątków?

Wyjątki, jak się okazuje, są. Na dodatek wcale nie trzeba w ich poszukiwaniu zapuszczać się w odmęty jakichś zupełnie egzotycznych technologii, bo słowa kluczowe, które nie są równocześnie słowami zarezerwowanymi znajdziemy w językach, które były w swoim czasie całkiem popularne. Zanim jednak przejdę do przykładów, zacznijmy od ustalenia definicji, którymi będziemy się tutaj posługiwać.

  • słowo kluczowe (ang. keyword) to słowo stanowiące wyodrębnioną jednostkę leksykalną, często w określonym kontekście, mające szczególne znaczenie i identyfikujące określony rozkaz, instrukcję lub deklarację w programie komputerowym [1].
  • słowo zarezerwowane (ang. reserved word) to słowo (ciąg znaków) zdefiniowane w składni określonego języka programowania, które nie może być użyte jako definiowany przez programistę element kodu źródłowego, mimo iż spełnia ono pozostałe kryteria definiowania danego elementu (np. identyfikatora) [2].

Większość współczesnych języków posiada słowa zarezerwowane, a ich zbiór jest tożsamy bądź w dużej mierze pokrywa się ze słowami kluczowymi. Z jednej strony zakazywanie używania pewnych ciągów znaków jako nazw zmiennych w pewien sposób ogranicza swobodę programisty, z drugiej jednak jest sporym ułatwieniem przy tworzeniu kompilatorów, a nierzadko też przy lekturze napisanego kodu. Dokładniej mówiąc, znacznie upraszcza on fazę analizy leksykalnej, której zadaniem jest zamiana sekwencji znaków (kodu źródłowego) w sekwencje tokenów. Przykładowo, mając fragment:

analizator leksykalny może przetworzyć go na coś w stylu:

Ponieważ słowo kluczowe „if” jest zarazem słowem zarezerowanym, to za każdym razem gdy lekser napotka ten ciąg znaków, może zinterpretować go jako słowo kluczowe. Czyż to nie banalne? Zauważmy, że gdyby, zależnie od kontekstu, „if” mogło być albo nazwą zmiennej, albo słowem kluczowym, to analiza nie byłaby już taka prosta. Kompilator, aby zdecydować jak zinterpretować dany ciąg znaków, jest wtedy zmuszony do wczytania kolejnych leksemów (tzw. look-ahead parsing).

Języki bez słów zarezerwowanych

Dodatkowa komplikacja dla kompilatora wcale nie oznacza jednak, że nie istnieją języki, w których słów zarezerwowanych po prostu nie ma. Zjawisko to występuje chociażby w PL/I, w którym całkowicie legalne będzie napisanie [3]:

Powyższy fragment ukazuje przy okazji, że brak słów zarezerwowanych to nie tylko trudność dla twórców kompilatorów, ale może też stanowić problem dla innych programistów, dla których tak napisany kod może być niezrozumiały i nieczytelny. Niezarezerwowane słowa kluczowe posiada także Fortran. Co więcej, język ten (przynajmniej w niektórych wersjach) pozwala też na inne dziwactwa, np. na spacje, które są ignorowane przez kompilator. Oznacza to, że wszystkie poniższe instrukcje są poprawne i mają identyczne znaczenie:

O ile w tym przypadku nie pojawia się jeszcze problem z interpretacją słów kluczowych, to kiedy mamy do czynienia z rozdzieloną spacją nazwą zmiennej rozpoczynającej się tak jak słowo kluczowe, sprawa nieźle się komplikuje. Jeden z najbardziej znanych przykładów to pętla DO, która w Fortranie może wyglądać np. tak:

oznacza ona, że wszystkie instrukcje aż do etykiety „10” zostaną wykonane pięciokrotnie (od indeksu 1 do 5). Wystarczy jednak, że w zamiast przecinka postawimy kropkę, aby całkowicie zmienić sens instrukcji:

powyższa linia jest bowiem ekwiwalentem przypisania wartości 1.5 do zmiennej o nazwie do10i. 

Stropping

Czasami z brakiem słów zarezerwowanych radzono sobie inaczej niż na podstawie analizy kontekstu, w którym pojawia sie dany ciąg znaków. Jedną ze stosowanych technik jest tzw. stropping. Polega on na oznaczaniu słów kluczowych jakimś dodatkowym znakiem, np. kropką, apostrofem lub podkreśleniem. Języki, w których zastosowano tę metodę to np.:

  • FORTRAN 77: słowne operatory logiczne oznaczane są przy pomocy dwóch kropek: .EQ., .OR., .NOT. itp.
  • ALGOL 68: pojedynczy apostrof wskazywał, że poprzedzone nim słowo jest kluczowe: 'BEGIN
  • Nim: współczesny język, w którym słowo kluczowe może zostać użyte jako identyfikator przez otoczenie go znakiem grawisu:  `for`
  • SQL: słowa zarezerwowane moga być nazwami kolumn, tabeli czy zmiennych, jeśli znajdują się wewnątrz cudzysłowów (lub innych znaków, zależy od implementacji)

Rezerwacje na przyszłość i przeszłość

A teraz mała zagadka: skoro słowa kluczowe mogą nie być zarezerwowane, to czy słowa zarezerwowane mogą nie być kluczowe? Okazuje sie, że tak i wcale nie jest to tak rzadka sytuacja, jak mogłoby się wydawać. W niektórych językach ich autorzy stosują rezerwowanie pewnych słów z myślą o przyszłości (tzw. reserved for future use). Takie działanie zapewnia kompatybilnośc w przód (ang. forward compatibility), ponieważ jeśli słowa te zostaną w przyszłości zaimplementowane jako kluczowe, nie spowoduje to problemów z kompilacją wcześniej napisanego kodu.

Innym przykładem słów, które są zarezerwowane mimo, iż nie są słowami kluczowymi są goto oraz const w Javie. Ich użycie jako nazwy zmiennych, funkcji czy klas jest zabronione, ale nie pełnią one żadnej roli. Ciekawostką dotyczącą tego pierwszego jest fakt, że pozostało ono zarezerwowane, aby zachować kompatybilność wsteczną, bowiem początkowe wersje JVM posiadały zaimplementowaną tę instrukcję skoku [4].

Istnieją przypadki słów, które są zarezerwowawne, ale nie są kluczowe. Np. goto albo const w javie, albo są „reserved for future use” – zarzerwowane na przyszlosc (np. w C++)

Źródła

  1. „Słowo kluczowe”, Wikipedia.
  2. „Słowo zastrzeżone”, Wikipedia.
  3. J. Ullman et. al., Kompilatory. Reguły, metody i narzędzia, WNT 2002, str. 83.
  4. StackOverflow: Is there a goto statement in Java?