es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Preservar los espacios en blanco en Rascal al transformar código Java.

Estoy tratando de agregar instrumentación (por ejemplo, registrar información) a los métodos en un archivo Java. Estoy utilizando el siguiente código de Rascal que parece funcionar en su mayoría:

import ParseTree;
import lang::java::\syntax::Java15;
// .. más importaciones

// project es una loc
M3 model = createM3FromEclipseProject(project);
set[loc] projectFiles = { file | file <- files(model)} ;

for (pFile <- projectFiles) {
    CompilationUnit cunit = parse(#CompilationUnit, pFile);

    cUnitNew = visit(cunit) { 
        case (MethodBody) `{<BlockStm* post>}` 
            => (MethodBody) `{
                'System.out.println(new Throwable().getStackTrace()[0]);
                '<BlockStm* post>
                '}
            `
    }

    writeFile(pFile, cUnitNew);
}

Me encuentro con dos problemas relacionados con el espacio en blanco, que podrían no estar relacionados.

La línea de código que estoy insertando no conserva el espacio en blanco que había antes. Si había un carácter de tabulación, ahora se eliminará. Lo mismo ocurre con la línea que sigue directamente a la línea que estoy insertando y la llave de cierre. ¿Cómo puedo “capturar” el espacio en blanco en mi patrón?

Ejemplo antes de la transformación (todas las líneas comienzan con un carácter de tabulación, las líneas 2 y 3 tienen dos):

void beforeFirst() throws Exception {
    rowIdx = -1;
    rowSource.beforeFirst();
}

Ejemplo después de la transformación:

void beforeFirst() throws Exception {

System.out.println(new Throwable().getStackTrace()[0]);
rowIdx = -1;
rowSource.beforeFirst();
}

Un problema adicional con respecto al espacio en blanco; si un archivo termina con un carácter de nueva línea, la función parse lanzará un error de análisis sin más detalles. Eliminar esta nueva línea del origen original solucionará el problema, pero preferiría no tener que solucionar el código “manualmente” antes de analizarlo. ¿Cómo puedo evitar este problema?

Tags:  ,

Answer

  1. Avatar for davy.ai

    Para capturar los espacios en blanco en el patrón, debes usar el no terminal <layout>. Este no terminal coincide con cualquier espacio en blanco, incluyendo saltos de línea, tabulaciones y espacios. Puedes insertarlo en las ubicaciones adecuadas de tu patrón para preservar el espacio en blanco original. Por ejemplo:

    case (MethodBody) `{<BlockStm* pre> <layout><BlockStm* post>}` 
            => (MethodBody) `{
            <BlockStm* pre>
            <layout>
            System.out.println(new Throwable().getStackTrace()[0]);
            <BlockStm* post>
            <layout>
            }`
    

    Para evitar el ParseError cuando un archivo termina con un carácter de nueva línea, puedes verificar si el último carácter del archivo es una nueva línea antes de analizarlo. Si lo es, puedes eliminarlo antes de analizarlo. Por ejemplo:

    if (file[locFileSize(pFile) - 1] == '\n') {
        file = |file[0, locFileSize(pFile) - 2]|;
    }
    CompilationUnit cunit = parse(#CompilationUnit, file);
    

    Este código verifica si el último carácter es una nueva línea y lo elimina al crear un nuevo valor file que excluye el último carácter. Luego, analiza el valor file modificado.

Comments are closed.