require 'rsync_config/config'

module RsyncConfig

grammar RsyncConfigFile

  rule start 
    global_section? module_section? EOF
    {
      attr_accessor :config, :active_module

      def to_config
        @config = ::RsyncConfig::Config.new
        @active_module = nil

        crawl self 

        @config
      end
    }
  end

  rule global_section
    (statement EOL global_section)
    / statement
  end

  rule module_section
    module_definition module_section
    / module_definition
  end

  rule module_definition
    module_header module_body
  end

  rule module_body
    (statement EOL module_body)
    / statement
  end

  rule statement
    comment / space? option?
  end

  rule option
    property space? '=' space? value space?
    {
      def action(top_node)
        receiver = top_node.active_module.nil? ? top_node.config : top_node.active_module
        receiver[property.text_value] = value.text_value

        # interrupt subtree crawling
        false
      end
    }
  end

  rule property
    [^=\n]+ 
  end

  rule value
    [^\n]* ('\\' space? EOL value)?
    {
      def value
        text_value.gsub(/\\\s*\n/, ' ')
      end
    }
  end

  rule module_header
    '[' module_label:([^/\]]+) ']' space?
    {
      def value
        module_label.text_value.gsub /\s+/, ' '
      end

      def action(top_node)
        top_node.active_module = top_node.config.module(module_label.text_value)

        # interrupt subtree crawling
        false
      end
    }
  end

  rule comment
    space? '#' [^"\n"]*
  end

  rule space
    [ \t]+
  end

  rule EOL
    "\n"
  end

  rule EOF
    !.
  end

  rule EOS
    EOL / EOF
  end
end

end