Gramatyka bezkontekstowa — Context-free grammar

Uproszczony fragment gramatyki formalnej dla języka programowania C (po lewej) i wyprowadzenie fragmentu kodu C (po prawej) z symbolu nieterminalowego . Symbole nieterminali i terminali są wyświetlane odpowiednio w kolorze niebieskim i czerwonym.

W teorii języka formalnego gramatyka bezkontekstowa ( CFG ) to gramatyka formalna, której reguły produkcji mają postać

z pomocą pojedynczego nieterminalowi symbol i ciąg zacisków i / lub nieterminali ( może być pusta). Gramatyka formalna jest „bezkontekstowa”, jeśli jej reguły produkcji mogą być stosowane niezależnie od kontekstu nieterminala. Bez względu na to, jakie symbole go otaczają, pojedynczy nieterminal po lewej stronie można zawsze zastąpić prawym. To właśnie odróżnia ją od gramatyki kontekstowej .

Gramatyka formalna jest zasadniczo zbiorem reguł produkcji, które opisują wszystkie możliwe ciągi znaków w danym języku formalnym. Zasady produkcji to proste zamienniki. Na przykład pierwsza zasada na zdjęciu:

zastępuje się . Dla danego symbolu nieterminalowego może istnieć wiele reguł zastępowania. Język generowany przez gramatykę jest zbiorem wszystkich łańcuchów symboli terminalowych, które mogą być wyprowadzone, przez powtarzające się zastosowania reguł, z określonego symbolu nieterminalnego ("symbol startowy"). Symbole nieterminalne są używane podczas procesu wyprowadzania, ale nie pojawiają się w końcowym ciągu wynikowym.

Języki generowane przez gramatyki bezkontekstowe są znane jako języki bezkontekstowe (CFL). Różne gramatyki bezkontekstowe mogą generować ten sam język bezkontekstowy. Ważne jest, aby odróżnić właściwości języka (właściwości wewnętrzne) od właściwości danej gramatyki (właściwości zewnętrzne). Równość język zapytania (zrobić dwa podane gramatyk bezkontekstowych generować ten sam język?) Jest nierozstrzygalny .

Gramatyki bezkontekstowe powstają w językoznawstwie, gdzie są używane do opisu struktury zdań i słów w języku naturalnym i zostały w rzeczywistości wymyślone przez językoznawcę Noama Chomsky'ego w tym celu. Natomiast w informatyce , wraz ze wzrostem użycia rekurencyjnie definiowanych pojęć, były one coraz częściej stosowane. We wczesnej aplikacji do opisu struktury języków programowania używane są gramatyki . W nowszych aplikacjach są one używane w podstawowej części Extensible Markup Language (XML) o nazwie Document Type Definition .

W językoznawstwie niektórzy autorzy używają terminu gramatyka struktury fraz w odniesieniu do gramatyk bezkontekstowych, przy czym gramatyki struktury fraz różnią się od gramatyk zależności . W informatyce popularnym zapisem gramatyk bezkontekstowych jest forma Backus-Naur lub BNF .

Tło

Przynajmniej od czasów Pāṇini lingwiści opisali gramatyki języków pod kątem ich struktury blokowej i opisali, w jaki sposób zdania są rekurencyjnie budowane z mniejszych fraz i ostatecznie pojedynczych słów lub elementów słownych. Istotną właściwością tych struktur blokowych jest to, że jednostki logiczne nigdy się nie nakładają. Na przykład zdanie:

John, którego niebieski samochód stał w garażu, poszedł do sklepu spożywczego.

można umieścić w nawiasach logicznych (z logicznymi metasymbole [ ] ) w następujący sposób:

[ John [ , [ którego [ niebieski samochód ]] [ był [ w [ garaż ]]] , ]] [ podszedł [ do [ [ sklep spożywczy ]]]] .

Gramatyka bezkontekstowa zapewnia prosty i matematycznie precyzyjny mechanizm opisywania metod, za pomocą których frazy w niektórych językach naturalnych są budowane z mniejszych bloków, odwzorowując w naturalny sposób „strukturę blokową” zdań. Jego prostota sprawia, że ​​formalizm jest podatny na rygorystyczne badania matematyczne. Ważne cechy składni języka naturalnego, takie jak zgodność i odwołanie, nie są częścią gramatyki bezkontekstowej, ale podstawową rekurencyjną strukturą zdań, sposobem, w jaki zdania zagnieżdżają się w innych zdaniach oraz sposobem, w jaki listy przymiotników i przysłówków są połknięte przez rzeczowniki i czasowniki, jest dokładnie opisane.

Gramatyki bezkontekstowe to szczególna forma systemów Semi-Thue, które w swojej ogólnej formie wywodzą się z prac Axela Thue .

