在C+中列出函数的参数+;使用javascript正则表达式

在C+中列出函数的参数+;使用javascript正则表达式,javascript,c++,regex,Javascript,C++,Regex,我正在使用javascript解析使用doxygen生成的文档 我要匹配的函数可能具有以下签名: funcName(type1*param1,const myNamespace::type2 param2,myNamespace::type3 param3) 参数的数量可能会有所不同,我希望得到以下输出(或类似输出): [type1,const myNamespace::type2,myNamespace::type3] 注意:我不想知道它是指针还是引用 到目前为止,我已经尝试过了: var s

我正在使用javascript解析使用doxygen生成的文档

我要匹配的函数可能具有以下签名:
funcName(type1*param1,const myNamespace::type2 param2,myNamespace::type3 param3)

参数的数量可能会有所不同,我希望得到以下输出(或类似输出):
[type1,const myNamespace::type2,myNamespace::type3]

注意:我不想知道它是指针还是引用

到目前为止,我已经尝试过了:

var signature = "funcName (type1 * param1, const myNamespace::type2 param2, myNamespace::type3 param3)";
/(?:.*?)\((?:((?:const\s)?(?:\w+\:\:)?\w+)(?:.*?,\s)?)+/g.exec(signature);
但这只给出了函数中的最后一个类型,或者更准确地说:
[“funcName(type1*param1,const myNamespace::type2 param2,myNamespace::type3”,“myNamespace::type3”]

我相信我对非贪婪算子和非捕获群的广泛使用可能是问题的根源,但我仍然无法解决这个问题


注意:一旦您隔离了签名,选项
/g
的使用似乎不会改变任何内容

var signature=“funcName(type1*param1,const myNamespace::type2 param2,myNamespace::type3 param3)”;
以下为您提供了参数:

var参数=/\(.*)/.exec(签名)[1];
现在,在一般情况下,您不能只
.split(“,”
它们,因为模板类型,例如
std::map

如果您说没有这样的模板类型,那么很简单:

var paramTypes=parameters.split(/\s*,\s*/).map(函数(i){
返回i.replace(/\s*[*&]*\s*\w+$/,“”);
});
结果:

[“类型1”、“常量myNamespace::类型2”、“myNamespace::类型3”]
让我们从结尾看一下
\s*[*&]*\s*\w+$
正则表达式:

  • $
    确保我们在最后
  • \w+
    与参数名称匹配
  • [*&]*
    匹配要删除的指针和引用限定符
  • \s*
    匹配中间可能的空格
此匹配将替换为空字符串,因此只剩下类型名称


现在,为了一些有趣的事情,让我们考虑一下讨厌的情况:

var signature=“funcName(int-param1,const-std::map¶m2,std::map¶m3)”;
这仍然适用于:

var参数=/\(.*)/.exec(签名)[1];
对于其余部分,我们需要一个状态机,它实际上是一个非常基本的解析器:

函数getArgTypes(签名){
var参数=/\(.*)/.exec(签名)[1],
结果=[],
级别=0,
re=/[^,]+|/g,
匹配,
currentParam=“”;
while(match=re.exec(参数)){
currentParam+=匹配[0];
开关(匹配[0]){
案例“”:
--水平;
打破
案例“,”:
如果(!级别){
result.push(currentParam.replace(/\s*[*&]*\s*\w+\s*,$/,“”)。trim();
currentParam=“”;
}
打破
}
}
currentParam=currentParam.trim();
如果(当前参数)
结果.推送(currentParam.replace(/\s*[*&]*\s*\w+\s*$/,“”);
返回结果;
}
结果:

[“int”、“const std::map”、“std::map”]
也没那么复杂:-)

[^,]+|.
regex执行标记化,这意味着它的目标是将文本的相关位分离为标记。请注意,
在这种特殊情况下实际上是
[,]
的缩写

对于本例,我们只对
标记感兴趣。其余部分可以粘在一起(例如,我们可以使用
std::map
,而无需像编译器那样将其拆分为
std
::
map

这将为我们提供以下代币:

int-param1
const-std::map
std::map


现在,处理这只是跟踪嵌套级别的问题。

std::vector
之类的东西怎么样?不是问题吗?没有模板,所有内容都包装在typedef中,但这可能确实是个问题。非常感谢!我现在意识到我的主要问题是尝试在单个正则表达式中完成所有内容(结果太复杂了)。切分信息也是一个有趣的策略。但出于我自己的好奇心……我想知道这是否可以在单个正则表达式中实现。@Xletor不是JavaScript,它的正则表达式引擎非常弱。但我在回答中添加了一点额外内容,以显示一些基本的解析:-)出色而深入的讨论,以及使用解析器的额外奖励+1。不是所有的事情都可以用正则表达式来完成,有些事情即使可以用正则表达式来完成,也能更好地解析。