Skip to content Skip to sidebar Skip to footer

Replace Conditional Operator With If/else Automatically?

A specific JS parser (not in my control) does not understand nested conditional operator syntax like this: return num === 1 ? condition ? condition : something : something; Hence,

Solution 1:

How do I go about it? (A regexp for Textmate or similar would be helpful.

I don't think this is possible with regular expressions - you would need to parse the whole JS expression grammar with them. Of course you might use them to find appearances of ternary operators, but replacing them would need to be done by hand.

This is because conditional operators form expressions, while if/else structures are statements. That means you will need to lift the statement containing the ternary operator around the if-else. There are two solutions to transform the general

<some statement ( condition ? then-expression : else-expression) >

  1. if ( condition ) {

    <some statement then-expression>

    } else {

    <some statement else-expression>

    }

  2. var helper;

    if ( condition )

    helper = then-expression;

    else

    helper = else-expression;

    <some statement helper>

Which of them to choose depends on the complexity of the some statement (for your return-statement I'd opt for #1). And since the replacements bring their own syntax rules, you even might need to adapt the surrounding blocks. All this is not a trivial task, and imho could be automated only if you already had a parsed AST to transform.


Solution 2:

One idea would be to transform x ? y : z into (x && y) || z. You're still probably going to have to do some fairly fancy parsing to find the ternary operators, but at least you can leave them as expressions rather than statements which will mean the changes needed are much less extensive. Note however that there might be cases where these two things are not exactly equivalent (e.g. if y is 0) so use this approach with caution and only when you have some control over what code it will be applied to.

The idea of (x && y) || z is that when x is truthy, it evaluates to y, and when x is falsey, it evaluates to z. This works due to some edge-cases in the way that JavaScript handles short-circuiting for non-Boolean values. It's sort of a generalization of standard boolean arithmetic. Essentially, JavaScript will return the last value that it needed to inspect in order to perform the operation. So true && (stuff) returns stuff, whereas false && (stuff) returns false. Likewise true || (stuff) returns true, whereas false || (stuff) returns stuff.

There are two cases to check to show that (x && y) || z (mostly) does what we want:

Case 1: x is truthy

Since x is truthy, (true && y) || z evaluates to y || z. If y is also truthy, then this evaluates to y and we get our desired behavior. If y is not truthy, the operation fails and we get z instead!

Case 2: x is falsey

Since x is falsey, (false && y) || z evaluates to false || z, which in turn evaluates to z. Here we are lucky and always get the desired behavior regardless of y.

Example

Here's an example of the desired behavior in 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 where y is not truthy!

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

Post a Comment for "Replace Conditional Operator With If/else Automatically?"