2011-01-16 8 views
6

Ich schreibe einen Lisp zu C Übersetzer und ich habe ein Problem mit der Handhabung von Strings. Dies ist ein Code, der eine einstellige Lisp-Funktion auf einen C äquivalent transformiert:Eine Liste von Strings in Prolog einbetten

define(F) --> fun_unary(F), !. 

fun_unary(F) --> "(define (", label(Fun), spaces, label(Arg1), ")", spaces, expr(Body), ")", 
    {swritef(F, "data *%t(data *%t) { return(%t); }", [Fun, Arg1, Body])}, !. 


funs([F]) --> define(F), !. 
funs([F|Fs]) --> define(F), spaces, funs(Fs), !. 

Jetzt habe ich eine beliebige Anzahl von Funktionen lesen will und sie als einzelne Zeichenfolge zurück. Die obigen funs ist das Beste, was ich tun konnte, aber es funktioniert wie folgt:

?- funs(F, "(define (carzero l) (= (car l) 0)) (define (zero n) (= 0 n))", []). 
F = ["data *carzero(data *l) { return(eq(car(l), make_atom_int(0))); }", "data *zero(data *n) { return(eq(make_atom_int(0), n)); }"]. 

Während ich so etwas wie dies will:

F = "data *carzero(data *l) { return(eq(car(l), make_atom_int(0))); }\n\ndata *zero(data *n) { return(eq(make_atom_int(0), n)); }". 

damit ich schön swritef in ein komplettes Programm , zwischen #include s und main(). Eine alternative Lösung besteht darin, den Übersetzer der höchsten Ebene zu modifizieren, um die Liste zu bearbeiten. Es sieht derzeit so aus:

program(P) --> define(F), {swritef(P, "#include \"lisp2c.h\" \n\n%t \nint main() { return 0; }", [F])}, !. 

Wie würde ich eines dieser beiden tun? Ich benutze SWI Prolog.

+0

Die Betreffzeile erwähnt Prolog, während der Körper von die Frage fragt nach "Lisp to C" Übersetzung. Hilf mir, herauszufinden, was hier ist. Die Code-Snippets sehen ein wenig wie Prolog aus, vielleicht weil die spezielle DCG-Syntax mit Prologs einfacherer Syntax für Regeln verwechselt wird. Während die Betreffzeile nach "einer Liste von Strings in Prolog" fragt, scheint das Parsen von Strings, die Lisp-Code enthalten, beteiligt zu sein. Die Verkettung einer Liste von Strings ist eine relativ einfache Aufgabe in Prolog. Ihr Beispiel-Prädikat ** farts/2 ** schlägt vor, dass Sie ein paar Zeilenumbrüche zwischen ... – hardmath

+0

... einfügen möchten, die aufeinanderfolgende Strings verketten. Wenn das der Umfang der Frage ist, kann ich sie beantworten, und wir können die Verwirrung der Syntaxen (wenn nötig) aussortieren. – hardmath

+0

Lisp zu C Übersetzung ist, was das Programm tut. Das Programm ist in Prolog geschrieben und verwendet die DCG-Syntax, um einzelne Fälle zu übersetzen. Die meisten Prädikate analysieren Lisp-Code, wobei ihr Argument der resultierende C-Code ist. Ich möchte zwei Zeilenumbrüche zwischen verketteten Strings. Hoffe das ist es. – Igor

Antwort

4

Abgesehen jetzt den Zweck, für den sie gebraucht wird, werfen wir einen Prolog-Prädikat schreiben, die eine Liste von Zeichenketten in einer Zeichenfolge verkettet, ein Doppel Newline zwischen jedem aufeinanderfolgenden Paar Saiten platzieren (aber nicht am Ende die Ausgabe-Zeichenfolge, nach dem Beispiel, dass Jerry gepostet).