Formalizm gramatyk bezkontekstowych został opracowany w połowie 1950 przez Noama Chomsky'ego , a także ich klasyfikację jako szczególny rodzaj z formalnym gramatyki (który nazwał gramatyk fraza struktura ). To, co Chomsky nazwał gramatyką struktury fraz, jest obecnie znane również jako gramatyka okręgowa, w której gramatyki okręgowe stoją w przeciwieństwie do gramatyk zależnościowych . W ramach gramatyki generatywnej Chomsky'ego składnia języka naturalnego została opisana za pomocą reguł bezkontekstowych połączonych z regułami transformacji.

Struktura blokowa została wprowadzona do języków programowania komputerowego przez projekt Algol (1957-1960), który w konsekwencji zawierał również gramatykę bezkontekstową do opisu powstałej składni Algola. Stało się to standardową cechą języków komputerowych, a notacja gramatyczna używana w konkretnych opisach języków komputerowych stała się znana jako forma Backus-Naur , po dwóch członkach komitetu projektowego języka Algol. Aspekt „struktury blokowej”, który przechwytują gramatyki bezkontekstowe, jest tak fundamentalny dla gramatyki, że terminy składnia i gramatyka są często utożsamiane z regułami gramatyki bezkontekstowej, zwłaszcza w informatyce. Formalne ograniczenia, które nie zostały uchwycone przez gramatykę, są wówczas uważane za część „semantyki” języka.

Gramatyki bezkontekstowe są na tyle proste, że umożliwiają konstruowanie wydajnych algorytmów analizowania, które dla danego ciągu określają, czy i jak można go wygenerować na podstawie gramatyki. Earley analizator jest przykładem takiego algorytmu, podczas gdy powszechnie stosowane LR i Parsery LL prostsze algorytmy, które zajmują jedynie bardziej restrykcyjnych podzbiorów bezkontekstowych gramatyk.

Formalne definicje

Gramatyka bezkontekstowa G jest zdefiniowana przez 4- krotkę , gdzie

  1. V jest zbiorem skończonym; każdy element jest nazywany znakiem nieterminalnym lub zmienną . Każda zmienna reprezentuje inny typ frazy lub klauzuli w zdaniu. Zmienne są również czasami nazywane kategoriami składniowymi. Każda zmienna definiuje podjęzyk języka zdefiniowanego przez G .
  2. Σ jest skończonym zbiorem terminali s, rozłącznych od V , które tworzą rzeczywistą treść zdania. Zbiór terminali to alfabet języka zdefiniowanego przez gramatykę G .
  3. R jest skończoną relacją w , gdzie gwiazdka reprezentuje operację gwiazdy Kleene . Elementy R są nazywane regułami (przepisywania) lub produkcją gramatyki. (również powszechnie symbolizowany przez P )
  4. S jest zmienną startową (lub symbolem startowym), używaną do reprezentowania całego zdania (lub programu). Musi to być element V .

Notacja reguł produkcji

Przepis produkcji w R jest sformalizowane matematycznie w postaci pary , w którym jest nieterminalowi i stanowi łańcuch zmiennych i / lub terminal; zamiast używać notacji par uporządkowanych , reguły produkcji są zwykle pisane przy użyciu operatora strzałki z jego lewą stroną i β jako prawą stroną: .

Dopuszcza się, aby β był ciągiem pustym i w tym przypadku zwyczajowo oznaczamy go przez ε. Forma nazywa się produkcją ε .

Powszechnie wymienia się wszystkie prawe strony tej samej lewej strony w tym samym wierszu, używając | ( symbol rury ), aby je oddzielić. Reguły i dlatego mogą być zapisywane jako . W tym przypadku i są nazywane odpowiednio pierwszą i drugą alternatywą.

Stosowanie reguł

Dla dowolnych łańcuchów , mówimy , że u daje bezpośrednio v , zapisane jako , if with i takie , że i . Zatem v jest wynikiem zastosowania reguły do u .

Powtarzające się stosowanie reguł

Dla strun mówimy u daje v lub v jest pochodzący z U , jeśli istnieje liczba całkowita dodatnia k i ciągi takie, że . Ta relacja jest oznaczona lub w niektórych podręcznikach. Jeśli , relacja jest zachowana. Innymi słowy, i są na zwrotne przechodni zamknięcie (pozwalającą na łańcuch, z wytworzeniem się) i czasownik zamknięcie (wymagające co najmniej jeden etap) , odpowiednio.

Język bez kontekstu

Język gramatyki to zbiór

wszystkich ciągów symboli terminala, które można wyprowadzić z symbolu startowego.

Mówi się, że język L jest językiem bezkontekstowym (CFL), jeśli istnieje CFG G , taki, że .

Niedeterministyczne automaty pushdown rozpoznają dokładnie języki bezkontekstowe.

