g | x | w | all
Bytes Lang Time Link
nanPerl 5170809T171801ZXcali
071Haskell170809T172845ZWheat Wi
057Ruby170809T152043ZNnnes
121Java OpenJDK 8170810T203442ZOlivier
055JavaScript ES6170809T170017ZETHprodu
035CJam170809T164514ZPeter Ta
076Mathematica170809T152310ZJungHwan
082Python170809T150854ZUriel
043Retina170809T213742ZNeil
121PHP170809T213503Zhalfmang
073Javascript170809T165609Zasgallan
047Pyth170809T155917ZArnold P
084Python 2170809T160111ZErik the
021SOGL V0.12170809T151941Zdzaima

Perl 5, 54 50 + 1 (-p) = 51 bytes

s/\{(.)\}/$1/g while s/[a-z]\K[a-z]+/_{$&}^{$&}/ig

Try it online!

How?

The substitution in the while condition breaks occurrences of multiple letters in the first letter, followed by the rest in braces like this:

abc -> a_{bc}^{bc}

The while loop executes the substitution until no more multi-letter sequences remain. The substitution inside the loop removes braces from around single letters.

Haskell, 71 bytes

f[x,y]=x:'_':y:'^':y:[]
f(x:y@(_:_))=x:"_{"++f y++"}^{"++f y++"}"
f x=x

Try it online!

If we just had to output valid code the following would work for 44 bytes:

f[a]=[a]
f(a:b)=a:"_{"++f b++"}^{"++f b++"}"

Try it online!

Ruby, 76 73 72 68 67 57 bytes

Use of lambda saving 4 bytes thanks to Tutleman

f=->s{(r=s[1..-1])[0]?s[0]+?_+[r[1]??{+f[r]+?}:r]*2*?^:s}

Try it online!

Ungolfed:

def f(s)
  r = s[1..-1]
  if r.size > 0
    if r.size > 1
      x = "{" + f(r) + "}"
    else
      x = r
    end
    return s[0] + "_" + [x, x].join("^")
  else
    return s
  end
end

Java (OpenJDK 8), 121 bytes

s->{int l=s.length;String r=--l<0?"":""+s[l];for(;l-->0;)r="{"+s[l]+"_"+r+"^"+r+"}";return r.replaceAll("^\\{|\\}$","");}

Try it online!

JavaScript (ES6), 57 55 bytes

f=([c,...s])=>s+s?c+`_${p=s[1]?`{${f(s)}}`:s}^`+p:c||''

Θ(len(s)) complexity! According to @PeterTaylor, this is actually Θ(2^len(s)), which is still the best possible...

CJam (35 bytes)

MqW%{"^{ }_{ }"{AW$,)3e<#<},S/@*+}/

This is a full program. Online demo.

3 bytes work around a bug in the interpreter (see below).

Dissection

M            e# Start building from the empty string
qW%{         e# For each character in the reversed input
  "^{ }_{ }" e#   Take a template
  {          e#   If the accumulator is of length n, remove all characters whose
    A        e#   codepoints are greater than pow(10,
    W$,)3e<  e#                                   min(n+1, 3))
    #<       e#   When the accumulator is the empty string, that's all of them.
  },         e#   When the accumulator is one character, that's {}
             e#   When the accumulator is any longer, it's none of them.
  S/@*       e#   Substitute the accumulator for the spaces.
  +          e#   Append to the new character.
}/

Note that the min(n+1, 3) is to work around a bug in the interpreter: there must be some pattern in the powers of 10 that '} is smaller than, but it's not obvious.

Mathematica, 72 84 77 76 bytes

a_±b__:={"{",a,"_",±b,"^",±b,"}"};±(a_:""):={"",a,""};""<>Most@Rest@±##&@@#&

Uses CP-1252 (Windows) encoding. Takes a list of characters as input.

Explanation

a_±b__:=

Define the function ±, with 2 or more arguments. Label the first argument a, and second and on b.

{"{",a,"_",±b,"^",±b,"}"}

Create a List equivalent to "{a_±b^±b}" (±b is evaluated again, recursively).

±(a_:""):= ...

Define the function ±, with 1 or 0 arguments. Label the first argumenta, if it exists, and assign "" to a otherwise.

{"",a,""}

Create a List equivalent to "a", padded with empty Strings.

""<>Most@Rest@±##&@@#&

A pure function that applies ± to the input, drops first and last element, and converts List to String.

Python, 95 90 86 92 82 bytes

10 bytes saved thanks to @ConnerJohnston

f=lambda s:s and s[0]+(s[1:]and'_{0}^{0}'.format(s[2:]and'{'+f(s[1:])+'}'or s[1]))

Try it online!

Retina, 43 bytes

(.)(.)$
$1¶$2
+`(.)¶(.*)
¶{$1_$2^$2}
¶{|}$

Try it online! Link includes test cases. Explanation:

(.)(.)$
$1¶$2

Get the ball rolling by slicing off the last character. (But if it's the only character, them leave it alone.)

+`(.)¶(.*)
¶{$1_$2^$2}

Move the ¶ character back one step at a time, each time taking the previous result and making it a subscript and superscript of the next character.

¶{|}$

Remove the now redundant ¶ and the outer {}s.

PHP, 121 bytes

function b($s){return $s[0].($s[1]?'_'.($s[2]?'{'.($b=b(substr($s,1))).'}^{'.$b.'}':"$s[1]^$s[1]"):'');}echo b($argv[1]);

The function itself is 104 bytes and shows a PHP Notice.

Javascript, 73 Bytes

s=>[...s].reduceRight((m,c)=>`${c}_{${m}}^{${m}}`).replace(/{(.)}/g,'$1')

Explanation

s=>                                  // take the input string
    [...s]                           // split the string into an array
    .reduceRight(                    // reduce the array in reverse order
        (m,c)=>`${c}_{${m}}^{${m}}`  // storing the result of each iteration in the memo m
    )                                // and returning m at the end
    .replace(/{(.)}/g,'$1')          // replace redundant {}

Because there is no specified initial value of m, reduceRight takes the last element of s as the initial value, and begins iterating at index s.length-2.

const f=s=>[...s].reduceRight((m,c)=>`${c}_{${m}}^{${m}}`).replace(/{(.)}/g,'$1');

const input = document.querySelector('#input');
const output = document.querySelector('#output');
output.textContent = f(input.value);
input.addEventListener('keyup', e => output.textContent = f(input.value));
Enter text to bifurcate: <input type="text" id="input" value="cat" />
<br />
<span id="output"></span>

Pyth, 47 bytes

Ljk[hb|&ttbs[\_\{ytb"}^{"ytb\})&tbs[\_htb\^htb;

Try it online!

This is pretty much a straight port of @Uriel's Python answer. Going to golf it down in a bit.

Python 2, 84 bytes

def b(s):q=s and(s[2:]and'{%s}'or'%s')%b(s[1:]);return s[1:]and s[0]+'^%s_'%q+q or s

Try it online!

SOGL V0.12, 21 bytes

±K;{╔+;lH?"{ŗ}”}1 ^Ο+

Try it Here!

Explanation:

±                      reverse the string
 K                     take off the first letter - will slowly convert to the output
  ;                    get the rest of the string ontop
   {                   iterate over the rest of the characters
    ╔+                   append "_" to it
      ;                  get the output string ontop
       lH?     }         if it's length - 1 [isn't 0]
          "{ŗ}”            push the string "{ŗ}" where ŗ is replaced by the output string
                1 ^Ο     wrap "^" around with the output string
                    +    prepend to it the current character + "_"