use v6.c;

unit grammar Nginx::Config::Parser;

rule TOP {
    <comment>*
    \n*
    \s*
    <server>*
}

rule server {
    <comment>*
    server '{'
    <directive>*
    '}'
    \n*
    \s*
    <comment>*
}

rule directive {
    <comment>
    | <server_name>
    | <root>
    | <listen>
    | <error_page>
    | <include>
    | <set>
    | <location>
    | <alias>
    | <return-uri>
    | <rewrite>
    | <if>
    | <ssl_certificate_key>
    | <ssl_certificate>
    | <proxy_set_header>
    | <proxy_pass>
    | <proxy_redirect>
    | <try_files>
    | <internal>
    | <charset>
    | <default_type>
    | <deny>
    | <allow>
    | <index>
    | <add_header>
    | <add_trailer>
    | <client_max_body_size>
}

token server_name {
    server_name <.ws> <domain> [<.ws> <domain>]* <.ws> \;
}

rule root {
    root <path> \;
}

rule listen {
    listen <domain>\:<port><string>? \;
}

rule error_page {
    error_page <status> <uri> \;
}

rule include {
    include <path> \;
}

rule set {
    set <variable> <string> \;
}

rule location {
    location <op>? <string> \{
        <directive>*
    \}
}

rule alias {
    alias <string> \;
}

rule return-uri {
    return <status>? <uri> \;
}

rule rewrite {
    rewrite <expression> <uri> (redirect|permanent|last|break)? \;
}

rule if {
    if \( <variable> <op> <string> \) \{
        <directive>*
    \}
}

rule ssl_certificate {
    ssl_certificate <uri> \;
}

rule ssl_certificate_key {
    ssl_certificate_key <uri> \;
}

rule proxy_set_header {
    proxy_set_header <string> <variable> \;
}

rule proxy_pass {
    proxy_pass <uri> \; <comment>?
}

rule proxy_redirect {
    proxy_redirect <.ws> <uri> [<.ws> <uri>]* \;
}

rule try_files {
    try_files<.ws><variable>? <uri> \=?<status>? \;
}

rule internal {
    (internal) \;
}

rule default_type {
    default_type <uri> \;
}

rule charset {
    charset <string> \;
}

rule deny {
    deny <string> \; <comment>?
}

rule allow {
    allow <string> \; <comment>?
}

rule add_header {
    add_header <string_with_quotes>+ \;
}

rule add_trailer {
    add_trailer <string>+\;
}

rule client_max_body_size {
    client_max_body_size <string>+\;
}

rule expires {
    expires <string>\;
}

token index {
    index <.ws> <uri> [<.ws> <uri>]* \;
}

token domain {
    [<[\w-]>+ | \*] [\. <[\w-]>+]*
}

token port {
    \d+
}

token status {
    \d+
}

token expression {
    \^?[\S]*
}

token path {
    <[\w\./-]>+
}

token uri {
    <-[\s;]>+
}

token variable {
    \$\w+
}

regex string {
    (\/[\S]*)
    || \" (<-[ " ]>*) \"
    | \' (<-[ ' ]>*) \'
    | (<-[ "'; ]>+)
}

regex string_with_quotes {
    (\/[\S]*)
    || (\" <-[ " ]>* \")
    | (\' <-[ ' ]>* \')
    | (<-[ "'; ]>+)
}

token comment {
    \s* '#' (\N*)
}

token op {
    <[^*!=~]>*
}

# vim: ft=perl6