Przykłady

Słowa połączone z ich rewersem

Gramatyka , z produkcjami

SaSa ,
SbSb ,
S → ε ,

jest bezkontekstowy. To nie jest właściwe, ponieważ zawiera produkcję ε. Typowym wyprowadzeniem w tej gramatyce jest

SaSaaaSaaaabSbaaaabba .

To wyjaśnia, że . Język jest bezkontekstowy, jednak można udowodnić, że nie jest regularny .

Jeśli produkcje

Sa ,
Sb ,

są dodawane, otrzymuje się gramatykę bezkontekstową dla zbioru wszystkich palindromów nad alfabetem { a , b } .

Dobrze uformowane nawiasy

Kanonicznym przykładem gramatyki bezkontekstowej jest dopasowanie nawiasów, które jest reprezentatywne dla przypadku ogólnego. Istnieją dwa symbole końcowe „(” i „)” i jeden symbol nieterminalny S. Zasady produkcji to

SSS ,
S → ( S ) ,
S → ()

Pierwsza reguła pozwala na mnożenie symbolu S; druga zasada pozwala na umieszczenie symbolu S w dopasowanych nawiasach; a trzecia reguła kończy rekurencję.

Dobrze uformowane nawiasy zagnieżdżone i nawiasy kwadratowe

Drugim kanonicznym przykładem są dwa różne rodzaje dopasowywania nawiasów zagnieżdżonych, opisane w produkcjach:

SSS
S → ()
S → ( S )
S → []
S → [ S ]

z symbolami terminala [ ] ( ) i nieterminalem S.

W tej gramatyce można wyprowadzić następującą sekwencję:

([ [ [ ()() [ ][ ] ] ]([ ]) ])

Pasujące pary

W gramatyce bezkontekstowej możemy łączyć znaki w pary tak, jak robimy to z nawiasami . Najprostszy przykład:

S → aSb
S → ab

Ta gramatyka generuje język , który nie jest regularny (zgodnie z lematem o pompowaniu dla języków regularnych ).

Znak specjalny ε oznacza pusty ciąg. Zmieniając powyższą gramatykę na

S → aSb
S → ε

zamiast tego otrzymujemy gramatykę generującą język . Różni się tylko tym, że zawiera pusty ciąg, podczas gdy oryginalna gramatyka nie.

Odrębna liczba a i b

Gramatyka bezkontekstowa dla języka składającego się ze wszystkich ciągów znaków powyżej {a,b} zawierających nierówną liczbę a i b:

S → T | U
T → VaT | VaV | TaV
U → VbU | VbV | UbV
V → aVbV | bVaV | ε

Tutaj nieterminal T może generować wszystkie łańcuchy z większą liczbą a niż b, nieterminal U generuje wszystkie łańcuchy z większą liczbą b niż a, a nieterminal V generuje wszystkie łańcuchy z równą liczbą a i b. Pominięcie trzeciej alternatywy w regułach T i U nie ogranicza języka gramatyki.

Drugi blok b podwójnego rozmiaru

Innym przykładem języka nieregularnego jest . Jest bezkontekstowy, ponieważ można go wygenerować za pomocą następującej gramatyki bezkontekstowej:

SbSbb | A
AaA | ε

Formuły logiczne pierwszego rzędu

Te zasady formacji do warunków i formuł logiki formalnej pasuje do definicji bezkontekstowych gramatyki, chyba że zbiór symboli może być nieskończona i nie może być więcej niż jeden symbol początek.

Przykłady języków, które nie są bezkontekstowe

W przeciwieństwie do dobrze uformowanych nawiasów zagnieżdżonych i nawiasów kwadratowych w poprzedniej sekcji, nie ma gramatyki bezkontekstowej do generowania wszystkich sekwencji dwóch różnych typów nawiasów, z których każdy jest oddzielnie zrównoważony bez względu na drugi , gdzie dwa typy nie muszą być zagnieżdżone w jednym inny, na przykład:

[ ( ] )

lub

[ [ [ [(((( ] ] ] ]))))(([ ))(([ ))([ )( ])( ])( ])

Fakt, że język ten nie jest bezkontekstowy, można udowodnić za pomocą lematu o pompowaniu dla języków bezkontekstowych oraz dowodu przez sprzeczność, przy czym wszystkie słowa formy powinny należeć do języka. Język ten należy raczej do bardziej ogólnej klasy i można go opisać za pomocą gramatyki spójników , która z kolei obejmuje również inne języki nie bezkontekstowe, takie jak język wszystkich słów formy .

Regularne gramatyki

Każda zwykła gramatyka jest bezkontekstowa, ale nie wszystkie gramatyki bezkontekstowe są regularne. Na przykład poniższa gramatyka bezkontekstowa jest również regularna.

