Raw Input
..(.(..(..)..)..)..(..(..)..(..)..)..(..)..
Desired Output
..\(.(..(..)..)..\)..\(..(..)..(..)..\)..\(..\)..
Description
To assign a level number to every parenthesis, we keep a counter whose initial value is zero.

This process scans the line from left to right:

  • Whenever a `(' is meet, we increase the counter by one, and the resulting number is used as its level number.
  • Whenever a `)' is meet, the value of the counter is used as its level number, then we decrease the counter by one.
For the example above, the level number is shown under every parenthesis:
..(.(..(..)..)..)..(..(..)..(..)..)..(..)..
  1 2  3  3  2  1  1  2  2  2  2  1  1  1
Script and Comments
Script1
[ 1] s/\(.*$/\n&\n/
[ 2] /\n/!b
[ 3] :loop
[ 4] /\n\(/s/$/#/
[ 5] /\n#$/s/\n/\\\n/
[ 6] /\n\)/s/#$//
[ 7] s/\n(.[^\n()]*)/\1\n/
[ 8] /\n\n/!b loop
[ 9] s/\n//g
Comments
  1. When scanning a line, two newline characters are used:
    • the character next to the first newline is the parenthesis to be examined in this iteration.
    • the `#' characters following the second newline are used to keep the value of the counter.
  2. Step [1] is used to insert a newline before the first `(' and at the end of line
  3. If a line does not have any `(', Step [2] will print it and start a new cycle.
  4. Step [3] adds a `#' to the counter if the parenthesis is a `('
  5. If the parenthesis is outermost, Step [4] escapes it by inserting a `\'.
  6. Step [5] removes a `#' from the counter if the parenthesis is a `)'.
  7. Step [6] moves the first newline character to the next parenthesis.
  8. If there exist parentheses not examined, jumps to Step [3]; otherwise removes all newline characters.