Common < EmptyObject {

Patterns < EmptyObject {
  Base < BasicObject { var name: parent_meme.name }
  UnaryBase  < Base { var inner }
  BinaryBase < Base { var first, var second }

  UnaryBase << {
    construct: construct_type.new(inner: inner.construct)
  }

  BinaryBase << {
    construct: construct_type.new(first: first.construct, second: second.construct)
  }
}

Constructions < EmptyObject {
  Base < BasicObject { }
  UnaryBase  < Base { var inner }
  BinaryBase < Base { var first, var second }
}

Constructions << {
  Base       << { const bytecode_can_capture?: false }
  UnaryBase  << { bytecode_can_capture?: inner.bytecode_can_capture? }
  BinaryBase << { bytecode_can_capture?: first.bytecode_can_capture?
                                     || second.bytecode_can_capture? }
}

Patterns << {
  ##
  # Shorthand methods for creating primitive patterns

  ShorthandMethods < EmptyObject {
    any:   ||                 String::Patterns::AnyCharacter   .new
    char:  |character|        String::Patterns::Character      .new(code:character.ord)
    str:   |string|           String::Patterns::CharacterString.new(codes:string.each_char.map(&:ord))
    set:   |string|           String::Patterns::CharacterSet   .new(codes:string.each_char.map(&:ord))
    range: |start, stop|      String::Patterns::CharacterRange .new(start:start.ord, stop:stop.ord)
    r:     |pattern, &block| Capture::Patterns::Reduction      .new(inner:pattern, block:block)
    si:    |*checks|          Stream::Patterns::Item           .new(checks:checks)
    esi:   ||                 Stream::Patterns::End            .new
  }

  ##
  # Operator overloading for combining and modifying patterns.
  #
  # Each operation returns a new Pattern object composed of the operands
  # so that complex grammars can be specified with relatively succint syntax.

  Base << {
    "!":         Composite::Patterns::NegativePredicate .new(inner:self)
    "/": |other| Composite::Patterns::OrderedChoice     .new(first:self, second:other)
    "+": |other=false|
      other &? Composite::Patterns::Concatenation       .new(first:self, second:other)
            ?? Composite::Patterns::OneOrMore           .new(inner:self)
    "-": |other=false|
      other &? raise("binary '-' operator not implemented")
            ?? Composite::Patterns::ZeroOrOne           .new(inner:self)
    "*": |other=false|
      other &? raise("binary '*' operator not implemented")
            ?? Composite::Patterns::ZeroOrMore          .new(inner:self)

    "[]": |name| Capture::Patterns::NamedCapture        .new(inner:self, name:name)
    text: |name=:text|
                 Capture::Patterns::NamedTextCapture    .new(inner:self, name:name)
    token: |name|
                 Capture::Patterns::NamedTokenCapture   .new(inner:self, name:name)

    [private]

    # Add |other| to |orig| in a right-associative tree of type |type|
    binary_right_assoc: |orig, other, type| {
      cursor = orig
      loop {
        unless(cursor.second.is_a?(type)) { break }
        cursor = cursor.second
      }
      cursor.second = type.new(first:cursor.second, second:other)
      orig
    }
  }
}

}