Old C Code Transmogrifier*
C, 206 205 bytes
(-1 thanks to ceilingcat)
The newlines are just here for readability.
c,d,q;f(char*s){for(char*S,*T,*t=s;c-63?q=0:q++,d=c<<8|*s,*s?
q>1&&(T=index(S="=/'()!<>-",*s))?t-=2,*s="#\\^[]|{}~"[T-S]:
d>*s&&(T=strstr(S=">:<>%<:%",&d))&&(c="][ }{ # "[T-S])&1?--t,*s=c:0:
0,*t++=c=*s++;);}
Modifies s
in place. Tested with GCC and clang on Fedora Workstation, x86, in 32-bit and 64-bit mode.
C is not exactly the best language for golfing here.
Retina, 65 bytes
T`-=/'()!<>?`~#\\^[]|{}_`\?\?[-=/'()!<>]
<:
[
:>
]
<%
{
>%
}
%:
#
Try it online! T
is a little awkward to use but still saves me 14 bytes.
JavaScript (ES6), 106 bytes
s=>[...'#\\^[]|{}~[]{}#'].map((c,i)=>s=s.split('<:<%%'[i-9]+':>%>:'[i-9]||'??'+"=/'()!<>-"[i]).join(c))&&s
How?
This is pretty straightforward.
We should note however that:
When i is less than 9, the expression
'<:<%%'[i-9] + ':>%>:'[i-9]
evaluates toundefined + undefined
which equalsNaN
(falsy as expected).When i is greater than or equal to 9, the expression
'??' + "=/'()!<>-"[i]
evaluates to"??" + undefined
which is coerced to the string"??undefined"
(truthy when we expect a falsy result).
That's why we must process the test in this order.
Test cases
let f =
s=>[...'#\\^[]|{}~[]{}#'].map((c,i)=>s=s.split('<:<%%'[i-9]+':>%>:'[i-9]||'??'+"=/'()!<>-"[i]).join(c))&&s
console.log(f(`if (true ??!??! false) {`)) // `if (true || false) {`
console.log(f(`??-arr.indexOf(n)`)) // `~arr.indexOf(n)`
console.log(f(`function f(??) { console.log('test??'); }`)) // `function f(] { console.log('test^); }`
console.log(f(`/* comment :> :) *??/`)) // `/* comment ] :) *\`
console.log(f(`%:What am I doing??!!??`)) // `#What am I doing|!??`
console.log(f(`??(??)??(??) <:-- not a palindrome`)) // `[][] [-- not a palindrome`
console.log(f(`??????????`)) // `??????????`
console.log(f(`int f(int??(??) a) ??< return a??(0??)??'a??(1??) + "??/n"; ??>`)) // `int f(int[] a) { return a[0]^a[1] + "\n"; }`
console.log(f(`??<:>??<%`)) // `{]{%`
console.log(f(`<:>`)) // `[>`
console.log(f(`<::>`)) // `[]`
console.log(f(`:>>`)) // `]>`
console.log(f(`#\^[]|{}~`)) // `#\^[]|{}~`
console.log(f(`: >`)) // `: >`