2011-01-16 15 views
6

Escribo un traductor de Lisp a C y tengo un problema con el manejo de cadenas. Este es un código que transforma una función Lisp unario a un equivalente de C:Concatenación de una lista de cadenas en 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), !. 

Ahora quiero leer cualquier número de funciones y devolverlos como una sola cadena. Lo anterior funs es lo mejor que podía llegar a, pero funciona de esta manera:

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

Mientras yo quiero algo como esto:

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

para que pueda muy bien swritef está en un programa completo , entre #include sy principal(). Una solución alternativa es modificar el traductor de más alto nivel para manejar la lista. Ciertamente se ve así:

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

¿Cómo podría hacer cualquiera de estos dos? Estoy usando SWI Prolog.

+0

El sujeto menciona Prolog, mientras que el cuerpo de la pregunta se refiere a la traducción de "Lisp a C". Ayudame a resolver qué es lo que aquí. Los fragmentos de código se parecen un poco a Prolog, tal vez porque la sintaxis DCG especial se confunde con la sintaxis más básica de Prolog para las reglas. Mientras que el asunto pregunta acerca de "una lista de cadenas en Prolog", parece que está involucrado el análisis de cadenas que contienen código Lisp. La concatenación de una lista de cadenas es una tarea relativamente simple en Prolog. Su predicado de ejemplo ** funs/2 ** sugiere que desea agregar un par de caracteres de línea nueva entre ... – hardmath

+0

... cadenas consecutivas que se concatenan. Si ese es el alcance de la pregunta, puedo responderla, y podemos resolver la confusión de sintaxis (si es necesario). – hardmath

+0

La traducción de Lisp a C es lo que hace el programa. El programa está escrito en Prolog, usando la sintaxis DCG para traducir casos individuales. La mayor parte del código Lisp analizado predicado, siendo su argumento el código C resultante. Quiero dos nuevas líneas entre cadenas concatenadas. Espero que sea eso. – Igor

Respuesta

4

Dejando a un lado por el momento la finalidad para la que se necesita, vamos a escribir un predicado Prolog que concatena una lista de cadenas en una cadena, la colocación de un doble salto de línea entre cada par consecutivo de cadenas (pero no al final de la cadena de salida, a juzgar por el ejemplo que publicó Jerry).

Manual

SWI-Prolog: Normalmente que había puesto vínculos "profundos" a the documentation, pero el sitio SWI-Prolog utiliza un estilo de dirección URL que desencadena cross-site scripting (XSS) advertencias con muchas combinaciones de navegador/plugin . Entonces, en su lugar, haré referencia a un enlace a la sección correspondiente.

Sección 4.22 Representar texto en cadenas dice (en parte), "Los objetos String de forma predeterminada no tienen representación léxica y por lo tanto solo se pueden crear usando los predicados siguientes oa través de la interfaz de idioma extranjero." Esto puede ser un poco confuso, ya que SWI-Prolog escribe cadenas como texto de doble cita, pero lee texto de doble cita (por defecto) como listas de códigos de caracteres.

Aquí es código para un predicado que concatena las cadenas en una lista, la inserción de otra cadena separador entre pares de cadenas consecutivas:

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

Nota que hemos definido dos predicados, strSepCat/3 y strSepCat/4. El primero se define en términos de este último, un patrón de diseño típico en Prolog que introduce un argumento adicional como un acumulador que se une a un resultado cuando se completa la recursión. Tal técnica a menudo es útil para obtener una definición de tail recursive.

utilizar el predicado strSepCat/3, generalmente nos tendríamos que construir la cadena de separador con (la secuencia de escape para) dos saltos de línea:

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

Desde cadenas en Prolog son realmente listas de códigos de caracteres, puede utilizar append en un predicado personalizado que también inserta los saltos de línea:

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

Uso:

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

funs (F, "(define (cero x) 0) (define (uno n) 1)", []), concat_program (F, X). Es falso. – Igor

+0

'F = [" data * carzero (data * l) {return (eq (coche (l), make_atom_int (0)))}}, "data * zero (data * n) {return (eq (make_atom_int (0), n));} "], concat_program (F, X) .' funciona. No puedo ver lo que está mal en el resto de tu código ya que no has dado la gramática completa. –

+0

La idea general es correcta, pero sospecho que la premisa "cadenas en Prolog son realmente listas de códigos de caracteres" puede ser incorrecta para la implementación de Prolog en uso. Vea esta discusión para las cadenas y la concatenación de SWI-Prolog: http://www.sci.hkbu.edu.hk/scilab/doc/prolog/sec-3.20.html – hardmath

2

Qué acerca del uso de la notación DCG para agregar las cuerdas?

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