SWI-Prolog Handbuch: Normalerweise eine Art von URL, die mit Kombinationen vieler Browser/Plugin Cross-Site Scripting (XSS) Warnungen ausgelöst würde ich "tief" Links zu the documentation posten, aber die SWI-Prolog Seite nutzt . Also werde ich stattdessen auf den entsprechenden Abschnitt verweisen.

Abschnitt 4.22 Darstellen von Text in Strings sagt (teilweise), "String-Objekte haben standardmäßig keine lexikalische Darstellung und können daher nur mit den Prädikaten unterhalb oder über die Fremdsprache-Schnittstelle erstellt werden." Dies kann etwas verwirrend sein, da SWI-Prolog Strings als doppelt zitierten Text schreibt, aber doppelt zitierten Text (standardmäßig) als Liste von Zeichencodes liest.

Hier Code für ein Prädikat, das die Zeichenfolge in einer Liste verkettet, zwischen aufeinander folgenden String-Paaren einer anderen Zeichenfolge Separators einfügen:

strSepCat([ ],_,Empty) :- 
    string_to_list(Empty,[ ]). 
strSepCat([H|T],Separator,StrCat) :- 
    strSepCat(T,Separator,H,StrCat). 

strSepCat([ ],_,StrCat,StrCat). 
strSepCat([H|T],Sep,Str,Cat) :- 
    string_concat(Sep,H,SepH), 
    string_concat(Str,SepH,StrSepH), 
    strSepCat(T,Sep,StrSepH,Cat). 

Bitte beachte, dass wir zwei Prädikate definiert haben, strSepCat/3 und strSepCat/4. Ersteres ist in Bezug auf Letzteres definiert, ein typisches Entwurfsmuster in Prolog, das ein zusätzliches Argument einfügt, wie ein Akkumulator, der an eine Ausgabe bindet, wenn die Rekursion abgeschlossen ist. Eine solche Technik ist oft hilfreich, um eine tail recursive Definition zu erhalten.

zum Prädikat strSepCat/3, verwenden wir den Trenn-String mit dem allgemein zu konstruieren bräuchten zu (der Escape-Sequenz für) zwei Zeilenumbrüche:

?- funs(Fs,Lisp,[ ]), string_to_list(Sep,"\n\n"), strSepCat(Fs,Sep,CProg). 
1

Da Strings in Prolog sind wirklich Listen von Zeichencodes, Sie append in einem benutzerdefinierten Prädikat, das auch fügt die Zeilenumbrüche verwenden können:

concat_program([], ""). 
concat_program([L|Ls], Str) :- 
    concat_program(Ls, Str0), 
    append("\n\n", Str0, Str1), 
    append(L, Str1, Str). 

Verbrauch:

funs(Fs, Lisp, []), 
concat_program(Fs, P), 
write("#include ...\n"), 
writef(P). 
+0

Spaß (F, "(define (null x) 0) (definieren (one n) 1)", []), concat_program (F, X). ist falsch. – Igor

+0

'F = [" Daten * Carzero (Daten * l) {return (eq (Auto (l), make_atom_int (0)));} "," Daten * Null (Daten * n) {return (eq (make_atom_int (0), n));} ", concat_program (F, X)." Funktioniert. Ich kann nicht sehen, was im Rest deines Codes falsch ist, da du nicht die volle Grammatik angegeben hast. –

+0

Die allgemeine Idee ist richtig, aber ich vermute, die Prämisse "Zeichenfolgen in Prolog sind wirklich Listen von Zeichencodes" kann für die Prolog-Implementierung in Verwendung fehlerhaft sein. Siehe diese Diskussion für SWI-Prolog-Strings und Verkettung: http://www.sci.hkbu.edu.hk/scilab/doc/prolog/sec-3.20.html – hardmath

2

Was über die Verwendung von DCG-Notation zum Anhängen der Saiten?

concat([]) --> []. 
concat([List|Lists]) --> List, "\n\n", concat(Lists).