转换 Java 代码时在 Rascal 中保留空格

Preserving whitespace in Rascal when transforming Java code

我正在尝试向 Java 文件中的方法添加检测(例如记录一些信息)。我正在使用以下似乎最有效的 Rascal 代码:

import ParseTree;
import lang::java::\syntax::Java15;
// .. more imports

// project is a 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);
}

我 运行 有两个关于空白的问题,这两个问题可能无关。

我插入的代码行没有保留之前的空白。如果有一个制表符,它现在将被删除。对于紧跟在我插入的行和右大括号之后的行也是如此。我怎样才能 'capture' 我的模式中的空格?

转换前的示例(所有行都以制表符开头,第 2 行和第 3 行有两个):

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

转换后的例子:

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

关于空白的额外问题;如果文件以换行符结尾,parse 函数将抛出 ParseError 而没有更多细节。从原始源中删除此换行符将解决此问题,但我宁愿 'manually' 不必在解析之前修复代码。我怎样才能避免这个问题?

唉,用具体的模式捕获空白不是当前版本的 Rascal 的功能。我们曾经拥有它,但现在它又回到了 TODO 列表中。如果您有兴趣,我可以为您指出有关该主题的论文。所以现在你必须稍后处理这个“伤害”。

您可以在通用级别编写树到树的转换(参见 ParseTree.rsc),以修复转换后解析树中的缩进问题,或重新插入丢失的注释。这是关于匹配 Tree 数据类型和 appl 构造函数。 Tree 格式是 Rascal 解析树的一种反射形式,它允许任何类型的转换,包括空格和注释。

你说的解析错误是没有使用start非终结符造成的。如果您使用 parse(#start[CompilationUnit], ...),则接受 CompilationUnit 前后的空格和注释。