Raport Haskell zawiera nieco notoryczną klauzulę w regułach dotyczących layoutu o nazwie "parse-error(t)". Celem tej reguły jest uniknięcie zmuszania programisty do pisania nawiasów klamrowych w wyrażeniach jednowierszowych let
i podobnych sytuacjach. Odpowiedni zdanie brzmi:W jaki sposób kompilatory Haskell implementują w praktyce regułę parse-error (t)?
Warunkiem strona parse-error (t) należy interpretować w następujący sposób: jeśli tokeny generowane dotychczas przez L wraz z kolejnym tokenem t reprezentuje nieprawidłowy prefiks gramatyki Haskell, a żetony generowane do tej pory przez L, po którym następuje token "}" reprezentują poprawny przedrostek gramatyki Haskella, a następnie parsowanie-błąd (t) jest prawdziwe.
Stwarza to niezwykłą zależność, w której leksytarz musi zarówno generować tokeny dla analizatora składni, jak i reagować na błędy powstałe w parserze, wstawiając dodatkowe tokeny do użycia przez parser. W przeciwieństwie do niemal wszystkiego, co można znaleźć w dowolnej innej definicji języka, znacznie komplikuje implementację, jeśli jest interpretowana w 100% dosłownie.
Nie jest zaskakujące, że żaden kompilator Haskella, o którym wiem, nie implementuje całej reguły w formie pisemnej. Na przykład, GHC fails to parse the following expression, co jest legalne według raportu:
let x = 42 in x == 42 == True
Istnieje szeroka gama innych podobnych dziwnych przypadków. This post zawiera listę szczególnie trudnych przykładów. Niektóre z tych GHC działa poprawnie, ale również (od 7.10.1) nie powiedzie się na tym jednym:
e = case 1 of 1 -> 1 :: Int + 1
Ponadto wydaje się GHC ma nieudokumentowane przedłużenie język zwany AlternativeLayoutRule
zastępujący parsującej-błąd (t) klauzula ze stosem kontekstów tokena w lexer, który daje podobne wyniki w większości przypadków; nie jest to jednak zachowanie domyślne.
Co robią kompilatory Haskella w świecie rzeczywistym (w tym w szczególności GHC) w celu zbliżenia zasady parsowania błędów (t) podczas leksykowania? Jestem ciekawy, ponieważ próbuję zaimplementować prosty kompilator Haskella i ta reguła naprawdę mnie potknęła. (Patrz również this related question.)
Te dziwne przypadki, które pokazujesz, zostały zniesione w Haskell 2010 właśnie dlatego, że są nieuzasadnione do wdrożenia. Zauważ, że ten post pochodzi z 1999 roku. –
Właściwie teraz nie jestem pewien drugiego przykładu. Wygląda na to, że wyskakuje GHC nie dlatego, że nie obsługuje błędu parsowania, ale dlatego, że istnieje rozszerzenie składni, które sprawia, że '+ 'legal jest typu ... –
Aby zobaczyć, że GHC faktycznie * próbuje * wiernie implementować regułę, zauważ, że 'case 1 of 1 -> 1 :: Int :: Int' perfekcyjnie analizuje. –