2011-06-29 20 views
9

Tôi rất ấn tượng với DCG của Prolog và tôi có thể nhanh chóng tạo ra tất cả các cấu trúc có thể phù hợp với một ngữ pháp cụ thể như thế nào.Prolog: Kết hợp các ngữ pháp DCG với các hạn chế khác

Nhưng tôi muốn kết hợp tìm kiếm này với các ràng buộc khác. Ví dụ, định nghĩa một ngữ pháp phức tạp và yêu cầu Prolog tạo tất cả các câu không quá 10 từ. Hoặc tất cả các câu không lặp lại cùng một từ hai lần.

Có thể thêm các ràng buộc bổ sung như thế này vào một ngữ pháp DCG không? Hay tôi về cơ bản phải dịch DCG lại thành các mệnh đề Prolog bình thường và bắt đầu sửa đổi chúng?

Trả lời

8

Nếu bạn chỉ muốn xem tất cả câu được tạo ra, nó rất thuận tiện để sử dụng như sau:

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

Dĩ nhiên mà tạo ra tất cả các câu. Nhưng nó rất hữu ích và nó giúp bạn tiết kiệm thời gian để suy nghĩ về một giới hạn cụ thể. Nếu bạn muốn hạn chế hơn nữa, hãy thêm mục tiêu between(0,10,N) ở phía trước.

Nếu bạn muốn nói trong một ngữ pháp, rằng một tổ chức phi cảng nhất định nên phải mất một thời gian nhất định, nó là tốt nhất để nói điều này một cách rõ ràng:

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

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

Nếu bạn vẫn không hài lòng, sau đó bạn muốn để thể hiện giao điểm của hai phi đầu cuối. Điều này tương đương với việc yêu cầu giao điểm của hai ngôn ngữ tự do ngữ cảnh mà trong trường hợp chung không thể giải quyết được. Nhưng sớm hơn nhiều, bạn sẽ gặp vấn đề với việc chấm dứt. Vì vậy, hãy nhận thức được rằng trong những gì sau:

:- op(950, xfx, &). 

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

Sau đây là chỉ cần thiết nếu bạn không sử dụng library(lambda):

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

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

Vì vậy, điều này cho phép bạn bây giờ để diễn tả giao điểm của hai phi thiết bị đầu cuối. Nhưng xin vui lòng, hãy lưu ý rằng chấm dứt là rất giòn ở đây. Đặc biệt, việc chấm dứt thiết bị đầu cuối không đầu cuối không nhất thiết giới hạn giây thứ hai.

+0

Tôi nghĩ rằng phần trước của điều này, đối phó với "seq", là những gì tôi cần (ví dụ: một nonterminal là một danh sách hữu hạn). Nhưng tôi không hoàn toàn nhận được nó để làm việc có lẽ vì tôi không hiểu. "Cụm từ" trong ví dụ đầu tiên là gì? – interstar

+0

Trước khi hiểu định nghĩa của '(&) // 2', hãy cố gắng hiểu cách DCG được mã hóa trong Prolog. Một cuốn sách hay về điều này là Prolog và phân tích ngôn ngữ tự nhiên của Pereira và Shieber. http://www.mtome.com/Publications/PNLA/pnla.html (miễn phí) – false

+0

Xin chào, cảm ơn vì đã tham khảo sách. Sẽ hữu ích. Về vấn đề cụ thể của tôi, tôi nghĩ giải pháp của bạn "a -> {length (Es, 10)}, seq (Es), {phrase (mynonterminal, Es)}." trông gần như chính xác những gì tôi muốn. Tôi chỉ không hiểu những gì, trong chương trình của tôi, tôi nên viết nơi bạn đã viết "cụm từ".Tôi có thể thấy mục đích của phần đó là để nói rằng trình tự được làm bằng mynonterminals. Nhưng chính cụm từ "cụm từ" đó là gì? – interstar

5

tốt, bạn luôn có thể sử dụng {} và viết bất kỳ loại ngữ prolog ở giữa, ví dụ:

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

vì vậy bạn có thể thêm một số loại từ quầy. tất nhiên, nếu mỗi mã thông báo là một từ bạn có thể chỉ cần viết một cái gì đó như: chiều dài (L, N), N < 11, bắt đầu (L, []).

mặt khác, có lẽ nó sẽ tốt hơn, tùy thuộc vào độ phức tạp của các ràng buộc, để mã hóa chúng ở một phần khác. một cái gì đó như parser-> kiểm tra ngữ nghĩa trong trình biên dịch.

Các vấn đề liên quan