2012-07-01 14 views
5

Próbuję przeanalizować język, w którym operatory mają atrybuty dynamiczne (priorytet i pierwszeństwo), używając parsera Menhir (podobnego do Ocamlyacc). Podczas fazy lekcji wszyscy operatorzy wypełniają token OP:string (więc "+" zmienia się w (OP "+") itd.).Określanie priorytetu i priorytetu dynamicznego dla operatora w Menhir/Ocamlyacc

Atrybuty operatora są określane w czasie analizy i wypełniają tabelę, w której znajdują się operatory i ich atrybuty. Biorąc pod uwagę tę tabelę, w jaki sposób mogę nakazać menhirowi dynamiczną zmianę priorytetu reguły parsującej operatorów na podstawie danych z tej tabeli?

Dzięki, CharlieP.

Odpowiedz

10

Przykro mi z powodu komentarza z komentarzem "robisz to źle". Mam trzy zastrzeżenia mam nadzieję są konstruktywne, w kolejności znaczenie maleje:

  1. Menhir nie jest przeznaczona dla aktualizacji dynamicznych gramatycznych; jeśli nalegasz na zmianę gramatyki w czasie parsetu, powinieneś użyć narzędzia udostępniającego tę funkcję, takiego jak parser GLR Dypgen. W podręczniku Dypgen wspomniano o możliwości dynamicznego aktualizowania priorytetów operatorów w ograniczonym zakresie (wydaje się, że można dodawać nowych operatorów i odpowiadające im priorytety, ale nie zmieniać priorytetu istniejących), które mogą, ale nie muszą odpowiadać twoim potrzebom. Zobacz rozdział 6.6 z Dypgen manual (PDF), strona ... 42.

  2. Dynamiczne aktualizowanie gramatyki CFG jest, jak sądzę, nie najlepszym sposobem radzenia sobie z priorytetami operatora zdefiniowanymi przez użytkownika. Agda ma bardzo ogólnych, zdefiniowanych przez użytkownika, operatorów mixfix, a ich rozwiązanie jest z grubsza następujące: użyj swojego parsera CFG do parsowania struktury gramatycznej, która jest statycznie znana, ale dla ekspresji, która może wykorzystywać fantazyjne cechy wstępne i skojarzenia, po prostu sparuj je na listę tokeny. Na przykład let x = if foo then x + y * z else bar zostanie przetworzony w coś takiego, jak Let(x, If(foo, Expr(x, +, y, *, z), bar). Późniejsza specjalistyczna przepustka może zebrać wymagane informacje, aby następnie przeanalizować je w węzłach Expr w ich wyspecjalizowanej strukturze. Używaj generatorów parsera do tego, do czego są one dobre (statycznie znana, bogata kombinacja CFG) i używaj przepustki do przetwarzania końcowego dla złożonych, źle zdefiniowanych, dynamicznych rzeczy. Faceci Agdy mają trochę literatury na ten temat, na przykład Parsing Mixfix Operators, Danielsson i Norell, 2009.

    Z punktu widzenia projektowania, zdecydowanie zachęcam do oddzielenia leksykowania i parsowania w kilku różnych przejściach, z których każdy dobrze - zdefiniowane i używane tylko informacje zebrane na poprzedniej strukturze, zamiast próbować dynamicznie zmieniać własne zachowanie. Będziesz mieć coś znacznie prostszego i znacznie solidniejszego.

  3. Dynamiczne lub zdefiniowane przez użytkownika pierwszeństwo i priorytety są, moim zdaniem, nieco złe. OCaml ma inny system, w którym priorytety pierwszeństwa operatorów są określane przez ich pierwsze kilka znaków (np. @, @@ i @+ są wszystkie skojarzenia prawe). Jest to nieco restrykcyjne dla osób wybierających operator infiksów, ale sprawia, że ​​kod czytelnik żyje o wiele bardziej komfortowo, ponieważ ma tylko jeden zestaw zasad gramatycznych do nauki, zamiast konieczności dynamicznego dostosowywania ich oczu do dowolnego nowego fragmentu kodu . Jeśli chcesz zezwolić na wstawianie dzikich, obcych fragmentów kodu z zupełnie inną składnią, mechanizmy cytowań (np. Camlp4 <:foo<...>>) są znacznie bardziej niezawodne niż manipulowanie przy asocjatywności i priorytetach na poziomie operatora, a także znacznie prostsze do analizowania.

    To powiedziawszy, projekty mają różne potrzeby i całkowicie zrozumiałbym, gdybyś nalegał na dynamiczną zmianę priorytetów operatorów i stowarzyszeń w przypadku niektórych aplikacji, o których nie wiem.Pamiętaj, że nie jest to jedyna droga, a czasami spójność i prostota są lepsze niż całkowita elastyczność.

Powiązane problemy