Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用平衡括号递归拆分R中的脚本_R_Regex - Fatal编程技术网

用平衡括号递归拆分R中的脚本

用平衡括号递归拆分R中的脚本,r,regex,R,Regex,有没有办法根据平衡括号将任何R脚本拆分为嵌套列表(控制嵌套深度) 即 将返回一个嵌套列表,其中包含两个子列表,这些子列表具有可完全计算的自包含部分 pcre(php)中有grep可以做到这一点,但R中似乎没有类似的功能。如果您可以使用Perl或pcre,您可以从这开始 ((\w*)\s*\(((?:(?>[^(){}]+)(?1))*)\{((?:(?>[^(){}]+)(?1))*)\} 就像我说的,每场比赛你只能得到外巢 它的工作方式是生成一个递归语言函数来解析 外部形式。 在该函数中,您

有没有办法根据平衡括号将任何R脚本拆分为嵌套列表(控制嵌套深度)

将返回一个嵌套列表,其中包含两个子列表,这些子列表具有可完全计算的自包含部分


pcre(php)中有grep可以做到这一点,但R中似乎没有类似的功能。

如果您可以使用Perl或pcre,您可以从这开始

((\w*)\s*\(((?:(?>[^(){}]+)(?1))*)\{((?:(?>[^(){}]+)(?1))*)\}

就像我说的,每场比赛你只能得到外巢

它的工作方式是生成一个递归语言函数来解析
外部形式。
在该函数中,您可以调用相同的函数来解析每个内部内容
(即核心)

伪码

function parse( core )
{
     if ( core =~ /regex/ )
     {
          // store the outer info
          if ( group2 matched )
          {
               // store group2 function name
               // then recurse the function core
               parse( group3 );
          }
          else
          if ( group4 matched )
          {
               // store info about the beginning of a block
               // then recurse the block core
               parse( group4 );
          }
          else
          if ( groupX matched )
               // Content
          else
               // Error, unwind
               return FALSE;
     }
     return TRUE;
}
当然还有更多内容,比如内容和错误处理。
既不是函数开始也不是块开始的内容。
或者,由不平衡文本引起的错误

这需要在正则表达式中进行额外的替换。
但是,如果要处理内容和错误,正则表达式应该比这里使用的更具结构

必须知道,在核心中,一切都必须考虑在内。
这包括内容和错误

我可以做,但这需要一些额外的努力,我没有时间

这应该让你开始

正则表达式解释

 (                             # (1 start), Recursion group
      ( \w* )                       # (2), Function name, optional
      \s* 
      \(                            # (
      (                             # (3 start), Function core
           (?:
                (?> [^(){}]+ )         # Not anything that starts recursion
             |  (?1)                   # or, recurse a core
           )*
      )                             # (3 end)
      \)                            # )
   |                              # or,
      \{                            # {
      (                             # (4 start), Block core
           (?:
                (?> [^(){}]+ )         # Not anything that starts recursion
             |  (?1)                   # or, recurse a core
           )*
      )                             # (4 end)
      \}                            # }
 )                             # (1 end)

事实证明,您可以用base R完成大部分工作。如果您想计算函数,您真的不应该使用正则表达式。您需要编写一个完整的R解析器

考虑以下事项 R脚本文件

any syntactical element of the R language

anyfunction = function(args){

  access any symbol constructed from any of the outer syntactical elements
  in enclosing scope and calculate something

  return result
}
如果函数访问文件中函数之外的任何内容,那么编写正则表达式来捕获函数将毫无用处。您还需要匹配它,并在评估函数之前使用R对其进行评估。这是一个自行编写的R解析器

~/test.R 这是要解析的代码的示例文件

v = c(1,2,3)
d = 1

increment = function(v, d) {
  sapply(v, function(v) v+d)

}

decrement = function(v, d) {
  increment(v,d)
  v-2*d
  increment2 = function(v, d) {
    v+d
  }
}
closure = function(){
  d
}
解析函数 这是从testfile解析函数的代码。它将测试文件中的表达式解析到一个环境中,以使您的命名空间不被云化,然后对它们求值并检查每个表达式的模式。然后将每个函数放入一个列表中,并可以按名称或索引调用。它将如图所示正确处理闭包,这是正则表达式方法所不能做到的

它只使用base R,因此对于R中的任何更新都是稳定的,这些更新不会从base中删除这些函数,并将处理最终的语法构造,如中缀声明的函数

既然可以使用R进行自身解析,为什么还要编写正则表达式解析器呢

env = new.env()
#to not pollute namespace

src.expression = parse(file='~/test.R')
#get expressions

eval(src.expression, envir = env)
#move expressions in to environment

src.modes = sapply(ls(env), function(exp) {
  mode(get(exp, envir = env))
  }
)

funs.idx = grepl("function", src.modes)

funs.names = names(src.modes[funs.idx])
funs = lapply(funs.names, function(fun) {
  get(fun, envir = env)
}
)
names(funs) = funs.names

funs[[2]](v=c(1,2,3), 1) == funs[["increment"]](v=c(1,2,3), 1)
#TRUE TRUE TRUE

funs$closure() == 1
#TRUE

不幸的是,我还没有解决如何递归地执行它。我们必须捕获每个函数中的封闭顶级变量和其他变量,并评估该环境中的嵌套函数,以保持标准R的行为。尽管封闭函数通常仅用于其封闭函数,但我想,我们可能有其原因。我还没有找到解析嵌套函数并将变量从函数保存到环境的好方法。不管它值多少钱,我希望这有助于你达到目的。

这可能无法用正则表达式在R中实现。它需要Perl、PCRE或dotnet中的递归功能(或平衡组)。即使使用递归,也有2个递归元素
({
。这不是假装的,因为这不仅需要递归正则表达式,还需要递归语言函数来提取嵌套内容。我已经做过很多次了。我会为其他人收费。试着用一个像样的解析器来做。perl是如何做到的?R正则表达式可以运行perl commandsparse将字符串转换为exp表达式;quote和bquote来计算解析的表达式;环境来控制变量的值。Strsplit或stringr库处理拆分脚本文件并将其转换为r字符串。您的意思是手动使用quote和bquote吗?Perl执行递归的方式,类似于
((?:(?:(?>[^(){}])+(?1))*\{(((((?>[^(){}])+)+)(?1))*\)
。正则表达式中的递归有效地匹配外部嵌套。您需要一个递归函数来解析每个连续的核心,直到到达绝对的内部核心。如下
(?xis-)(?:(?)([a-z]\w*)\s*(?)((?&core)|((?&core)|(((?&operators))|(((?&content))|()((?(DEFINE)((?(?)(((?&operators)(?))(?&content))|(((?&content)=(?)=(?)(?)(?)(?)\))+)(?(?>[?|])(?(?![a-z]\w*\s*\(|[()])+)
这可能比你能处理的要多。谢谢你的例子。你能粘贴你正在寻找的文件的脚本吗?这很有意义。注意
funs[[2]](v=c(1,2,3),1)==funs[[“increment”](v=c(1,2,3),1)
不返回任何内容,因此逻辑不求值。我再次尝试,并在codinggrounds online R parser上尝试。它在那里工作?它真的不应该是不同的R版本和平台的问题。你确定粘贴的所有内容都正确吗?你得到了什么准确的错误?lhs和rhs都是一个数字向量,由e元素组成同样的,所以你应该得到一个逻辑向量作为回报。你能再看一看,看看它看起来完全一样写?当然,文件名需要手动应用。是的。但要让它递归工作是一个挑战。我正在尝试使用as.list(body()。作为实现我的目标的更好方法,如果函数访问封闭文件作用域中的任何内容,您是否能够评估该函数?@LoveTäting-可能,如果您评估整个块,而不是全局块。在这里,您可以看到,如果按照上面的伪代码所述,在每个级别解析核心,结果会是什么。我只是移动了fu是的,因此您可以在任何级别进行计算,只需使用所需的捕获组文本即可。@LoveTäting-您可以在解析函数时始终存储函数文本,而
env = new.env()
#to not pollute namespace

src.expression = parse(file='~/test.R')
#get expressions

eval(src.expression, envir = env)
#move expressions in to environment

src.modes = sapply(ls(env), function(exp) {
  mode(get(exp, envir = env))
  }
)

funs.idx = grepl("function", src.modes)

funs.names = names(src.modes[funs.idx])
funs = lapply(funs.names, function(fun) {
  get(fun, envir = env)
}
)
names(funs) = funs.names

funs[[2]](v=c(1,2,3), 1) == funs[["increment"]](v=c(1,2,3), 1)
#TRUE TRUE TRUE

funs$closure() == 1
#TRUE