def init_rule(rule_name)
    rule_name.to_s[/^([^?!]*)([?!])?$/]
    rule_name = $1.to_sym
    option = $2
    match_rule = rules[rule_name]
    raise "no rule for #{rule_name}" unless match_rule

    self.parser = lambda {|parent_node| match_rule.parse(parent_node)}
    self.name ||= rule_name
    case option
    when "?"  then self.optional = true
    when "!"  then self.negative = true
    end
  end
def init_rule(rule_name)
    rule_name.to_s[/^([^?!]*)([?!])?$/]
    rule_name = $1.to_sym
    option = $2
    match_rule = rules[rule_name]
    raise "no rule for #{rule_name}" unless match_rule

    self.parser = lambda {|parent_node| match_rule.parse(parent_node)}
    self.name ||= rule_name
    case option
    when "?"  then self.optional = true
    when "!"  then self.negative = true
    end
  end
initialize PatternElement as a parser that matches a named sub-rule