Aby odpowiedzieć na zadane pytanie (bez nadmiernego powtarzania tego, co pojawia się w innych odpowiedziach)
Lexery i parsery nie różnią się bardzo, jak sugeruje przyjęta odpowiedź. Oba opierają się na prostych formalizmach językowych: zwykłych językach dla leksykalnych i prawie zawsze językach bezkontekstowych (CF) dla parserów. Oba są powiązane z dość prostymi modelami obliczeniowymi, automatem skończonym i automatem stosu push-down. Zwykłe języki to szczególny przypadek języków bezkontekstowych, dzięki czemu leksykon może być produkowany z nieco bardziej złożoną technologią CF. Ale to nie jest dobry pomysł z co najmniej dwóch powodów.
Podstawową kwestią w programowaniu jest to, że komponent systemu powinien być wyposażony w najbardziej odpowiednią technologię, aby można go było łatwo wyprodukować, zrozumieć i utrzymać. Technologia nie powinna być przesadna (przy użyciu technik o wiele bardziej złożonych i kosztownych niż jest to potrzebne), ani nie powinna być na granicy swoich możliwości, wymagając w związku z tym technicznych starań, aby osiągnąć zamierzony cel.
Dlatego „wydaje się modne nienawidzić wyrażeń regularnych”. Chociaż mogą wiele zrobić, czasem wymagają bardzo nieczytelnego kodowania, aby to osiągnąć, nie wspominając o tym, że różne rozszerzenia i ograniczenia w implementacji nieco zmniejszają ich teoretyczną prostotę. Lexery zwykle tego nie robią i są zwykle prostą, wydajną i odpowiednią technologią do parsowania tokena. Używanie parserów CF dla tokena byłoby przesadą, choć jest to możliwe.
Innym powodem, dla którego nie należy używać formalizmu CF dla leksykonów, jest to, że może być kuszące, aby użyć pełnej mocy CF. Ale może to powodować problemy strukturalne związane z czytaniem programów.
Zasadniczo większość struktury tekstu programu, z którego wyodrębnia się znaczenie, to struktura drzewa. Wyraża, w jaki sposób zdanie (program) parsowane jest generowane na podstawie reguł składniowych. Semantyka wyprowadzana jest za pomocą technik kompozytorskich (homomorfizm dla matematyki) ze sposobu, w jaki tworzone są reguły składniowe do budowania drzewa parsowania. Dlatego struktura drzewa jest niezbędna. Fakt, że tokeny są identyfikowane za pomocą leksykonu opartego na regularnym zestawie, nie zmienia sytuacji, ponieważ CF złożony z regularnym wciąż daje CF (mówię bardzo luźno o zwykłych przetwornikach, które przekształcają strumień znaków w strumień tokena).
Jednak CF skomponowany z CF (za pomocą przetworników CF ... przepraszam za matematykę), niekoniecznie daje CF i może sprawić, że rzeczy będą bardziej ogólne, ale mniej praktyczne. Tak więc CF nie jest odpowiednim narzędziem dla leksykonów, nawet jeśli można go użyć.
Jedną z głównych różnic między zwykłym a CF jest to, że zwykłe języki (i przetworniki) komponują się bardzo dobrze z prawie każdym formalizmem na różne sposoby, podczas gdy języki CF (i przetworniki) nie, nawet z sobą (z kilkoma wyjątkami).
(Należy pamiętać, że zwykłe przetworniki mogą mieć inne zastosowania, takie jak formalizacja niektórych technik obsługi błędów składniowych).
BNF to tylko specyficzna składnia do prezentacji gramatyki CF.
EBNF jest cukrem syntaktycznym dla BNF , wykorzystującym funkcje regularnego notowania w celu uzyskania lepszej wersji gramatyki BNF. Zawsze można go przekształcić w równoważny czysty BNF.
Jednak regularna notacja jest często używana w EBNF tylko w celu podkreślenia tych części składni, które odpowiadają strukturze elementów leksykalnych i powinny być rozpoznawane za pomocą leksera, podczas gdy pozostałe powinny być raczej przedstawione w prostym BNF. Ale to nie jest absolutna zasada.
Podsumowując, prostsza struktura tokena jest lepiej analizowana za pomocą prostszej technologii zwykłych języków, podczas gdy drzewna struktura języka (składni programu) jest lepiej obsługiwana przez gramatyki CF.
Sugerowałbym również przyjrzenie się odpowiedzi AHR .
Ale to pozostawia otwarte pytanie: dlaczego drzewa?
Drzewa są dobrą podstawą do określania składni, ponieważ
nadają tekstowi prostą strukturę
bardzo wygodne jest powiązanie semantyki z tekstem na podstawie tej struktury, z matematycznie dobrze rozumianą technologią (składanie przez homomorfizmy), jak wskazano powyżej. Jest to podstawowe narzędzie algebraiczne do definiowania semantyki formalizmów matematycznych.
Dlatego jest to dobra reprezentacja pośrednia, o czym świadczy sukces drzew abstrakcyjnych składni (AST). Należy zauważyć, że AST często różnią się od drzewa parsowania, ponieważ technologia analizy używana przez wielu specjalistów (takich jak LL lub LR) ma zastosowanie tylko do podzbioru gramatyki CF, wymuszając w ten sposób zniekształcenia gramatyczne, które są później korygowane w AST. Można tego uniknąć dzięki bardziej ogólnej technologii analizowania (opartej na programowaniu dynamicznym), która akceptuje dowolną gramatykę CF.
Oświadczenie o tym, że języki programowania są wrażliwe na kontekst (CS), a nie CF, są arbitralne i dyskusyjne.
Problem polega na tym, że rozdzielenie składni i semantyki jest arbitralne. Sprawdzanie deklaracji lub zgodności typów może być postrzegane jako część składni lub semantyka. To samo dotyczy zgodności płci i liczby w językach naturalnych. Są jednak języki naturalne, w których zgodność w liczbie mnogiej zależy od faktycznego znaczenia semantycznego słów, więc nie pasuje do składni.
Wiele definicji języków programowania w semantyce denotacyjnej umieszcza deklaracje i sprawdzanie typu w semantyce. Stwierdzenie, jak zrobiono to Ira Baxter, że parsery CF są hakowane w celu uzyskania czułości kontekstu wymaganej przez składnię, jest w najlepszym razie arbitralnym obrazem sytuacji. Może być zorganizowany jako hack w niektórych kompilatorach, ale nie musi tak być.
Nie tylko parsery CS (w znaczeniu używanym w innych odpowiedziach tutaj) są trudne do zbudowania i mniej wydajne. Nie są one również wystarczające do wyraźnego wyrażenia wrażliwości kontekstu, która może być potrzebna. I nie wytwarzają naturalnie struktury syntaktycznej (takiej jak drzewa parsowania), która jest wygodna do uzyskania semantyki programu, tj. Do wygenerowania skompilowanego kodu.