Xel*_*tor 2 javascript c++ regex
我正在使用 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);
Run Code Online (Sandbox Code Playgroud)
但这只给了我函数中的最后一个类型,或者更准确地说:
["funcName (type1 * param1, const myNamespace::type2 param2, myNamespace::type3", "myNamespace::type3"]
我相信我对非贪婪运算符和非捕获组的广泛使用可能是问题的根源,但我仍然无法解决那个问题......
注意:选项的使用/g似乎没有改变任何东西
隔离签名后:
var signature = "funcName (type1 * param1, const myNamespace::type2 param2, myNamespace::type3 param3)";
Run Code Online (Sandbox Code Playgroud)
以下为您提供参数:
var parameters = /\((.*)\)/.exec(signature)[1];
Run Code Online (Sandbox Code Playgroud)
现在,在一般情况下,您不能只是.split(",")它们,因为例如模板类型std::map<int, std::string>。
如果你说没有这样的模板类型,那么很简单:
var paramTypes = parameters.split(/\s*,\s*/).map(function(i) {
return i.replace(/\s*[*&]*\s*\w+$/, "");
});
Run Code Online (Sandbox Code Playgroud)
结果:
["type1", "const myNamespace::type2", "myNamespace::type3"]
Run Code Online (Sandbox Code Playgroud)
让我们\s*[*&]*\s*\w+$从最后看一下正则表达式:
$ 确保我们在最后\w+ 匹配参数名称[*&]* 匹配您想要去除的指针和引用限定符\s* 匹配之间可能的空格这个匹配被一个空字符串替换,所以只剩下类型名称。
现在,为了好玩,让我们考虑一个令人讨厌的案例:
var signature = "funcName (int param1, const std::map<int, std::string>& param2, std::map<int, std::map<int, double>>& param3)";
Run Code Online (Sandbox Code Playgroud)
这仍然成立:
var parameters = /\((.*)\)/.exec(signature)[1];
Run Code Online (Sandbox Code Playgroud)
剩下的,我们需要一个状态机,它真的是一个非常基本的解析器:
function getArgTypes(signature) {
var parameters = /\((.*)\)/.exec(signature)[1],
result = [],
level = 0,
re = /[^<>,]+|./g,
match,
currentParam = "";
while (match = re.exec(parameters)) {
currentParam += match[0];
switch (match[0]) {
case "<":
++level;
break;
case ">":
--level;
break;
case ",":
if (!level) {
result.push(currentParam.replace(/\s*[*&]*\s*\w+\s*,$/, "").trim());
currentParam = "";
}
break;
}
}
currentParam = currentParam.trim();
if (currentParam)
result.push(currentParam.replace(/\s*[*&]*\s*\w+\s*$/, ""));
return result;
}
Run Code Online (Sandbox Code Playgroud)
结果:
["int", "const std::map<int, std::string>", "std::map<int, std::map<int, double>>"]
Run Code Online (Sandbox Code Playgroud)
也没有那么复杂:-)
在[^<>,]+|.正则表达式进行符号化,这意味着它的目标是将文本的相关位分成令牌。请注意,在这种特殊情况下,这.实际上是一种简写[<>,]。
对于这个例子,我们只对<,>和,令牌感兴趣。其余的可以保持粘合在一起(std::map例如,我们可以使用它,无需std :: map像编译器那样将其分开。
这应该给我们以下令牌:
int param1 , const std::map < int , std::string > & param2 , std::map < int , std::map < int , double > > & param3
现在,处理这只是跟踪嵌套级别的问题。