         return p2
       return (new Choice(p1, p2)).attrCheck(node)
 
+  ###*
+   * A pattern requiring both of its subpatterns to be valid, in any order
+  ###
   class Interleave extends Pattern
     constructor: (pattern1, pattern2) ->
       @pattern1 = getPattern pattern1


  #** Pattern Classes

  class Pattern
    check: (node, descend) =>
      unless node?
        _nodelog node, "missing node", node, this
        throw new Error("ack node missing")
      _nodelog node, "checking #{this} against", node, [this, node]
      res = @_check(node, descend)
      _nodelog node, "result for #{this} against", node, "is #{res}", [this, node, res]
      return res

    _check: (node, descend) =>
      return new NotAllowed("pattern check failed", this, node)
    attrCheck: (node) =>
      return new Empty("not checking an attribute", this, node)
    toString: =>
      "<UNDEFINED PATTERN>"
    nullable: =>
      false
    require: =>
      return this
    contains: (nodeName) =>
      throw new RNGException("Cannot call 'contains(#{nodeName})' on pattern '#{@toString()}'")
    dereference: =>
      return this

  class Empty extends Pattern
    constructor: (@message, @pattern, @childNode) ->
    toString: =>
      "empty"
    nullable: =>
      true
    _check: (node, descend) =>
      return this
      if h.getNodeType(node) is Node.TEXT_NODE and h.textContent(node).replace(/^\s+|\s+$/gm, "") is ""
        return this
      return new NotAllowed("expected nothing, found #{h.getLocalName(node)}", this, node)
    attrCheck: (node) =>
      return this

  class NotAllowed extends Pattern
    constructor: (@message, @pattern, @childNode, @priority) ->
    toString: =>

      else
        "missingContent"

  ###*
   * A pattern accepting any text content
  ###
  class Text extends Empty
    toString: =>
      "text"
