# bre2ere.sed - convert BRE to ERE sed
#
# note: ^ and $ not at start of end resp. of the RE are considered as
# literal chars.
# (POSIX documents as an option /\(^a$\)/ to be equivalent to /^\(a\)$/,
# here it gets converted to /(\^a\$)/)

s/'/'a/g
s/_/'b/g

# parse the line
s/^/_/

s/_\([  ]*\)/\1_/
# look for optional addresses before the command
: addr
# a 's' in the hold buffer indicates that the RE was part of a subst
# command. Since we're looking for addresses, clear the hold buffer.
x  
s/.*//
x  
# skip <address>, <address><comma>, <address>!,
s/_\([0-9!,$  ]*\)/\1_/

# handle /re/ as if it was \/re/ (i.e. special case of \xrex)
/_\// {
  s//\/_\//
  b rebeg
}  

# handle \xrex
/_\\'*./ {
  # we will carry the delimiter after the _
  s/_\\\('*.\)/\\\1_\1/
  : rebeg
  # first case: ^ as first position
  s/\(_'*.\)^/^\1/
  : reloop
  /_\('*.\)\1/ b reend
  # skip one ordinary char
  s/\(_'*.\)\([^'/[\(){}+?|^]\)/\2\1/
  # ( -> \(
  s/\(_'*.\)\([(){}?+|^]\)/\\\2\1/
  # \( -> (
  s/\(_'*.\)\\\([(){}]\)/\2\1/
  # $ -> \$ except if last
  s/_\('*.\)$\1/$_\1\1/
  s/\(_'*.\)\$/\\$\1/
  # skip any other \x
  s/\(_'*.\)\([\']'*[^(){}]\)/\2\1/
  # skip bracket expression
  s/\(_'*.\)\(\[\^'*.[^]]*]\)/\2\1/
  s/\(_'*.\)\(\['*.[^]]*]\)/\2\1/
  # loop
  b reloop
  : reend
  # if an s is in the hold buf, go back to s
  x
  /s/ b subst
  x
  s/_\('*.\)\1/\1_/
}  

# skip white space and any !
s/_\([!  ]*\)/\1_/

# if a comma is found, loop for the second address
/_,/ b addr

# we now reach the command char
/_s'*./ {
  s/_s\('*.\)/s\1_\1/
  x
  s/^/s/
  x
  b rebeg
  : subst
  x
  s/_\('*.\)\1/\1_\1/
  : rhsloop
  /_\('*.\)\1/ b rhsend
  s/\(_'*.\)\([^\']\)/\2\1/
  s/\(_'*.\)\([\']'*.\)/\2\1/
  /_'*.\\$/ {
    s/_\('*.\)\\$/\\\1/
    s/'b/_/g
    s/'a/'/g
    N
    s/'/'a/g
    s/_/'b/g
    s/\\\('*.\)\(\n\)/\\\2_\1/
  }
  b rhsloop
  : rhsend
  s/_\('*.\)./\1_/
  # flags
  s/_\([0-9pg]*\)/\1_/
  # w flag handled as the w command
}  

/_y'*./ {
  s/_y\('*.\)/y\1_\1/
  : y1loop
  /_\('*.\)\1/ {
    s/_\('*.\)\1/\1_\1/
    b y2loop
  }
  s/\(_'*.\)\([^\]\)/\2\1/
  s/\(_'*.\)\([\']'*.\)/\2\1/
  b y1loop
  : y2loop
  /_\('*.\)\1/ b y2end
  s/\(_'*.\)\([^\]\)/\2\1/
  s/\(_'*.\)\([\']'*.\)/\2\1/
  b y2loop
  : y2end
  s/_\('*.\)\1/\1_/
}  

# :label, b label, t label, r file, w file (cmd & flag), # comment
# all these include the end of line
/_\([bt:rw#]\)/ b out

# simple commands
s/_\([dDgGhHlnNpPqx}]\)/\1_/

# a\, c\, i\
/_\([aic]\)/ {
  s//\1_/
  : aloop
  s/_\([^\]*\)/\1_/
  /_\\$/ {
    s//\\/
    s/'b/_/g
    s/'a/'/g
    N
    s/'/'a/g
    s/_/'b/g
    s/\(\n\)/\1_/
  }
  s/_\(\\:*.\)/\1_/
  /_$/ !b aloop
  b out
}  

# skip whitespace
s/_\([  ]*\)/\1_/

# loop while there is still a command
/_[;{]/ {
  s/_\([;{]\)/\1_/
  b addr
}  

/_$/ b out

# weird case
h  
s/[^_]*_/unknown construct: /
p  
i \
line was:
x  
q  

: out
# remove the _
s/_//
# unquote _ and '
s/'b/_/g
s/'a/'/g

### colorized by sedsed, a sed script debugger/indenter/tokenizer/HTMLizer