具体的语法模式匹配可以进行哪些操作?

What operations are possible in concrete syntax pattern matching?

我正在尝试仅使用具体语法(无 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] 转换为它?如何在 {Identifier "."}+ 上达到 mapper( , toUpperCase)

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

  3. 在文档中我找到了如何将 {Identifier "."}+ 转换为列表。但是有没有其他直接操作{Identifier "."}+. 以一种形式进行模式匹配会很好: [ *标识符 firstIds, (标识符)<code>someName, *标识符 otherIds ]

首先是一些简短的回答让事情更清楚:

  • [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;

所以要将 list[Identifier] 变成 {Identifier "."} 你可以这样写:

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

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

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