func (t *template) write(re *syntax.Regexp) {
	switch re.Op {
	case syntax.OpLiteral:
		if t.level == 0 {
			for _, r := range re.Rune {
				t.buffer.WriteRune(r)
				if r == '%' {
					t.buffer.WriteRune('%')
				}
			}
		}
	case syntax.OpCapture:
		t.level++
		t.index++
		if t.level == 1 {
			t.groups = append(t.groups, re.Name)
			t.indices = append(t.indices, t.index)
			t.buffer.WriteString("%s")
		}
		for _, sub := range re.Sub {
			t.write(sub)
		}
		t.level--
	case syntax.OpConcat:
		for _, sub := range re.Sub {
			t.write(sub)
		}
	}
}
write writes a reverse template to the buffer.
package reverse
import (
	"bytes"
	"fmt"
	"net/url"
	"regexp"
	"regexp/syntax"
)
type Regexp struct {
	compiled *regexp.Regexp  
	template string          
	groups   []string        
	indices []int  
}
func CompileRegexp(pattern string) (*Regexp, error) {
	compiled, err := regexp.Compile(pattern)
	if err != nil {
		return nil, err
	}
	re, err := syntax.Parse(pattern, syntax.Perl)
	if err != nil {
		return nil, err
	}
	tpl := &template{buffer: new(bytes.Buffer)}
	tpl.write(re)
	return &Regexp{
		compiled: compiled,
		template: tpl.buffer.String(),
		groups:   tpl.groups,
		indices:  tpl.indices,
	}, nil
}
func (r *Regexp) Compiled() *regexp.Regexp {
	return r.compiled
}
func (r *Regexp) Template() string {
	return r.template
}
func (r *Regexp) Groups() []string {
	return r.groups
}
func (r *Regexp) Indices() []int {
	return r.indices
}
func (r *Regexp) MatchString(s string) bool {
	return r.compiled.MatchString(s)
}
func (r *Regexp) Values(s string) url.Values {
	match := r.compiled.FindStringSubmatch(s)
	if match != nil {
		values := url.Values{}
		for k, v := range r.groups {
			values.Add(v, match[r.indices[k]])
		}
		return values
	}
	return nil
}
func (r *Regexp) Revert(values url.Values) (string, error) {
	vars := make([]interface{}, len(r.groups))
	for k, v := range r.groups {
		if len(values[v]) == 0 {
			return "", fmt.Errorf(
				"Missing key %q to revert the regexp "+
					"(expected a total of %d variables)", v, len(r.groups))
		}
		vars[k] = values[v][0]
		values[v] = values[v][1:]
	}
	return fmt.Sprintf(r.template, vars...), nil
}
func (r *Regexp) RevertValid(values url.Values) (string, error) {
	reverse, err := r.Revert(values)
	if err != nil {
		return "", err
	}
	if !r.compiled.MatchString(reverse) {
		return "", fmt.Errorf("Resulting string doesn't match the regexp: %q",
			reverse)
	}
	return reverse, nil
}
type template struct {
	buffer *bytes.Buffer
	groups []string  
	indices []int  
	index   int    
	level   int    
}