6

Lisp から C へのトランスレータを書いていますが、文字列の処理に問題があります。これは、単項 Lisp 関数を C の等価関数に変換するコードです。

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), !.

ここで、任意の数の関数を読み取り、それらを 1 つの文字列として返したいと考えています。上記funsは私が思いつくことができる最高のものですが、次のように機能します。

?- 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)); }"].

私はこのようなものが欲しいのですが:

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)); }".

s と main() のswritef間の完全なプログラムにうまく入ることができるように。#include別の解決策は、最上位レベルのトランスレータを変更してリストを処理することです。現在、次のようになっています。

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

これら2つのいずれかを行うにはどうすればよいですか?SWI プロローグを使用しています。

4

4 に答える 4

4

必要な目的はさておき、文字列のリストを 1 つの文字列に連結し、連続する文字列の各ペアの間に二重の改行を配置する Prolog 述語を書きましょう (ただし、出力文字列の最後ではありません。 Jerry が投稿した例)。

SWI-Prolog マニュアル:通常、ドキュメント への「深い」リンクを投稿しますが、SWI-Prolog サイトでは、多くのブラウザー/プラグインの組み合わせでクロスサイト スクリプティング (XSS) 警告をトリガーするスタイルの URL を使用しています。代わりに、適切なセクションへのリンクよりも参照します。

セクション 4.22 Representing text in strings は、(部分的に) 「文字列オブジェクトはデフォルトでは字句表現を持たないため、以下の述語を使用するか、外国語インターフェースを介してのみ作成できます」と述べています。SWI-Prolog は文字列を二重引用符で囲んだテキストとして書き込みますが、(デフォルトでは) 二重引用符で囲まれたテキストを文字コードのリストとして読み取るため、これは少し混乱する可能性があります。

リスト内の文字列を連結し、連続する文字列ペアの間に別の文字列 Separator を挿入する述語のコードを次に示します。

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).

strSepCat/3strSepCat/4という 2 つの述語を定義したことに注意してください。前者は、再帰が完了したときに出力にバインドするアキュムレータとして追加の引数を導入する Prolog の典型的な設計パターンである後者に関して定義されます。このような手法は、末尾再帰定義を取得するのに役立つことがよくあります。

述語strSepCat/3を使用するには、通常、2 つの改行 (のエスケープ シーケンス) を使用して区切り文字列を作成する必要があります。

?- funs(Fs,Lisp,[ ]), string_to_list(Sep,"\n\n"), strSepCat(Fs,Sep,CProg).
于 2011-01-18T22:09:11.490 に答える
2

文字列を追加するために DCG 表記を使用するのはどうですか?

concat([]) --> [].
concat([List|Lists]) --> List, "\n\n", concat(Lists).
于 2011-01-17T14:26:48.957 に答える
1

appendProlog の文字列は実際には文字コードのリストであるため、改行も挿入するカスタム述語で使用できます。

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

使用法:

funs(Fs, Lisp, []),
concat_program(Fs, P),
write("#include ...\n"),
writef(P).
于 2011-01-17T12:07:43.387 に答える