4

最近、私は Prolog で DCG を使って遊んでいますが、それがどのように機能するかについていくつかの問題に直面しています。たとえば、次の小さな文法があります。

<atom> :: <letter> <atom_part> | <letter>
<atom_part> :: <letter> | <digit> | <letter> <atom_part> | <digit> <atom_part>
<letter>:: 'a' | 'b' ... |'Z'
<digit> :: '0' |...|'9'

これは、私の間違いでなければ、文字で始まる必要がある文字または数字の文字列です。とにかく、それを解析しようとする私の試みは次のとおりです。

letter("a") --> "a".
number(X) --> number(X).
...
%etc
programme(I) --> atomm(I).
atomm(C) --> letter(Ch).
atomm(C) --> numb(Ch).
atomm((E)) --> atomm_part(E).
atomm_part(E1,E2) --> atomm(E1),!,atomm(E2).

ここで、最後の 2 行が間違っていることは明らかだと思います。これは、「再帰呼び出し」を行う方法がわからないため、パーサーが文字列の次の文字が数値か文字列かを再度確認するためです。どうすればこれを修正できますか? 前もって感謝します!

ところで、私はswi-prologを使用しています

4

1 に答える 1

3

あなたの文法は必要以上に複雑に思えます。'epsilon' を使用して単純化できます (空のプロダクション、DCG では[])。それとは別に、「プログラム」を仕様により忠実に保つ必要があります。

atom --> letter, atom_part | letter.
atom_part --> letter | digit | letter, atom_part | digit, atom_part.
letter --> "a" | "b" | /* omissis... */ "Z".
digit --> [D], {memberchk(D, "0123456789")}.

元の仕様とどれだけ似ているかがわかります。それと

?- phrase(atom, "a").
true ;
false.

?- phrase(atom, "3a").
false.

?- phrase(atom, "a3").
true ;
false.

letterdigit単一の文字を照合するさまざまな方法を示します。digitコードで行うように、入力から値をキャプチャする必要がある場合は、より簡単です。ただし、26*2 文字を列挙するとエラーが発生しやすいため、code_type /2の使用を検討してください。

atom(A) --> letter(L), atom_part(P), {A=[L|P]} | letter(L), {A=[L]}.
atom_part(P) --> letter(L), {P=[L]} | digit(D), {P=[D]} | letter(L), atom_part(A), {P=[L|A]} | digit(D), atom_part(A), {P=[D|A]}.
letter(L) --> [L], {code_type(L, alpha)}.
digit(D) --> [D], {memberchk(D, "0123456789")}.

また、通常、Prolog の代替はこの方法でエンコードされていることも考慮してください。

atom([L|P]) --> letter(L), atom_part(P).
atom([L]) --> letter(L).

より単純な形式では、ヘッド パターンで「データ構造」を移動できます。

于 2013-01-06T13:31:06.910 に答える