func simplify1(op Op, flags Flags, sub, re *Regexp) *Regexp {
	if sub.Op == OpEmptyMatch {
		return sub
	}
	if op == sub.Op && flags&NonGreedy == sub.Flags&NonGreedy {
		return sub
	}
	if re != nil && re.Op == op && re.Flags&NonGreedy == flags&NonGreedy && sub == re.Sub[0] {
		return re
	}
	re = &Regexp{Op: op, Flags: flags}
	re.Sub = append(re.Sub0[:0], sub)
	return re
}
simplify1 implements Simplify for the unary OpStar,
OpPlus, and OpQuest operators. It returns the simple regexp
equivalent to

Regexp{Op: op, Flags: flags, Sub: {sub}}

under the assumption that sub is already simple, and
without first allocating that structure. If the regexp
to be returned turns out to be equivalent to re, simplify1
returns re instead.

simplify1 is factored out of Simplify because the implementation
for other operators generates these unary expressions.
Letting them call simplify1 makes sure the expressions they
generate are simple.
package syntax
func (re *Regexp) Simplify() *Regexp {
	if re == nil {
		return nil
	}
	switch re.Op {
	case OpCapture, OpConcat, OpAlternate:
		nre := re
		for i, sub := range re.Sub {
			nsub := sub.Simplify()
			if nre == re && nsub != sub {
				nre = new(Regexp)
				*nre = *re
				nre.Rune = nil
				nre.Sub = append(nre.Sub0[:0], re.Sub[:i]...)
			}
			if nre != re {
				nre.Sub = append(nre.Sub, nsub)
			}
		}
		return nre
	case OpStar, OpPlus, OpQuest:
		sub := re.Sub[0].Simplify()
		return simplify1(re.Op, re.Flags, sub, re)
	case OpRepeat:
		if re.Min == 0 && re.Max == 0 {
			return &Regexp{Op: OpEmptyMatch}
		}
		sub := re.Sub[0].Simplify()
		if re.Max == -1 {
			if re.Min == 0 {
				return simplify1(OpStar, re.Flags, sub, nil)
			}
			if re.Min == 1 {
				return simplify1(OpPlus, re.Flags, sub, nil)
			}
			nre := &Regexp{Op: OpConcat}
			nre.Sub = nre.Sub0[:0]
			for i := 0; i < re.Min-1; i++ {
				nre.Sub = append(nre.Sub, sub)
			}
			nre.Sub = append(nre.Sub, simplify1(OpPlus, re.Flags, sub, nil))
			return nre
		}
		if re.Min == 1 && re.Max == 1 {
			return sub
		}
		var prefix *Regexp
		if re.Min > 0 {
			prefix = &Regexp{Op: OpConcat}
			prefix.Sub = prefix.Sub0[:0]
			for i := 0; i < re.Min; i++ {
				prefix.Sub = append(prefix.Sub, sub)
			}
		}
		if re.Max > re.Min {
			suffix := simplify1(OpQuest, re.Flags, sub, nil)
			for i := re.Min + 1; i < re.Max; i++ {
				nre2 := &Regexp{Op: OpConcat}
				nre2.Sub = append(nre2.Sub0[:0], sub, suffix)
				suffix = simplify1(OpQuest, re.Flags, nre2, nil)
			}
			if prefix == nil {
				return suffix
			}
			prefix.Sub = append(prefix.Sub, suffix)
		}
		if prefix != nil {
			return prefix
		}
		return &Regexp{Op: OpNoMatch}
	}
	return re
}