Frage

Ich habe die angegebene kontextfreie Grammatik in die Datenbank eingelegt behaupten(....)Wenn die Grammatik so etwas ist wie

S-->a,S,b
S-->c

Diese Grammatik wird in die Datenbank eingefügt. Ich muss ein DCG schreiben, um Sätze für die CFG in der Datenbank zu generieren. Zum Beispiel, wenn ich das DCG auf diese Weise definiere mydcg ('s', str), das 'S'(nicht terminal) sollte genannt werden oder ersetzt durch Asb oder c | d oder so.

Das Problem ist, wie ich anrufen/ersetzen kann 'S' Durch Fakten aus der Datenbank wird jedes Mal, wenn ein Nicht -Terminal ('s') auftritt, um Sätze zu generieren.

Ich hoffe, Sie haben meine Frage verstanden, wenn nicht, werde ich versuchen, die Frage zu bearbeiten.


Unten (Beispielcode) ist das, was ich genau tun wollte. Dies ist nicht DCG.

myGrammar([], []):-!.

myGrammar([T|Rest], [T|Sentence]):-
          myGrammar(Rest, Sentence).

myGrammar([NT|Rest], Sentence):-
          grammar(NT, Rest1),
          append(Rest1,Rest, NewRest),
          myGrammar(NewRest, Sentence). 

Immer wenn ein Terminal angetroffen wird, sollte es ausgedruckt werden und wenn ein nicht terminal auftritt, wird es zurückverfolgen.

War es hilfreich?

Lösung

In Ihrem Prädikat mygrammar/2 Es gibt eine Liste von Nicht-Terminals und Terminals im ersten Argument und eine Liste von Terminals im zweiten. Es sollte wahrscheinlich erfolgreich sein, wenn das zweite Argument der Form der ersten ist. Was Sie hier also haben, ist im Wesentlichen ein Meta -Dolmetscher für DCGs. Ein paar Vorschläge:

Ihr Tokenizer produziert derzeit [grammar('S',[a,'S',b]),grammar('S',[....]),..]. Lass es produzieren [grammar('S',[t(a),nt('S'),t(b)]),grammar('S',[....]),..] stattdessen. Auf diese Weise ist es offensichtlich, was ein Terminal ist und was nicht terminal ist. Und, oh, entfernen Sie das!

myGrammar([], []).
myGrammar([t(T)|Rest], [T|Sentence]):-
   myGrammar(Rest, Sentence).
myGrammar([nt(NT)|Rest], Sentence):-
   grammar(NT, Rest1),
   append(Rest1,Rest, NewRest),
   myGrammar(NewRest, Sentence).

DCGs, übrigens sind etwas allgemeiner als dieser Dolmetscher.

Die tatsächliche Klassifizierung zwischen Nicht-Terminals und Terminals muss vom Tokenizer durchgeführt werden.

uppercasecode(C) :-
   between(0'A,0'Z,C).

lowercasecode(C) :-
   between(0'a,0'z,C).

Wenn Sie Zeichen verwenden (Ein-Charakter-Atome), werden Sie verwenden char_code(Char, Code) zwischen ihnen konvertieren.

Die volle Unicode -Unterstützung steckt noch in den Kinderschuhen. Es ist sehr schwierig, weil all diese besonderen Fälle für Charaktere wie ⓐ ⓐ, die obere Fall ist, aber immer noch nicht Teil einer Kennung sein kann. Aber hier ist, wie Sie es derzeit in SWI machen können.

uppercasecode(C) :-
   '$code_class'(C,upper),
   '$code_class'(C,id_start).

lowercasecode(C) :-
   '$code_class'(C,id_start),
   '$code_class'(C,id_continue),
   \+ '$code_class'(C,upper).

Update: In der Zwischenzeit gibt es char_type/2 und code_type/2 für diesen Zweck.

uppercasecode(C) :-
   code_class(C, upper),
   code_class(C, prolog_var_start).

Andere Tipps

Ich gehe davon aus, dass Sie kürzlich mit Prolog begonnen haben. Ja, Sie können Dinge in die Datenbank einleiten, aber dies ist nicht die übliche Sache, die Sie in erster Linie tun. Sie möchten diese Funktion viel später verwenden, wenn Sie sich mit der Basissprache sicher fühlen.

Was Sie normalerweise tun, ist, eine Grammatik in eine Datei wie zu schreiben myfirstgrammar.pl Laden Sie diese Datei dann in Ihr Prolog -System.

Bitte beziehen Sie sich auf Dieser jüngste Thread für Details zur Grammatik.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top