Sa
SaS
SbS

W tutaj zaciski są i B , podczas gdy tylko nieterminalowi jest S . Opisany język to wszystkie niepuste ciągi s i s, które kończą się na .

Ta gramatyka jest regularna : żadna reguła nie ma więcej niż jednego nieterminala po swojej prawej stronie, a każdy z tych nieterminali znajduje się na tym samym końcu po prawej stronie.

Każda gramatyka regularna odpowiada bezpośrednio niedeterministycznemu automatowi skończonemu , wiemy więc, że jest to język regularny .

Używając symboli kreski pionowej, powyższą gramatykę można opisać bardziej zwięźle w następujący sposób:

Sa | jako | bS

Pochodne i drzewa składniowe

Wyprowadzenie z ciągiem do gramatyki jest ciągiem zastosowań reguł gramatyki, które przekształcają się symbol startu do łańcucha. Wyprowadzenie dowodzi, że ciąg należy do języka gramatyki.

Wyprowadzenie jest w pełni określone przez podanie, dla każdego kroku:

  • zasada zastosowana w tym kroku
  • występowanie jego lewej strony, do której jest stosowany

Dla jasności zwykle podaje się również ciąg pośredni.

Na przykład za pomocą gramatyki:

  1. SS + S
  2. S → 1
  3. Sa

sznurek

1 + 1 +

można wyprowadzić z symbolu początkowego S z następującym wyprowadzeniem:

S
S + S (zgodnie z zasadą 1. na S )
S + S + S (zgodnie z zasadą 1. na drugim S )
→ 1 + S + S (zgodnie z zasadą 2. na pierwszym S )
→ 1 + 1 + S (zgodnie z zasadą 2. na drugim S )
→ 1 + 1 + a (zgodnie z zasadą 3. na trzecim S )

Często stosuje się strategię, która deterministycznie wybiera następny nieterminal do przepisania:

  • w najbardziej lewostronnej derywacji zawsze jest to najbardziej lewy nieterminal;
  • w najbardziej prawostronnym wyprowadzeniu jest zawsze najbardziej prawostronnym nieterminalem.

Przy takiej strategii wyprowadzenie jest całkowicie zdeterminowane kolejnością zastosowanych reguł. Na przykład jedną skrajną lewą derywacją tego samego ciągu jest

S
S + S (zgodnie z zasadą 1 po lewej stronie S )
→ 1 + S (zgodnie z zasadą 2 po lewej stronie S )
→ 1 + S + S (zgodnie z zasadą 1 po lewej stronie S )
→ 1 + 1 + S (zgodnie z zasadą 2 po lewej stronie S )
→ 1 + 1 + a (zgodnie z zasadą 3 po lewej stronie S ),

co można podsumować jako

Zasada nr 1
zasada 2
Zasada nr 1
zasada 2
zasada 3.

Jednym najbardziej prawym pochodnym jest:

S
S + S (zgodnie z zasadą 1 po prawej stronie S )
S + S + S (zgodnie z zasadą 1 po prawej stronie S )
S + S + a (zgodnie z zasadą 3 po prawej stronie S )
S + 1 + a (zgodnie z zasadą 2 po prawej stronie S )
→ 1 + 1 + a (zgodnie z zasadą 2 po prawej stronie S ),

co można podsumować jako

Zasada nr 1
Zasada nr 1
zasada 3
zasada 2
zasada 2.

Rozróżnienie między wyprowadzeniem skrajnym lewym i prawym jest ważne, ponieważ w większości parserów transformacja wejścia jest definiowana przez podanie fragmentu kodu dla każdej reguły gramatycznej, która jest wykonywana za każdym razem, gdy reguła jest stosowana. Dlatego ważne jest, aby wiedzieć, czy parser określa lewą, czy prawą derywację, ponieważ określa to kolejność wykonywania fragmentów kodu. Zobacz na przykład parsery LL i parsery LR .

Wyprowadzenie również narzuca w pewnym sensie strukturę hierarchiczną na wyprowadzony łańcuch. Na przykład, jeśli ciąg „1 + 1 + a” jest wyprowadzony zgodnie z wyprowadzeniem najbardziej od lewej opisanym powyżej, struktura ciągu będzie następująca:

{{1} S + {{1} S + { a } S } S } S

gdzie {...} S wskazuje podciąg rozpoznawany jako należący do S . Ta hierarchia może być również postrzegana jako drzewo:

Wyprowadzenie z prawej strony `1 + 1 + a`

To drzewo jest nazywane drzewem analizy lub „drzem składni konkretnej” ciągu, w przeciwieństwie do abstrakcyjnego drzewa składni . W tym przypadku przedstawione skrajnie lewe i prawe wyprowadzenia definiują to samo drzewo analizy; istnieje jednak inna najbardziej prawostronna derywacja tego samego ciągu

