code: func concat(x, y regexpInfo) (out regexpInfo) {
  	//println("concat", x.String(), "...", y.String())
  	//defer func() { println("->", out.String()) }()
  	var xy regexpInfo
  	xy.match = x.match.and(y.match)
  	if x.exact.have() && y.exact.have() {
  		xy.exact = x.exact.cross(y.exact, false)
  	} else {
  		if x.exact.have() {
  			xy.prefix = x.exact.cross(y.prefix, false)
  		} else {
  			xy.prefix = x.prefix
  			if x.canEmpty {
  				xy.prefix = xy.prefix.union(y.prefix, false)
  			}
  		}
  		if y.exact.have() {
  			xy.suffix = x.suffix.cross(y.exact, true)
  		} else {
  			xy.suffix = y.suffix
  			if y.canEmpty {
  				xy.suffix = xy.suffix.union(x.suffix, true)
  			}
  		}
  	}
  
  	// If all the possible strings in the cross product of x.suffix
  	// and y.prefix are long enough, then the trigram for one
  	// of them must be present and would not necessarily be
  	// accounted for in xy.prefix or xy.suffix yet.  Cut things off
  	// at maxSet just to keep the sets manageable.
  	if !x.exact.have() && !y.exact.have() &&
  		x.suffix.size() <= maxSet && y.prefix.size() <= maxSet &&
  		x.suffix.minLen()+y.prefix.minLen() >= 3 {
  		xy.match = xy.match.andTrigrams(x.suffix.cross(y.prefix, false))
  	}
  
  	xy.simplify(false)
  	return xy
  }
docs: // concat returns the regexp info for xy given x and y.