rascal - 在具体的语法模式匹配中可以进行哪些操作?
问题描述
我正在尝试仅使用具体语法(无 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"
};
它不起作用。我也尝试使用列表,但没有成功。
是否有可能以某种方式创建
{Identifier "."}+
?还是转换list[Identifier]
成它?我怎样才能mapper( , toUpperCase)
实现{Identifier "."}+
?有没有办法将一些 str 变量直接插入到具体语法中?
在文档中,我发现 {Identifier "."}+ 如何转换为列表。但是在 {Identifier "."}+ 上是否有任何其他直接操作。以一种形式进行模式匹配会很好:
[ *Identifier firstIds, (Identifier)
someName
, *Identifier 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;
所以要把 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]);
同意这有点笨拙,我们可能应该优先考虑更简单的具体列表语法模板语法。我们也愿意接受改进建议。
推荐阅读
- javascript - 将 jquery $(this) 作为参数传递给点击事件
- scip - 使用 ug 和 soplex 解决 LP 问题
- c++ - 在 for 循环中使用引用作为迭代器
- spring-boot - Spring Boot 和 GlassFish
- java - 我如何在没有spring security的情况下使用spring boot + JPA进行简单登录
- python - 用 NaN 替换 'UN' 表示的值
- javascript - 角度动态表单添加嵌套表单数组
- python - 如何在 OpenCV for Python 中使用 OpenCL?
- local-storage - 读取 key 为对象的 localstorage
- android - 在 Wear 应用中创建的通知不会显示在 Android 智能手表上