2011-06-29 15 views
9

Jestem pod dużym wrażeniem DCG Prolog i jak szybko mogę wyprodukować wszystkie możliwe struktury, które pasują do konkretnej gramatyki.Prolog: Łączenie gramatyk DCG z innymi ograniczeniami

Ale chciałbym połączyć to wyszukiwanie z innymi ograniczeniami. Na przykład zdefiniuj złożoną gramatykę i poproś Prologa o wygenerowanie wszystkich zdań z nie więcej niż 10 wyrazami. Lub wszystkie zdania, które nie powtarzają tego samego słowa dwa razy.

Czy można dodać dodatkowe ograniczenia do gramatyki DCG? Czy zasadniczo muszę przetłumaczyć DCG z powrotem na normalne klauzule Prolog i zacząć je modyfikować?

Odpowiedz

8

Jeśli tylko chcesz zobaczyć wszystkie zdania, które są wytwarzane, jest bardzo wygodny w użyciu, co następuje:

?- length(Xs, N), phrase(mynonterminal, Xs). 

Oczywiście, że generuje wszystkie zdania. Jest to jednak bardzo przydatne i oszczędza czas na wymyślenie konkretnego limitu. Jeśli chcesz ograniczyć to dalej, dodaj cel between(0,10,N) z przodu.

Jeśli chcesz powiedzieć w gramatyce, że pewna nieterminalny powinny podjąć pewną długość, to najlepiej powiedzieć to wprost:

seq([]) --> []. 
seq([E|Es]) --> [E], seq(Es). 

a --> {length(Es,10)}, seq(Es), {phrase(mynonterminal,Es)}. 

Jeśli nadal nie jest zadowolony, to chcesz do wyrażenia przecięcia dwóch nie-terminali. Jest to równoznaczne z pytaniem o przecięcie dwóch języków bez kontekstu, co w ogólnym przypadku jest nierozstrzygalne. Ale o wiele wcześniej, będziesz miał problemy z zakończeniem. Więc mieć świadomość, że w tym, co następuje:

^(V0, Goal, V0, V) :- 
     call(Goal,V). 

^(V, Goal, V) :- 
    call(Goal). 

tak to zezwala teraz wyrazić przecięcie dwóch nie zacisków:

:- op(950, xfx, &). 

(NT1 & NT2) --> 
    call(Xs0^Xs^(phrase(NT1,Xs0,Xs),phrase(NT2,Xs0,Xs))). 

jest potrzebne tylko wtedy, gdy użytkownik nie korzysta library(lambda) następujący. Ale proszę, miejcie świadomość, że zakończenie jest tutaj bardzo kruche. W szczególności zakończenie pierwszego nieterminalnego niekoniecznie ogranicza drugi.

+0

Myślę, że wcześniejsza część tego, zajmująca się "seq", jest tym, czego potrzebuję (tj. Jeden nieterminal jest skończoną listą). Ale nie całkiem rozumiem, że może to zadziałać, ponieważ nie rozumiem. Czym jest "fraza" w tym pierwszym przykładzie? – interstar

+0

Zanim zrozumiesz definicję '(&) // 2', spróbuj zrozumieć, w jaki sposób DCG są kodowane w Prologu. Dobra książka na ten temat to Prolog i analiza naturalnego języka autorstwa Pereiry i Shiebera. http://www.mtome.com/Publications/PNLA/pnla.html (to nic nie kosztuje) – false

+0

Cześć nieprawda, dzięki za referencje do książki. Będzie użyteczne. W moim konkretnym przypadku, myślę, że twoje rozwiązanie "a -> {length (Es, 10)}, seq (Es), {phrase (mynonterminal, Es)}." wygląda prawie dokładnie to, co chcę. Po prostu nie rozumiem, co powinienem napisać w swoim programie tam, gdzie napisałeś "frazę".Widzę, że celem tej części jest powiedzenie, że sekwencja składa się z minynterminali. Ale czym jest to "wyrażenie"? – interstar

5

dobrze, zawsze można użyć {} i zapisywać wszelkiego rodzaju prolog orzecznika w między, na przykład:

foo(X)--> 
    { valid(X) }, 
    [a]. 
foo(X)--> 
    [b]. 

więc można dodać jakieś słowo licznika. oczywiście, jeśli każdy token jest słowem, możesz po prostu napisać coś w stylu: length (L, N), N < 11, start (L, []).

z drugiej strony, być może będzie lepiej, w zależności od złożoności ograniczeń, zakodować je w innej części. coś w rodzaju parser-> semantyczny checker w kompilatorach.

Powiązane problemy