section_delim = _{ "---" }
whitespace    = _{ " " | "\t" }

collection_name        = { "name" ~ whitespace* ~ "=" ~ whitespace* ~ value ~ NEWLINE }
collection_description = { "description" ~ whitespace* ~ "=" ~ whitespace* ~ value }

variable = { "$" ~ whitespace* ~ key ~ whitespace* ~ "=" ~ whitespace* ~ value }

key   = { (!"=" ~ ANY)+ }
value = { (!"\n" ~ ANY)+ }

preamble = _{ NEWLINE* ~ ((collection_name | collection_description | variable | header | query | callback) ~ NEWLINE*)+ }

http_method = { "GET" | "PUT" | "POST" | "PATCH" | "DELETE" | "OPTIONS" }

header = { "*" ~ whitespace* ~ key ~ whitespace* ~ "=" ~ whitespace* ~ value }

query = { "?" ~ whitespace* ~ key ~ whitespace* ~ "=" ~ whitespace* ~ value }

file = { "@" ~ whitespace* ~ value }
text = { value }
form = { "~" ~ whitespace* ~ key ~ whitespace* ~ "=" ~ whitespace* ~ (file | text) }

callback = { "!" ~ whitespace* ~ value }

response_capture = { "&" ~ whitespace* ~ (!NEWLINE ~ ANY)+ }

guard_content = { (!"]" ~ ANY)+ }
guard = _{ "[" ~ guard_content ~ "]" }
guard_prefix = _{ guard ~ whitespace* }

assertion = { guard_prefix? ~ "^" ~ whitespace* ~ (!NEWLINE ~ ANY)+ }

fragment_path = { (!NEWLINE ~ ANY)+ }
fragment_include = { guard_prefix? ~ "<<" ~ whitespace* ~ fragment_path }

dependency = { ">" ~ whitespace* ~ "requires" ~ whitespace* ~ ":" ~ whitespace* ~ (!NEWLINE ~ ANY)+ }

body_content_type =  { value }
body              =  { (!"~~~" ~ ANY)+ }
body_block        = _{ "~~~" ~ whitespace* ~ body_content_type* ~ NEWLINE ~ body* ~ "~~~" }

url = { (!"\n" ~ ANY)+ }

description = { !http_method ~ value ~ NEWLINE }

request = {
    ((variable | dependency | description) ~ NEWLINE*)* ~ http_method ~ whitespace+ ~ url ~ (header | query | body_block | form | callback | variable | response_capture | assertion | fragment_include | dependency | NEWLINE)*
}

requests = {
    request ~ (section_delim ~ NEWLINE+ ~ request)*
}

request_collection = { (preamble ~ section_delim ~ NEWLINE*)* ~ requests }