S
S + S (zgodnie z zasadą 1 po prawej stronie S )
S + a (zgodnie z zasadą 3 po prawej stronie S )
S + S + a (zgodnie z zasadą 1 po prawej stronie S )
S + 1 + a (zgodnie z zasadą 2 po prawej stronie S )
→ 1 + 1 + a (zgodnie z zasadą 2 po prawej stronie S ),

który definiuje ciąg o innej strukturze

{{{1} S + { a } S } S + { a } S } S

i inne drzewo analizy:

Skrajne wyprowadzenie `1 + 1 + a`

Zauważ jednak, że oba drzewa parsowania można uzyskać zarówno z lewej, jak i z prawej strony. Na przykład ostatnie drzewo można uzyskać z wyprowadzeniem najbardziej od lewej w następujący sposób:

S
S + S (zgodnie z zasadą 1 po lewej stronie S )
S + S + S (zgodnie z zasadą 1 po lewej stronie S )
→ 1 + S + S (zgodnie z zasadą 2 po lewej stronie S )
→ 1 + 1 + S (zgodnie z zasadą 2 po lewej stronie S )
→ 1 + 1 + a (zgodnie z zasadą 3 po lewej stronie S ),

Jeśli ciąg w języku gramatyki ma więcej niż jedno drzewo analizowania, mówi się, że gramatyka jest gramatyka niejednoznaczna . Takie gramatyki są zwykle trudne do przeanalizowania, ponieważ parser nie zawsze może zdecydować, którą regułę gramatyczną ma zastosować. Zwykle niejednoznaczność jest cechą gramatyki, a nie języka, i można znaleźć jednoznaczną gramatykę, która generuje ten sam język bezkontekstowy. Istnieją jednak pewne języki, które mogą być generowane tylko przez niejednoznaczne gramatyki; takie języki nazywane są językami z natury niejednoznacznymi .

Przykład: wyrażenia algebraiczne

Oto gramatyka bezkontekstowa dla poprawnych składniowo wyrażeń algebraicznych wrostkowych w zmiennych x, y i z:

  1. Sx
  2. Sy
  3. Sz
  4. SS + S
  5. SSS
  6. SS * S
  7. SS / S
  8. S → ( S )

Ta gramatyka może na przykład generować ciąg

( x + y ) * xz * y / ( x + x )

następująco:

S
SS (zgodnie z zasadą 5)
S * SS (zgodnie z zasadą 6, stosuje się do skrajnie lewej S )
S * SS / S (zgodnie z zasadą 7, stosuje się do skrajnego S )
→ ( S ) * SS / S (zgodnie z zasadą 8, stosuje się do skrajnie lewej S )
→ ( S ) * SS / ( S ) (zgodnie z zasadą 8, stosuje się do skrajnej prawej S )
→ ( S + S ) * SS / ( S ) (zgodnie z zasadą 4, stosuje się do skrajnie lewej S )
→ ( S + S ) * SS * S / ( S ) (zgodnie z zasadą 6, stosuje się do czwartego S )
→ ( S + S ) * SS * S / ( S + S ) (zgodnie z zasadą 4, stosuje się do skrajnie prawej S )
→ ( x + S ) * SS * S / ( S + S ) (itd.)
→ ( x + y ) * SS * S / ( S + S )
→ ( x + y ) * xS * S / ( S + S )
→ ( x + y ) * xz * S / ( S + S )
→ ( x + y ) * xz * y / ( S + S )
→ ( x + y ) * xz * y / ( x + S )
→ ( x + y ) * xz * y / ( x + x )

Zwróć uwagę, że dokonano wielu wyborów dotyczących tego, które przepisanie zostanie wykonane w następnej kolejności. Te wybory wyglądają dość arbitralnie. W rzeczywistości są, w tym sensie, że ostatecznie wygenerowany ciąg jest zawsze taki sam. Na przykład drugi i trzeci przepis przepisuje

S * SS (zgodnie z zasadą 6, stosuje się do skrajnie lewej S )
S * SS / S (zgodnie z zasadą 7, stosuje się do skrajnego S )

można to zrobić w odwrotnej kolejności:

SS / S (zgodnie z zasadą 7, stosuje się do skrajnej prawej S )
S * SS / S (zgodnie z zasadą 6, stosuje się do skrajnie lewej S )

Dokonano również wielu wyborów, według której reguła ma być stosowana do każdego wybranego S . Zmiana dokonanych wyborów, a nie tylko kolejności, w jakiej zostały wykonane, zwykle wpływa na to, który ciąg terminala pojawia się na końcu.

Przyjrzyjmy się temu bardziej szczegółowo. Rozważ drzewo analizy tego wyprowadzenia:

