require 'haproxy/treetop/nodes'

module HAProxy::Treetop

grammar Config
  rule configuration
    (comment_line / blank_line / global_section / defaults_section / userlist_section / listen_section / frontend_section / backend_section)* <ConfigurationFile>
  end

  rule global_section
    global_header config_block <GlobalSection>
  end

  rule defaults_section
    defaults_header config_block <DefaultsSection>
  end

  rule userlist_section
    userlist_header config_block <UserlistSection>
  end

  rule listen_section
    listen_header config_block <ListenSection>
  end

  rule frontend_section
    frontend_header config_block <FrontendSection>
  end

  rule backend_section
    backend_header config_block <BackendSection>
  end

  rule global_header
    whitespace "global" whitespace comment_text? line_break <GlobalHeader>
  end

  rule userlist_header
    whitespace "userlist" whitespace proxy_name comment_text? line_break <UseristHeader>
  end

  rule defaults_header
    whitespace "defaults" whitespace proxy_name? whitespace comment_text? line_break <DefaultsHeader>
  end

  rule listen_header
    whitespace "listen" whitespace proxy_name whitespace service_address? value? comment_text? line_break <ListenHeader>
  end

  rule frontend_header
    whitespace "frontend" whitespace proxy_name whitespace service_address? value? comment_text? line_break <FrontendHeader>
  end

  rule backend_header
    whitespace "backend" whitespace proxy_name whitespace value? comment_text? line_break <BackendHeader>
  end

  rule config_block
    (server_line / option_line / config_line / comment_line / blank_line)* <ConfigBlock>
  end

  rule server_line
    whitespace "server" whitespace server_name whitespace service_address value? comment_text? line_break <ServerLine>
  end

  rule option_line
    whitespace "option" whitespace keyword whitespace value? comment_text? line_break <OptionLine>
  end

  rule config_line
    whitespace !("defaults" / "global" / "listen" / "frontend" / "backend") keyword whitespace value? comment_text? line_break <ConfigLine>
  end

  rule comment_line
    whitespace comment_text line_break <CommentLine>
  end

  rule blank_line
    whitespace line_break <BlankLine>
  end

  rule comment_text
    '#' char* &line_break <CommentText>
  end

  rule line_break
    [\n] <LineBreak>
  end

  rule keyword
     (("errorfile" / "timeout") whitespace)? [a-z0-9_\-\.]+ <Keyword>
  end

  rule server_name
    [a-zA-Z0-9\-_\.:]+ <ServerName>
  end

  rule service_address
    host [:]? port <ServiceAddress>
  end

  rule host
    ipv4_host / dns_host / wildcard_host
  end

  rule port
    [\d]* <Port>
  end

  rule ipv4_host
    [\d] 1..3 '.' [\d] 1..3 '.' [\d] 1..3 '.' [\d] 1..3 <Host>
  end

  rule wildcard_host
    "*" <Host>
  end

  rule dns_host
    [a-zA-Z\-\.\d] 4..255 <Host>
  end

  rule proxy_name
    [a-zA-Z0-9\-_\.:]+ <ProxyName>
  end

  rule value
    [^#\n]+ <Value>
  end

  rule char
    ![\n] . <Char>
  end

  rule whitespace
    [ \t]* <Whitespace>
  end

# Valid Global Keywords (1.4) # * Process management and security # - chroot <jail dir> # - daemon # - gid <number> # - group <group name> # - log <address> <facility> [max level [min level]] # - log-send-hostname [<string>] # ? log-tag <string> # - nbproc <number> # - pidfile <pidfile> # - uid <number> # - ulimit-n <number> # - user <user name> # - stats socket <path> [{uid | user} <uid>] [{gid | group} <gid>] [mode <mode>] [level <level>] # - stats timeout <timeout, in milliseconds> # - stats maxconn <connections> # - node <name> # - description <text> # # * Performance tuning # - maxconn <number> # - maxpipes <number> # - noepoll # - nokqueue # - nopoll # - nosepoll # - nosplice # - spread-checks <0..50, in percent> # - tune.bufsize <number> # - tune.chksize <number> # - tune.maxaccept <number> # - tune.maxpollevents <number> # - tune.maxrewrite <number> # - tune.rcvbuf.client <number> # - tune.rcvbuf.server <number> # - tune.sndbuf.client <number> # - tune.sndbuf.server <number> # # * Debugging # - debug # - quiet

# Valid Userlist keywords # - userlist <listname> # - group <groupname> [users <user>,<user>,(…)] # - user <username> [password|insecure-password <password>] [groups <group>,<group>,(…)]

end

end