2011-01-16 55 views
6

Tôi đang viết một trình dịch từ Lisp sang C và tôi gặp vấn đề với việc xử lý các chuỗi. Đây là một mã biến đổi hàm Lisp đơn nhất thành một hàm C tương đương:Lướt một danh sách các chuỗi trong Prolog

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

Bây giờ tôi muốn đọc bất kỳ số hàm nào và trả về dưới dạng một chuỗi. Trên đây funs là tốt nhất mà tôi có thể đưa ra, nhưng nó hoạt động như thế này:

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

Trong khi tôi muốn một cái gì đó như thế này:

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

để tôi có thể độc đáo swritef là vào một chương trình hoàn chỉnh , giữa #include s và chính(). Một giải pháp thay thế là sửa đổi trình dịch cấp cao nhất để xử lý danh sách. Nó trông giống như sau:

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

Làm cách nào để thực hiện một trong hai cách này? Tôi đang sử dụng SWI Prolog.

+0

Đối tượng đề cập Prolog, trong khi cơ thể của câu hỏi hỏi về bản dịch "Lisp to C". Giúp tôi phân loại những gì ở đây. Các đoạn mã trông hơi giống Prolog, có lẽ vì cú pháp DCG đặc biệt đang bị nhầm lẫn với cú pháp cơ bản hơn của Prolog cho các quy tắc. Trong khi dòng chủ đề hỏi về "một danh sách các chuỗi trong Prolog", có vẻ như phân tích các chuỗi có chứa mã Lisp có liên quan. Việc kết hợp một danh sách các chuỗi là một nhiệm vụ tương đối đơn giản trong Prolog. Ví dụ mẫu của bạn ** funs/2 ** gợi ý bạn muốn ném vào một vài ký tự dòng mới giữa ... – hardmath

+0

... chuỗi liên tiếp được ghép nối. Nếu đó là phạm vi của câu hỏi, tôi có thể trả lời nó, và chúng ta có thể phân loại sự nhầm lẫn của các cú pháp (nếu cần). – hardmath

+0

Lisp to C dịch là những gì chương trình hiện. Chương trình được viết bằng Prolog, sử dụng cú pháp DCG để dịch từng trường hợp. Hầu hết các mã parse Lisp được xác định trước, với đối số của chúng là mã C kết quả. Tôi muốn hai dòng mới giữa các chuỗi nối. Hy vọng là vậy. – Igor

Trả lời

4

Thiết dành cho bây giờ mục đích mà nó cần thiết, chúng ta hãy viết một vị Prolog rằng concatenates một danh sách các chuỗi thành một chuỗi, đặt một dòng mới đôi giữa mỗi cặp liên tiếp của chuỗi (nhưng không phải ở phần cuối của chuỗi đầu ra, đánh giá bằng ví dụ mà Jerry đã đăng).

SWI-Prolog Manual: Thông thường tôi sẽ đăng các liên kết "sâu" để the documentation, nhưng trang web SWI-Prolog sử dụng một phong cách của URL kích hoạt cross-site scripting (XSS) cảnh báo với nhiều trình duyệt/kết hợp Plugin . Vì vậy, thay vào đó tôi sẽ tham khảo hơn liên kết đến phần thích hợp.

Phần 4.22 Biểu diễn văn bản trong chuỗi nói (một phần), "Đối tượng chuỗi theo mặc định không có biểu diễn từ vựng và do đó chỉ có thể được tạo bằng cách sử dụng các biến vị ngữ bên dưới hoặc thông qua giao diện ngoại ngữ." Điều này có thể hơi khó hiểu vì SWI-Prolog viết các chuỗi như văn bản được trích dẫn kép, nhưng đọc văn bản được trích dẫn kép (theo mặc định) dưới dạng danh sách các mã ký tự.

Dưới đây là mã cho một vị rằng concatenates các chuỗi trong một danh sách, chèn một chuỗi tách ở giữa cặp chuỗi liên tiếp:

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

Lưu ý rằng chúng tôi đã xác định hai vị từ, strSepCat/3strSepCat/4. Trước đây được định nghĩa về mặt sau, một mẫu thiết kế điển hình trong Prolog giới thiệu một đối số bổ sung là một bộ tích lũy liên kết với đầu ra khi đệ quy hoàn tất. Kỹ thuật này thường hữu ích khi nhận định nghĩa tail recursive.

Để sử dụng vị strSepCat/3, chúng ta thường sẽ cần phải xây dựng các chuỗi phân cách với (các dãy thoát cho) hai dòng mới:

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

Kể từ chuỗi trong Prolog là thực sự danh sách các mã ký tự, bạn có thể sử dụng append ở một vị tùy chỉnh mà cũng chèn dòng mới:

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

Cách sử dụng:

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

funs (F, "(xác định (zero x) 0) (xác định (một n) 1)", []), concat_program (F, X). là sai. – Igor

+0

'F = [" dữ liệu * carzero (dữ liệu * l) {return (eq (xe (l), make_atom_int (0)));} "," dữ liệu * số không (dữ liệu * n) {return (eq (make_atom_int (0), n));} "], concat_program (F, X) .' hoạt động. Tôi không thể nhìn thấy những gì sai trong phần còn lại của mã của bạn kể từ khi bạn đã không đưa ra các ngữ pháp đầy đủ. –

+0

Ý tưởng chung là chính xác nhưng tôi nghi ngờ tiền đề "chuỗi trong Prolog thực sự là danh sách các mã ký tự" có thể bị lỗi cho việc triển khai Prolog được sử dụng. Xem phần thảo luận này cho các chuỗi SWI-Prolog và nối: http://www.sci.hkbu.edu.hk/scilab/doc/prolog/sec-3.20.html – hardmath

2

gì về việc sử dụng ký hiệu DCG để gắn thêm chuỗi?

concat([]) --> []. 
concat([List|Lists]) --> List, "\n\n", concat(Lists). 
Các vấn đề liên quan