Przykładowe drzewo analizy

Zaczynając od góry, krok po kroku, S w drzewie jest rozszerzane, aż nie pozostanie już nierozwinięty S es (nieterminale). Wybranie innej kolejności rozwinięcia da inną derywację, ale to samo drzewo analizy. Drzewo analizy zmieni się tylko wtedy, gdy wybierzemy inną regułę do zastosowania w jakiejś pozycji w drzewie.

Ale czy inne drzewo analizy może nadal generować ten sam ciąg końcowy, który w tym przypadku jest ( x + y ) * xz * y / ( x + x ) ? Tak, dla tej konkretnej gramatyki jest to możliwe. Gramatyki z tą właściwością nazywane są niejednoznacznymi .

Na przykład x + y * z można utworzyć za pomocą tych dwóch różnych drzew analizy:

Dwa różne drzewa analizy z tego samego wejścia

Jednak język opisany przez tę gramatykę nie jest z natury niejednoznaczny: dla języka można podać alternatywną, jednoznaczną gramatykę, na przykład:

Tx
Ty
Tz
SS + T
SST
SS * T
SS / T
T → ( S )
ST ,

ponownie wybierając S jako symbol startu. Ta alternatywna gramatyka wygeneruje x + y * z z drzewem parsowania podobnym do lewego powyżej , tj. niejawnie zakładając skojarzenie ( x + y ) * z , które nie jest zgodne ze standardową kolejnością operacji . Można skonstruować bardziej rozbudowane, jednoznaczne i bezkontekstowe gramatyki, które tworzą drzewa analizowania, które przestrzegają wszystkich pożądanych reguł pierwszeństwa operatorów i asocjatywności.

Normalne formy

Każda gramatyka bezkontekstowa bez tworzenia ε ma równoważną gramatykę w postaci normalnej Chomsky'ego i gramatykę w postaci normalnej Greibacha . „Ekwiwalent” oznacza tutaj, że obie gramatyki generują ten sam język.

Szczególnie prosta forma reguł produkcji w gramatykach postaci normalnej Chomsky'ego ma implikacje zarówno teoretyczne, jak i praktyczne. Na przykład, mając gramatykę bezkontekstową, można użyć postaci normalnej Chomsky'ego do skonstruowania algorytmu wielomianowego , który decyduje, czy dany ciąg jest w języku reprezentowanym przez tę gramatykę, czy nie ( algorytm CYK ).

Właściwości zamknięcia

Języki bezkontekstowe są zamykane pod różnymi operacjami, to znaczy, jeśli języki K i L są bezkontekstowe, to jest to wynik następujących operacji:

Nie są one zamknięte pod ogólnym przecięciem (a więc ani pod dopełnieniem ) i ustawić różnicę.

Rozstrzygalne problemy

Poniżej przedstawiono kilka rozstrzygających problemów dotyczących gramatyk bezkontekstowych.

Rozbiór gramatyczny zdania

Problem parsowania, sprawdzania, czy dane słowo należy do języka podanego przez gramatykę bezkontekstową, jest rozstrzygalny przy użyciu jednego z algorytmów parsowania ogólnego przeznaczenia:

Leslie G. Valiant wykazał, że parsowanie bezkontekstowe dla gramatyk postaci normalnej Chomsky'ego można zredukować do mnożenia macierzy logicznej , dziedzicząc w ten sposób górną granicę złożoności O ( n 2.3728639 ). Odwrotnie, Lillian Lee pokazała, że mnożenie macierzy logicznej O ( n 3−ε ) jest redukowalne do parsowania O ( n 3−3ε ) CFG, ustanawiając w ten sposób pewnego rodzaju dolne ograniczenie dla tego ostatniego.

Osiągalność, produktywność, nieważność

Przykładowa gramatyka:
SBb | DW | Ee
BBb | b
CC
DBd | Cd | D
EEe

Symbol nieterminalny jest nazywany produktywnym lub generującym , jeśli istnieje wyprowadzenie jakiegoś łańcucha symboli końcowych. jest nazywany osiągalnym, jeśli istnieje wyprowadzenie niektórych łańcuchów symboli nieterminalnych i końcowych z symbolu startowego. nazywana jest bezużyteczną, jeśli jest nieosiągalna lub nieproduktywna. nazywa się nullable , jeśli istnieje wyprowadzenie . Reguła nazywa się ε-produkcją . Wyprowadzenie nazywa się cyklem .

Wiadomo, że algorytmy eliminują z danej gramatyki, nie zmieniając jej wygenerowanego języka,

  • nieproduktywne symbole,
  • nieosiągalne symbole,
  • ε-produkcje, z jednym możliwym wyjątkiem, oraz
  • cykle.

