2014-02-11 80 views
6

我想創建這樣的語言得到接受一個DCG:如何在Prolog中創建此DCG?

  • Ç
  • bbbcbbb
  • bbacbba
  • abacaba
  • aababacaababa

正如你可以看到這個手段有一個特定的順序a和b,然後是一個c,然後又是與c之前完全相同的順序。如果不符合這些條件,則將失敗。

我目前在這裏與我的做法(的作品,但也承認錯誤的話)

s --> x, s, x. 
s --> [c]. 
x --> [a]. 
x --> [b]. 

你們有人能幫我什麼,我需要改變嗎?我不知道如何繼續下去。非常感謝。

回答

5

DCG實際上只是一個Prolog程序,預處理添加了實現差異列表的隱藏參數。我們可以隨時添加我們自己的參數,並使用模式匹配。然後

s --> ab(X), [c], ab(X). 
ab([a|T]) --> [a], ab(T). 
ab([b|T]) --> [b], ab(T). 
ab([]) --> []. 

?- atom_chars(aababacaababa,Cs),phrase(s, Cs). 
Cs = [a, a, b, a, b, a, c, a, a|...] 
5

您所描述的語言既不規則也不是上下文無關。所以你需要使用DCG提供的Prolog擴展。有一些成語,你可能習慣:

% any sequence 

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

有了這個非終端,我們可以描述重複,並通過一個字符分隔的序列:

​​

這顯然是過於籠統。你只想要abc。現在您可以添加更多的要求:

rep(Seq, Sep) --> 
    seq(Seq), 
    {phrase(abs,Seq)}, 
    [Sep], 
    seq(Seq). 

abs --> [] | ("a"|"b"), abs. 

所以現在:

s --> 
    rep(_,c). 

另一種方法是「硬編碼」的語法,如@CapelliC顯示。使用seq//1使該方法更加靈活。

對於字符列表使用雙引號是非常方便的。 請參閱this answer如何允許使用雙引號表示字符列表。

+0

這個設計也很好地通過'phrase(s,L)產生解決方案。' – lurker

+0

@mbratch:這比運氣好多了。查看所有解的規範方法是「長度(L,N),短語(s,L)」。現在,他們也按長度排序。請參閱http://stackoverflow.com/questions/6524722/prolog-combining-dcg-grammars-with-other-restrictions/6525089#6525089 – false

+0

Lefty Gomez說:「我寧願比幸運更幸運。」 ;)但不管如何,上面的代碼按長度順序生成「a,b」序列並在移動到下一個長度之前完成每個長度的置換集合是一個很好的偶然事件。我仍然在學習很多DCG的細微差別,所以這和@ CapelliC的帖子對我來說都非常有啓發性。 – lurker