perl, <strike>1111</strike> 918 bytes === There is more golfing to do, but under 1000 bytes seemed a good stopping point, especially as no one else has answered this question yet =) @l=("A".."Z","a".."z");@h=(0..9,@l);sub g{join"|",@_}sub p{length$_[0]>1&&substr($_[0],0,1)ne"("?"($_[0])":$_[0]}sub e{$e=$_[0];for(split//,$_[1]){return if$i[$e++]ne$_}1}sub x{push@o,$l=p g @_}$w=c("^.*\$");sub N{++$n}sub I{$i[$n]}sub c{@i=split//,shift;$f=$t=0;shift@i,$f=1 if$i[0]eq"^";pop@i,$t=1 if$i[-1]eq"\$";@o=();for($n=0;$n<@i;N){if(e$n,"(?:"){push@o,"(";$n+=2}elsif(e$n,"."){x@h}elsif(e$n,"\\d"){x 0..9;N}elsif(e$n,"\\D"){x@l;N}elsif(e$n,"["){N;my($v,@c);$v=1,N if"^"eq I;while(I ne"]"){push@c,$i[$n+1]eq"-"?I..$i[$n+=2]:I;N}@c=grep{$d=$_;!grep{$_ eq$d}@c}@h if$v;x @c}elsif(e$n,"?"){splice@o,-1,1,"(|$l)"}elsif(e$n,"+"){$l=p$l;splice@o,-1,1,"$l$l*"}elsif(e$n,"{"){N;my($j,$k,$h);$j.=$i[$n++]until","eq I||"}"eq I;if(","eq I){$h=1;$k.=I until$i[N]eq"}"}$l=p$l;@r=$l x$j;push@r,defined$k?"(|$l)"x($k-$j):"$l*"if$h;splice@o,-1,1,@r}else{x I}}push@o,$w if!$t;join"",$f?@o:($w,@o)}while(<>){chomp;print c($_).$/} And here's a still-pretty-obfuscated, but at-least-it's-indented version: use strict; use warnings; my @let = ('A'..'Z','a'..'z'); my @chars = (0..9,@let); sub g { join('|',@_) } sub p { length $_[0] > 1 && substr($_[0],0,1) ne '(' ? "($_[0])" : $_[0] }; sub comp { my @i = split//,shift; my ($front_anchor, $tail_anchor); if($i[0] eq '^') { shift @i; $front_anchor=1 } if($i[-1] eq '$') { pop @i; $tail_anchor=1 } my @out; my ($c,$last); for(my $n=0;$n<@i;++$n) { $c = $i[$n]; if($i[$n] eq '(' && $i[$n+1] eq '?' && $i[$n+2] eq ':') { push @out, '('; $n+=2; } elsif($i[$n] eq '.') { $last = g @chars; push @out, p $last; } elsif($i[$n] eq '\\' && $i[$n+1] eq 'd') { $last = g 0..9; push @out, p $last; ++$n; } elsif($i[$n] eq '\\' && $i[$n+1] eq 'D') { $last = g @let; push @out, p $last; ++$n; } elsif($i[$n] eq '[') { ++$n; my $invert=0; if($i[$n] eq '^') { $invert=1; ++$n; } my @c; do { if($i[$n+1] eq '-') { push @c, $i[$n]..$i[$n+2]; $n+=2; } else { push @c, $i[$n]; } ++$n; } while($i[$n] ne ']'); @c = grep { my $c=$_; !grep { $_ eq $c } @c } @chars if $invert; $last = g @c; push @out, p $last; } elsif($i[$n] eq '?') { $last = "(|$last)"; splice @out, -1, 1, $last; } elsif($i[$n] eq '+') { $last = p $last; $last = "$last$last*"; splice @out, -1, 1, $last; } elsif($i[$n] eq '{') { ++$n; my ($bm, $bn, $hc); $bm .= $i[$n++] until $i[$n] eq ',' || $i[$n] eq '}'; if($i[$n] eq ',') { $hc=1; $bn .= $i[$n] until $i[++$n] eq '}'; } my @r; push @r, p $last for 1..$bm; push @r, p($last).'*' if $hc && !defined $bn; if($hc && defined $bn) { my $y = $bn - $bm; push @r, '(|'.p($last).')' for 1..$y; } splice @out, -1, 1, @r; undef $last; #no nested quantifiers } else { $last = $c; push @out, $last; } } @out = (comp('^.*$'),@out) unless $front_anchor; @out = (@out,comp('^.*$')) unless $tail_anchor; return wantarray?@out:join"",@out; } while(<>) { chomp; print comp($_)."\n"; }