W szczególności alternatywę zawierającą bezużyteczny symbol nieterminalowy można usunąć z prawej strony reguły. Takie zasady i alternatywy nazywane są bezużytecznymi .

W przedstawionym przykładzie gramatyki nieterminal D jest nieosiągalny, a E jest nieproduktywne, podczas gdy CC powoduje cykl. Stąd pominięcie trzech ostatnich reguł nie zmienia języka generowanego przez gramatykę, ani pominięcie alternatyw "| Cc | Ee " z prawej strony reguły dla S .

Mówi się, że gramatyka bezkontekstowa jest właściwa, jeśli nie zawiera bezużytecznych symboli, ani produkcji ε, ani cykli. Łącząc powyższe algorytmy, każdą gramatykę bezkontekstową nie generującą ε można przekształcić w słabo równoważną właściwą.

Kontrola prawidłowości i LL( k )

Rozstrzyga się, czy dana gramatyka jest gramatykią regularną , a także czy jest to gramatyka LL( k ) dla danego k ≥0. Jeśli k nie jest podane, ten ostatni problem jest nierozstrzygnięty.

Biorąc pod uwagę język bezkontekstowy , nie można rozstrzygnąć, czy jest on regularny, ani czy jest to język LL( k ) dla danego k .

Pustka i skończoność

Istnieją algorytmy decydujące o tym, czy język danego języka bezkontekstowego jest pusty, a także skończony.

Nierozstrzygnięte problemy

Niektóre pytania, które są nierozstrzygnięte dla szerszych klas gramatyk, stają się rozstrzygalne dla gramatyk bezkontekstowych; np. problem pustki (czy gramatyka w ogóle generuje jakieś ciągi końcowe) jest nierozstrzygalny dla gramatyk kontekstowych , ale rozstrzygalny dla gramatyk bezkontekstowych.

Jednak wiele problemów jest nierozstrzygniętych nawet dla gramatyk bezkontekstowych. Przykłady to:

Uniwersalność

Czy dany CFG generuje język wszystkich ciągów znaków w alfabecie symboli terminali użytych w jego regułach?

Zmniejszenie tego problemu można wykazać na podstawie dobrze znanego nierozstrzygalnego problemu określania, czy maszyna Turinga akceptuje określone dane wejściowe ( problem zatrzymania ). Redukcja wykorzystuje koncepcję historii obliczeń , ciągu opisującego całe obliczenie maszyny Turinga . Można skonstruować CFG, który generuje wszystkie ciągi, które nie akceptują historii obliczeń dla określonej maszyny Turinga na określonym wejściu, a zatem zaakceptuje wszystkie ciągi tylko wtedy, gdy maszyna nie zaakceptuje tego wejścia.

Równość językowa

Czy biorąc pod uwagę dwa CFG, generują ten sam język?

Nierozstrzygalność tego problemu jest bezpośrednią konsekwencją poprzedniego: nie można nawet zdecydować, czy CFG jest równoważny z trywialnym CFG definiującym język wszystkich napisów.

Włączenie języka

Biorąc pod uwagę dwa CFG, czy pierwszy może wygenerować wszystkie ciągi, które może wygenerować drugi?

Gdyby ten problem był rozstrzygalny, to równość języków również mogłaby zostać rozstrzygnięta: dwie CFG G1 i G2 generują ten sam język, jeśli L(G1) jest podzbiorem L(G2) i L(G2) jest podzbiorem L(G1).

Będąc na niższym lub wyższym poziomie hierarchii Chomsky'ego

Korzystając z twierdzenia Greibacha można wykazać, że dwa następujące problemy są nierozstrzygalne:

Niejednoznaczność gramatyczna

Czy dane CFG są niejednoznaczne ?

Nierozstrzygalność tego problemu wynika z faktu, że gdyby istniał algorytm określania niejednoznaczności, to można by rozstrzygnąć problem korespondencji pocztowej , o którym wiadomo, że jest nierozstrzygalny.

Rozłączność językowa

Biorąc pod uwagę dwa CFG, czy istnieje jakiś ciąg, który można wyprowadzić z obu gramatyk?

Gdyby ten problem był rozstrzygalny, można by też rozstrzygnąć nierozstrzygalny problem z korespondencją pocztową : dane ciągi nad jakimś alfabetem , niech gramatyka składa się z reguły

;

gdzie oznacza odwrócony ciąg i nie występuje wśród ; i niech gramatyka składa się z reguły

;

Wtedy problem Post podany przez ma rozwiązanie wtedy i tylko wtedy, gdy i udostępnia ciąg, który można wyprowadzić.

Rozszerzenia

