Replace conditional statement with if / else automatically?

The concrete JS parser (not in my control) doesn't understand nested conditional statement syntax like this:

return num === 1 ? condition ? condition : something : something;

      

Hence, I would like to replace all conditional statements (simple and nested) in the file with an if / else block . How should I do it? (It would be helpful to use a regex for Textmate or something similar.)

+3


source to share


2 answers


How should I do it? (It would be helpful to use a regex for Textmate or similar.

I don't think this is possible with regexes - you will need to parse the entire JS expression grammar with them. Of course, you can use them to find the occurrence of ternary operators, but their replacement will need to be done manually.

This is because conditional statements form expressions and if / else statements are statements. This means that you will need to drop the statement containing the ternary operator around the if-else. There are two solutions to convert common



<some operator (condition ?

then-expression :

else-expression)>

  • if (

    condition ) {

    <some then-expression>

    } else {

    <some else-expression statement>

    }

  • var helper;

    if (

    condition )

    helper =

    then-expression ;

    else

    helper =

    else-expression ;

    <some operator helper

    >

Which one to choose depends on the complexity of some operator (for your return

country, I would choose # 1). And since replacements bring their own syntax rules, you may even need to adapt the surrounding blocks. All this is not a trivial task and imho can only be automated if you have already parsed the AST for conversion.

+5


source


One idea would be to convert x ? y : z

to (x && y) || z

. You may have to do some pretty fancy parsing to find ternary operators, but at least you can leave them as expressions rather than statements, which means the changes needed are much less extensive. Note, however, that there may be cases where the two are not exactly equivalent (for example, if y

equal to 0), use this approach with caution and only when you have some control over which code it will be applied to.

The idea (x && y) || z

is that when x is true it calculates y, and when x is false it calculates z. This works because of some edges in the way JavaScript handles short-circuiting for non-boolean values. This is a kind of generalization of standard Boolean arithmetic. Basically, JavaScript will return the last value that needs to be checked to complete the operation. Therefore it true && (stuff)

returns stuff

, whereas it false && (stuff)

returns false

. Similarly, it true || (stuff)

returns true

, whereas it false || (stuff)

returns stuff

.

There are two cases to check that (x && y) || z

(basically) does what we want:

Case 1: x is true

Since x is true, (true && y) || z

evaluates to y || z

. If y is also true, then it evaluates to y and we get the desired behavior. If y is not truthful, the operation fails and we get z instead

Case 2: x is false



Since x is false, it (false && y) || z

evaluates to false || z

, which in turn evaluates to z

. Here we are in luck and always get the desired behavior regardless of y.

Example

Here is an example of the desired behavior on the chrome console:

> var x1 = "a" //truthy
> var x2 = "" //falsey
> var y = "y"
> var z = "z"
> (x1 && y) || z
"y"
> (x2 && y) || z
"z"

      

Just watch out for cases when y

not being truthful!

> var y2 = 0
> (x1 && y2) || z
"z"

      

+1


source







All Articles