Jak zauważyłeś, ludzie komunikują się między sobą w „naturalnym” języku, takim jak angielski, francuski, niemiecki. Nazywa się je naturalnymi, ponieważ naturalnie je nabywamy, a nie celowo je wymyślamy (wyjątek stanowi esperanto).
Język formalny to taki, który został wymyślony w jakimś celu. Język programowania, taki jak na przykład C, jest językiem formalnym wymyślonym w celu programowania komputerów.
Wszystkie języki można opisać za pomocą gramatyki. Hierarchię gramatyczną opisał Noam Chomsky w 1956 roku. Składa się z następujących poziomów:
Gramatyka typu 0 (gramatyka nieograniczona). Są najbardziej ogólne i odpowiadają maszynie Turinga. W związku z tym problem decydowania o tym, czy dany ciąg znaków jest częścią nieograniczonej gramatyki, jest nierozstrzygalny.
Gramatyki typu 1 (gramatyki kontekstowe). Prawie wszystkie języki naturalne, takie jak angielski, są wrażliwe na kontekst. Przykładem wrażliwości kontekstu w języku angielskim są dwa wyrażenia: „Czas leci jak strzała”. i „Owoce lecą jak banan”. Zasadniczo komputerom trudno jest zrozumieć języki kontekstowe.
Gramatyki typu 2 (bezkontekstowe). Języki bezkontekstowe są teoretyczną podstawą składni większości języków programowania.
Gramatyki typu 3 (gramatyki zwykłe). Rodzinę języków regularnych można uzyskać za pomocą wyrażeń regularnych. Zwykłe języki są powszechnie używane do definiowania wzorców wyszukiwania i struktury leksykalnej języków programowania.
Gramatyki typu 2 (bezkontekstowe) i typu 3 (zwykłe) są najczęściej obsługiwane przez komputery, ponieważ analizatory składni dla nich można skutecznie zaimplementować.
BNF (Backus Normal Form lub Backus – Naur Form) to technika notacji gramatyki bezkontekstowej, często używana do opisania składni języków używanych w informatyce.
Na przykład identyfikator można opisać jako:
<identifier> ::= <letter> { <letter> | <digit> }
co oznacza, że musi zaczynać się od litery i może zawierać dodatkowe litery lub cyfry.
Wcześniej litera jest definiowana jako „a” | „b” | „c” itp., a cyfra jest definiowana jako „0” do „9” przy użyciu tego samego rodzaju notacji.
Instrukcja AC „for” może być zdefiniowana jako:
<for_statement> ::=
'for' '(' <expression> ';' <expression> ';' <expression> ')' <statement>
Analizatory leksykalne i parsery (pierwsze etapy kompilatora lub interpretera) są następnie konstruowane w celu przyjęcia określonej gramatyki opisanej przez BNF dla określonego języka. Analizatory leksykalne są zwykle używane do oddzielania różnych tokenów języka (takich jak słowo kluczowe, identyfikator lub liczba), a analizator składni służy do ustalenia, w jaki sposób tokeny działają razem, na przykład w jaki sposób budowana jest instrukcja „for” .