それらを楽しんでいるという理由だけで、私は定節文法 (DCG) に傾倒するでしょう。次に、ステートメントを作成して、かなり簡単に解析できます。
word(Word) --> [Word].
statement(Statement) -->
word(Thing), [is], word(Category),
{ Statement =.. [Category, Thing] }.
ここで DCG で行われているトリックは、文法が差分リスト表現に変換されていることです。括弧内の部分は通常の Prolog コードです。その前後の部分は、リストのリテラル部分または他の文法規則として解釈されます。したがって、[単語] は 1 つのアトムに一致します。実際には、次のようにルールを記述できます。
statement(Statement) -->
[Thing, is, Category],
{ Statement =.. [Category, Thing] }.
同じ効果があり、おそらくもっと読みやすくなりますが、私は衒学的であることが好きです。=..
リストをファクトに、またはその逆に変換する の使用に特に注意してください(したがって、[fruit, apple]
になりますfruit(apple)
)。
DCG を使用した解析は非常に簡単です。次を使用しますphrase/2
。
?- phrase(statement(X), [apple,is,fruit]).
X = fruit(apple).
asserta
次に、これらの句を動的ストアに挿入するために使用できます。
input(Text) :-
phrase(statement(Statement), Text),
asserta(Statement).
例えば:
?- input([apple,is,fruit]).
true.
?- fruit(X).
X = apple.
これで、クエリを解析するための別の句を作成できます。
query(Query) -->
['Is'], word(Word), word(Category),
{ Query =.. [Category, Word] }.
とても似ています!繰り返しますが、必要に応じて、次の構文を使用できます。
query(Query) -->
['Is', Word, Category],
{ Query =.. [Category, Word] }.
ここで、両方の文法規則を 1 つの "文" 規則に結合する句を書きたいと思うかもしれません:
sentence(statement(S)) --> statement(S).
sentence(query(Q)) --> query(Q).
やってみて:
?- phrase(sentence(X), ['Is', apple, fruit]).
X = query(fruit(apple)).
?- phrase(sentence(X), [apple, 'is', fruit]).
X = statement(fruit(apple)) ;
解析されたファクトだけでなく、それがステートメントであるかクエリであるかを示すラッパーも取得することがわかります。ステートメントとクエリの代わりにこれを使用して解析し、次のinput
ように書き換えることができるようになりました。
input(Text) :-
phrase(sentence(S), Text), perform(S).
作業を処理するための補助を追加しました:
perform(statement(S)) :- asserta(S).
perform(query(Q)) :- Q.
これは、後で文法の抽象化を追加するときに便利です。各perform
句は異なる「文」タイプを処理するため、上記の解析を行い、以下の作業を処理します。そして今、多かれ少なかれ、あなたが望んでいたものを手に入れました:
?- input([apple,is,fruit]).
true ;
false.
?- input(['Is',apple,fruit]).
true.
?- input(['Is',banana,fruit]).
false.
ルールにカットを導入し、特別な出力で true/false を処理することで改善できますsentence
が、特に将来的に異なる構文を処理できるようにしたい場合は、これが私が行きたい方向だと思います。