module Temple::Mixins::GrammarDSL

def Rule(rule)

def Rule(rule)
  case rule
  when Rule
    rule
  when Symbol, Class, true, false, nil
    Value(rule)
  when Array
    start = Or.new(self)
    curr = [start]
    rule.each do |elem|
      case elem
      when /^(.*)(\*|\?|\+)$/
        elem = Element.new(self, const_get($1))
        curr.each {|c| c << elem }
        elem << elem if $2 != '?'
        curr = $2 == '+' ? [elem] : (curr << elem)
      else
        elem = Element.new(self, elem)
        curr.each {|c| c << elem }
        curr = [elem]
      end
    end
    elem = Value([])
    curr.each {|c| c << elem }
    start
  else
    raise ArgumentError, "Invalid grammar rule '#{rule.inspect}'"
  end
end

def Value(value)

def Value(value)
  Value.new(self, value)
end

def const_missing(name)

def const_missing(name)
  const_set(name, Root.new(self, name))
end

def extended(mod)

def extended(mod)
  mod.extend GrammarDSL
  constants.each do |name|
    const_get(name).copy_to(mod) if Rule === const_get(name)
  end
end

def match?(exp)

def match?(exp)
  const_get(:Expression).match?(exp)
end

def validate!(exp)

def validate!(exp)
  const_get(:Expression).validate!(exp)
end