我正在翻译一种旧语言(FOCAL)的代码,它使用“()”作为函数参数和向量索引。 目标语言 (R) 也使用“( )”表示函数,但使用“[ ]”表示索引。
FOCAL 变量名称仅限于两个字符,至少在开始时,我假设所有函数名称都有 3 个或更多字符(对于所有内部函数都是如此)。 例如,字符串
" ab(c(kk)) ab(c(5)) sin(x) qr(g) exp(cos(qr)) exp(z) exp(cos(qr(3))) cos(y(3))) sin(3)"
应转换为
" ab[c[kk] ] ab[c[5] ] sin(x) qr[g] exp(cos(qr)) exp(z) exp(cos(qr[3] )) cos(y[3] )) sin(3)"
作为第一个镜头,我首先通过这个正则表达式(R 代码)运行输入来查找数字索引,
str1 <- gsub('([^a-z][a-z]{1,2})[(]([0-9]{1,})[)]' ,'\\1\\[\\2\\] ' , thestr)
接下来我寻找变量名称的索引
str2 <- gsub('([^a-z][a-z]{1,2})[(]([^)]{1,})[)]' ,'\\1\\[\\2\\] ' , str1)
只有当我在第二个正则表达式上递归时才会成功。 我希望有一种更干净的方法,最好是不需要重复操作的方法。
不清楚一般情况可能是什么,但如果我们修复
cos(y(3)))
中不平衡的括号,那么这适用于显示的输入。 它会在空白处中断输入,然后将 fix_parens
应用于每个组件。 它使用 getParseData
对输入进行标记,然后跟踪 parens
中的括号类型,它替换一两个字符名称及其匹配项后面的括号。 utils 包是 R 自带的,所以不需要安装。
library(utils)
fix_parens <- function(x) {
txt <- getParseData(parse(text = x))$text
txt <- txt[txt != ""]
out <- txt
paren <- c()
for(i in seq_along(txt)[-1]) {
if (nchar(txt[i-1]) %in% 1:2 && txt[i] == "(") {
paren <- c(paren, "]")
out[i] <- "["
} else if (txt[i] == "(") {
paren <- c(paren, ")")
} else if (txt[i] == ")") {
out[i] <- tail(paren, 1)
paren <- head(paren, -1)
}
}
paste0(out, collapse = "")
}
# same as in question except we fixed the unbalanced parentheses
inp <- " ab(c(kk)) ab(c(5)) sin(x) qr(g) exp(cos(qr)) exp(z) exp(cos(qr(3))) cos(y(3)) sin(3)"
s <- strsplit(inp, " +")[[1]]
s <- s[s != ""]
paste(unname(sapply(s, fix_parens)), collapse = " ")
## [1] "ab[c[kk]] ab[c[5]] sin(x) qr[g] exp(cos(qr)) exp(z) exp(cos(qr[3])) cos(y[3]) sin(3)"