Parentheses into Footnotes

Emacs Lisp, 335 bytes

Foreword. This answer and the Scheme ones are currently the only answers officially sanctioned by both the Mighty Popular Republic of LISP and the Church of Emacs. Other answers, shorter or not, are considered a threat to peace. In particular, and with a profound disdain to any libelious allegation of McCarthyism that is sporadically heard from hostile opponents of the state, we enjoin anyone who has information about the real identity of the anonymous authors writing Nonlisp answers to contact your Local Bureau. It is reminded that everyone should take time to reflect and upvote in accordance to what he or she deeply believes will not threaten his or her future interactions with official representants of the power in place. Code is data. Data is code.

(defun p()(let(b(cpt 0)n)(goto-char 0)(while(search-forward"("()t)(setf b(point)n(number-to-string(incf cpt)))(backward-char)(forward-sexp)(backward-char)(kill-region b(point))(delete-backward-char 1)(delete-forward-char 1)(insert "<sup>"n"</sup>")(save-excursion(end-of-buffer)(newline 2)(insert "<sub>"n" ")(yank)(insert"</sub>")))))

More elegantly:

(defun parens ()
  (let (b(cpt 0)n)
    (goto-char 0)
    (while(search-forward"("()t)
      (setf b(point)n(number-to-string(incf cpt)))
      (backward-char)
      (forward-sexp)
      (backward-char)
      (kill-region b(point))
      (delete-backward-char 1)
      (delete-forward-char 1)
      (insert "<sup>"n"</sup>")
      (save-excursion
       (end-of-buffer)
       (newline 2)
       (insert "<sub>"n" ")
       (yank)
       (insert "</sub>")))))

Perl, 81 75 72 bytes

71 bytes code + 1 byte command line argument.

Requires Perl 5.10 or newer (for recursive regex support)

$i++;s#(\((((?1)|.)*?)\))(.*)#<sup>$i</sup>$4

<sub>$i $2</sub>#s&&redo

Usage:

perl -p entry.pl input.txt

Explanation

-p parameter will print the result of applying the given commands to the input, avoiding the need for an explicit print.

The regex (\(((?1)|.)*?)\)) is looking for the outermost set of brackets from the start of the string. When this is found, we perform the substitution, ensuring we only add the at the very end of the input (by capturing everything until the end of the input using (.*)).

We then repeat the regex substitution on the now-substituted string using redo, which will continually apply the regex substitution until it no longer matches. The s modifier ensures that the . in the regex will match new lines, which is necessary because we re-apply the regex match on the result of the previous regex substitution.


Retina, 96 86 83 bytes * 120% = 99.6

The source code of this solution consists of two files:

+s`\((((\()|(?<-3>\))|[^)])*).(.*)(?<=(1+).*?)?
<sup>1$5</sup>$4

<sub>1$5 $1</sub>

Explanation

This is a very direct implementation of the algorithm as described in the challenge. The code consists of a single regex substitution which turns the first set of parentheses into a footnote. This substitution is repeated via the + until the string stops changing, which here means that the regex no longer matches (because it can't find any more parentheses).

The footnotes are enumerated in unary, so that I can simply look for the last footnote's number and append a 1 to create the next one.

The regex for finding the first set of parentheses is based on the standard technique for matching parentheses with balancing groups (hrhr, "matching parentheses"). It has been shortened a bit by using an unnamed group and by assuming that the parentheses are correctly balanced (which means we can omit the ( from the negated character class and match the final ) with a simple . and we also don't need to ensure that the capture stack is empty).

After matching the parentheses and capturing their contents into group 1, we capture the remainder of the string with (.*) into group 4 and then search back through the the string for the first set of 1s with a negative lookbehind. If we find such a substring, we store in group 5. If we don't, we lookbehind fails, but that's okay because it's optional - it just means that $5 will give an empty string which is the unary representation of 0 and which is also correct.

The substitution string then simply pieces everything together based on the capturing groups. The footnote number is incremented by prepending a 1 to the last number with 1$5.