0

I'm struggling to get a javascript regex to work on some edge cases.

The goal is to take a string with some js code and rewrite a function, using the original arguments. A simple case is: 'apples("a", 1, {value: 2})' would become 'bananas("a", 1, {value: 2})'.

However it's a bit more complicated when you deal with real code. For example replacing a function for a "promisified" version of that function with nested functions, and return statements, and multiline objects:

string = 'function(){
  return Request({
    json:true,
    url: "http://google.com"
    method: "GET"
  })
}'

In this case the result I expect is:

string = 'function(){
  return newPromiseFunction({
    json:true,
    url: "http://google.com"
    method: "GET"
  }).then(function( res ){ console.log(res) })
}'

So my best attempt is:

var substring = string.match(/\return\sRequest+\(.+?\)/g );
var argsString = substring[0].match( /\((.*?)\)/ );
var result  = 'return newPromiseFunction('+ argsString + ').then(function( res ){ console.log(res) })}'

However this code only works if there are no line breaks nor tabs in the argument. But a multiline object (as above) will fail.

Is there a simple fix to my regex above? Is there a simpler way to do it? Is regex even the best way to approach this?

8
  • 1
    Why are you trying to parse code as strings? Commented Jun 24, 2016 at 18:23
  • 1
    Regex is not powerful enough to parse JavaScript code in general. If you have a very specific set of strings that you need to replace, you may be able to use regex. If you want to use regex you're going to have to say what all your cases are specifically. Commented Jun 24, 2016 at 18:25
  • 2
    There are several JavaScript parsers out there already which are complete -- dealing with the Abstract Symbol Tree (AST) might be easier than parsing yourself. Here is one: github.com/ternjs/acorn Commented Jun 24, 2016 at 18:26
  • @MikeMcCaughan I have a database of js code that is stored as strings, and some manipulation needs to be done on these strings. I thought dealing with AST was too heavy for this case, but perhaps that's the best way. Commented Jun 24, 2016 at 18:39
  • 2
    Could you give some context in your question? Maybe there are other solutions. What will you do with the modified JS string? Will you execute it, or just write it back to the database? Do all JS strings represent functions, in the sense that they are of the format function .... (...) { ... }? Or what else is common to all of them? Commented Jun 24, 2016 at 20:19

2 Answers 2

2

This seems to work :

var codestring = `function(){ 
   return Request({  
    json:true,  
    url: "http://google.com" 
    method: "GET" 
  }) 
}`;

var reg = /return\s+Request\((\{[\S\s]*?\})\)/g;
var result = codestring.replace(reg, "return newPromiseFunction($1).then(function( res ){ console.log(res) })");

alert(result);

Note that back-ticks were used to create a multiline string for the codestring.
Might need to change that if your parser isn't ES6 ready.

And instead of a match & string concatination, it's now an instant replace.
But that's just a choice really. The other method can be used instead with same result.

Also, [\S\s]*? was used instead of .*? because . doesn't cover the linebreaks.

Sign up to request clarification or add additional context in comments.

Comments

2

Here you are:

var code = `function() {
  return Request({
    json: true,
    url: "http://google.com"
    method: "GET"
  });
}`

var result = code.replace(/return\s+Request\s*\(([^\)]*)\)/g,
  (m, g1) => 'return newPromiseFunction('+ g1 + ').then(function( res ){ console.log(res) })}'
);

logs.innerText = result;
<pre id="logs"></pre>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.