我有以下命令:
/(?:this\.(\w+)\(([\s\S]*?)\))/g
它用于接受如下代码:
this.doSomething(foo, bar)
并将其替换为:
this.lookup('doSomething', [foo, bar])
对于该用例(最常见的用例),它正确工作,但如果在用例中使用this
,则不能工作:
this.doSomething(foo, bar, this.baz())
其结果是错误的:
this.lookup('doSomething', [foo, bar, this.baz(]))
应该是这样:
this.lookup('doSomething', [foo, bar, this.baz()])
这是第一个问题。它实际上应该像this.doSomething
一样被转换,所以最终的结果应该是:
this.lookup('doSomething', [foo, bar, this.lookup('baz', [])]);
基本上,我的regex假设来自this.baz()
的结束括号是this.doSomething()
的结束括号,并且也不递归地操作。这里我需要某种递归行为/控制。
我听说过xregexp,但我不知道它如何帮助我。它似乎也是真正的语言解析器可能是唯一的方法。我在那里经验不多,但我不怕弄脏我的手。像Esprima这样的工具能帮上忙吗?
最后,我希望在代码的构建步骤中做一些小的语言/语法更改,也就是完全像Babel那样。事实上我在利用巴贝尔。也许某种Babel插件是一种选择?
无论如何,我对quickfix技巧或更支持/健壮的语言解析技术都持开放态度。我也很好奇,这些问题通常是如何处理的。扫描整个输入和匹配的打开/关闭大括号/括号/等等,我想?
发布于 2015-12-05 11:32:53
下面是一个例子,说明如何使用Babel插件来完成这个任务:
var names = ['doSomething', 'baz'];
module.exports = function(context){
var t = context.types;
return {
visitor: {
CallExpression: function(path){
var callee = path.get('callee');
// Only process "this.*()" calls.
if (!callee.isMemberExpression() ||
!callee.get('object').isThisExpression() ||
!callee.get('property').isIdentifier()) return;
// Make sure the call is to one of your specific functions.
if (names.indexOf(path.node.callee.property.name) === -1) return;
// Build "this.lookup('<name>', [])".
path.replaceWith(t.callExpression(
t.memberExpression(t.thisExpression(), t.identifier('lookup')),
[
t.stringLiteral(path.node.callee.property.name),
t.arrayExpression(path.node.arguments),
]
));
}
}
};
}
例如,如果将其放到plugin.js
函数中,则可以创建一个.babelrc
配置文件,并确保./plugin.js
或指向它的任何路径都在plugins
数组中。
.babelrc
{
"presets": ['es2015'],
"plugins": ['./plugin']
}
https://stackoverflow.com/questions/34100079
复制