首页 > 解决方案 > 在具体的语法模式匹配中可以进行哪些操作?

问题描述

我正在尝试仅使用具体语法(无 AST)重写 java 代码。下一个代码有效:

CompilationUnit rewritePackage(CompilationUnit input) = 
    visit(input) {
        case (PackageDeclaration) `package <{Identifier "."}+ N>;` => 
            (PackageDeclaration) `package <{Identifier "."}+ N>.<Identifier s>;`
            when s:= [Identifier] "othertest"
    };  

现在我想创建{Identifier "."}+以便将其插入到重写结果中:

CompilationUnit rewritePackage(CompilationUnit input) = 
    visit(input) {
        case (PackageDeclaration) `package <{Identifier "."}+ N>;` => 
            (PackageDeclaration) `package <{Identifier "."}+ NUpdated>;`
            when NUpdated := [{Identifier "."}+] "a1.b2"
    };

它不起作用。我也尝试使用列表,但没有成功。

  1. 是否有可能以某种方式创建{Identifier "."}+?还是转换list[Identifier]成它?我怎样才能mapper( , toUpperCase)实现{Identifier "."}+

  2. 有没有办法将一些 str 变量直接插入到具体语法中?

  3. 在文档中,我发现 {Identifier "."}+ 如何转换为列表。但是在 {Identifier "."}+ 上是否有任何其他直接操作。以一种形式进行模式匹配会很好: [ *Identifier firstIds, (Identifier)someName, *Identifier otherIds ]

标签: rascal

解决方案


首先是一些简短的答案,以使事情更清楚:

  • [NonTerminal] "string"符号的实现尚未完成。目前它只支持命名的非终端,例如[Identifiers] xxx. 这是一个已知的 TODO 并且它已经被跟踪为一个问题。
  • 目前还没有用于创建具体列表的简短语法。您必须使用循环或递归手动构造它们。目前的建议是:
  • 为语法中的列表引入一个非终结符名称,并且
  • 编写一个辅助函数来构造列表

要创建{Identifier "."}+列表,请使用如下的具体语法模式:

syntax Identifiers = {Identifier "."}+ elems;

private {Identifier "."}+ insert(Identifier first, {Identifier "."}+ tail) 
  = (Identifiers) `<Identifier first>.<{Identifier "."} tail>`.elems;

append 函数首先将列表包装在Identifiers非终结符中以便能够使用(..)..符号,然后使用该.elems字段投影出新的嵌套列表。你这样生成的语法树是静态正确的。与使用[..]..动态调用解析器的符号不同,此(..)..符号静态调用解析器并在运行时组合正确的树。

或者您可能想要连接两个标识符列表:

{Identifier "."}+ append({Identifier "."}+ prefix, {Identifier "."}+ postfix) 
      = (Identifiers) `<{Identifier "."} prefix>.<{Identifier "."}+ postfix>`.elems;

有时您想连接可能为空的子列表,这是允许的,并且.分隔符将被自动删除:

{Identifier "."}+ append({Identifier "."}+ prefix, {Identifier "."}* postfix) 
      = (Identifiers) `<{Identifier "."} prefix>.<{Identifier "."}* postfix>`.elems;

所以要把 alist[Identifier]变成 a{Identifier "."}你可以这样写:

{Identifier "."}+ identifiers([Identifier head]) = (Identifiers) `<Identifier head>`.elems;

{Identifier "."}+ identifiers([Identifier head, Identifier sec, *Identifier tail])
    = append(insert(head, identifiers([sec, *tail]);

同意这有点笨拙,我们可能应该优先考虑更简单的具体列表语法模板语法。我们也愿意接受改进建议。


推荐阅读