Oczywistym sposobem rozszerzenia bezkontekstowego formalizmu gramatycznego jest umożliwienie nieterminalom posiadania argumentów, których wartości są przekazywane w ramach reguł. Dzięki temu funkcje języka naturalnego, takie jak zgodność i odniesienie , oraz analogi języka programowania, takie jak prawidłowe użycie i definicja identyfikatorów, mogą być wyrażane w naturalny sposób. Np. możemy teraz łatwo wyrazić, że w zdaniach angielskich podmiot i czasownik muszą się zgadzać w liczbie. W informatyce Przykłady takiego podejścia obejmują umieszczają gramatyk , gramatyk atrybutów , indeksowane gramatyki i Van Wijngaarden dwupoziomowe gramatyk . Podobne rozszerzenia istnieją w językoznawstwie.

Szerszym kontekście wolne gramatyki (lub stałym elementem gramatyki prawo ) jest taka, w której po prawej stronie od zasad produkcji może być wyrażenie regularne nad terminalami i nieterminali gramatyki za. Rozszerzone gramatyki bezkontekstowe opisują dokładnie języki bezkontekstowe.

Innym rozszerzeniem jest umożliwienie pojawiania się dodatkowych symboli terminala po lewej stronie reguł, ograniczając ich zastosowanie. Daje to formalizm gramatyk kontekstowych .

Podklasy

Istnieje kilka ważnych podklas gramatyk bezkontekstowych:

Parsowanie LR rozszerza parsowanie LL w celu obsługi większego zakresu gramatyk; z kolei uogólnione parsowanie LR rozszerza parsowanie LR o obsługę dowolnych gramatyk bezkontekstowych. W gramatykach LL i gramatykach LR zasadniczo wykonuje odpowiednio parsowanie LL i parsowanie LR, podczas gdy w gramatykach niedeterministycznych jest tak wydajny, jak można się spodziewać. Chociaż parsowanie GLR zostało opracowane w latach 80-tych, wiele nowych definicji języka i generatorów parserów nadal opiera się na parsowaniu LL, LALR lub LR do dnia dzisiejszego.

Aplikacje językowe

Chomsky początkowo miał nadzieję na pokonanie ograniczeń gramatyk bezkontekstowych poprzez dodanie reguł transformacji .

Takie reguły są kolejnym standardowym narzędziem w językoznawstwie tradycyjnym; np. pasywacja w języku angielskim. Wiele gramatyki generatywnej poświęcono znalezieniu sposobów udoskonalenia opisowych mechanizmów gramatyki struktury fraz i reguł transformacji, tak aby można było wyrazić dokładnie takie rodzaje rzeczy, na jakie pozwala język naturalny. Zezwalanie na dowolne przekształcenia nie spełnia tego celu: są one zbyt potężne, ponieważ są kompletne pod względem Turinga, chyba że zostaną dodane znaczące ograniczenia (np. żadne przekształcenia, które wprowadzają, a następnie przepisują symbole w sposób bezkontekstowy).

Ogólne stanowisko Chomsky'ego dotyczące braku kontekstu bezkontekstowego języka naturalnego utrzymało się od tego czasu, chociaż jego konkretne przykłady dotyczące nieadekwatności gramatyk bezkontekstowych ze względu na ich słabą zdolność generatywną zostały później obalone. Gerald Gazdar i Geoffrey Pullum twierdzili, że pomimo kilku konstrukcji niebezkontekstowych w języku naturalnym (takich jak zależności między szeregami w szwajcarskim niemieckim i reduplikacja w Bambara ), zdecydowana większość form w języku naturalnym jest rzeczywiście bezkontekstowa.

Zobacz też

Bibliografia

Uwagi

Dalsza lektura

  • Hopcroft, John E .; Ullman, Jeffrey D. (1979), Wprowadzenie do teorii automatów, języków i obliczeń , Addison-Wesley. Rozdział 4: Gramatyki bezkontekstowe, s. 77-106; Rozdział 6: Właściwości języków bezkontekstowych, s. 125–137.
  • Sipser, Michael (1997), Wprowadzenie do teorii obliczeń , Wydawnictwo PWS, ISBN 978-0-534-94728-6. Rozdział 2: Gramatyki bezkontekstowe, s. 91–122; Sekcja 4.1.2: Rozstrzygalne problemy dotyczące języków bezkontekstowych, s. 156-159; Sekcja 5.1.1: Redukcje poprzez historie obliczeń: s. 176–183.
  • J. Berstel, L. Boasson (1990). Jan van Leeuwen (red.). Języki bezkontekstowe . Podręcznik informatyki teoretycznej. B . Elsevier. s. 59–102.

Zewnętrzne linki

  • Programiści komputerowi mogą uznać rozwiązanie wymiany stosu za przydatne.
  • CFG Developer stworzony przez Christophera Wonga na Uniwersytecie Stanforda w 2014 roku; zmodyfikowany przez Kevina Gibbonsa w 2015 roku.