hurl/docs/spec/hurl.grammar

484 lines
8.2 KiB
Plaintext
Raw Normal View History

2022-06-14 15:45:14 +03:00
# General
hurl-file: entry*
lt*
entry: request
response?
request:
lt*
method sp value-string lt
header*
request-section*
body?
response:
lt*
version sp status lt
header*
response-section*
body?
method:
"GET"
| "HEAD"
| "POST"
| "PUT"
| "DELETE"
| "CONNECT"
| "OPTIONS"
| "TRACE"
| "PATCH"
2022-11-29 18:59:43 +03:00
| "LINK"
| "UNLINK"
| "PURGE"
| "LOCK"
| "UNLOCK"
| "PROPFIND"
| "VIEW"
2022-06-14 15:45:14 +03:00
version:
"HTTP/1.0"
| "HTTP/1.1"
| "HTTP/2"
| "HTTP"
2022-06-14 15:45:14 +03:00
status: [0-9]+
header:
lt*
key-value lt
body:
lt*
bytes lt
# Sections
request-section:
query-string-params-section
| form-params-section
| multipart-form-data-section
| cookies-section
2022-08-11 21:44:40 +03:00
| options-section
2022-06-14 15:45:14 +03:00
response-section:
captures-section
| asserts-section
query-string-params-section:
lt*
"[QueryStringParams]" lt
key-value*
form-params-section:
lt*
"[FormParams]" lt
key-value*
multipart-form-data-section:
lt*
"[MultipartFormData]" lt
multipart-form-data-param*
cookies-section:
lt*
"[Cookies]" lt
key-value*
captures-section:
lt*
"[Captures]" lt
capture*
asserts-section:
lt*
"[Asserts]" lt
assert*
2022-08-11 21:44:40 +03:00
options-section:
lt*
"[Options]" lt
option*
2022-06-14 15:45:14 +03:00
key-value: key-string ":" value-string
multipart-form-data-param: file-param | key-value
file-param :
lt*
key-string ":" file-value lt
file-value: "file," filename ";" (file-contenttype)?
file-contenttype: [a-zA-Z0-9/+-]+
capture:
lt*
2022-10-26 15:09:17 +03:00
key-string ":" query (sp filter)* lt
2022-06-14 15:45:14 +03:00
assert:
lt*
2022-10-26 15:09:17 +03:00
query (sp filter)* sp predicate lt
2022-06-14 15:45:14 +03:00
2022-08-11 21:44:40 +03:00
option:
lt*
2022-09-02 10:13:42 +03:00
( ca-certificate-option
| follow-redirect-option
| insecure-option
| max-redirs-option
2022-10-18 15:04:49 +03:00
| retry-option
| retry-interval-option
| retry-max-count-option
2022-09-02 10:13:42 +03:00
| variable-option
2022-08-16 10:44:26 +03:00
| verbose-option
| very-verbose-option
2022-09-02 10:13:42 +03:00
)
ca-certificate-option: "cacert" ":" filename lt
follow-redirect-option: "location" ":" boolean lt
2022-08-11 21:44:40 +03:00
2022-08-12 21:07:14 +03:00
insecure-option: "insecure" ":" boolean lt
2022-08-11 21:44:40 +03:00
2022-09-02 10:13:42 +03:00
max-redirs-option: "max-redirs" ":" integer lt
2022-10-18 15:04:49 +03:00
retry-option: "retry" ":" boolean lt
retry-interval-option: "retry-interval" ":" integer lt
retry-max-count-option: "retry-max-count" ":" integer lt
2022-09-02 10:13:42 +03:00
variable-option: "variable" ":" variable-definition lt
2022-06-14 15:45:14 +03:00
2022-08-12 21:07:14 +03:00
verbose-option: "verbose" ":" boolean lt
2022-09-02 10:13:42 +03:00
very-verbose-option: "very-verbose" ":" boolean lt
2022-08-12 21:07:14 +03:00
2022-09-02 10:13:42 +03:00
variable-definition: variable-name "=" variable-value
variable-value:
null
| boolean
| integer
| float
| key-string
| quoted-string
2022-08-16 10:44:26 +03:00
2022-06-14 15:45:14 +03:00
# Query
2022-10-26 15:09:17 +03:00
query:
2022-06-14 15:45:14 +03:00
status-query
2022-10-16 10:35:54 +03:00
| url-query
2022-06-14 15:45:14 +03:00
| header-query
| cookie-query
| body-query
| xpath-query
| jsonpath-query
| regex-query
| variable-query
| duration-query
| bytes-query
| sha256-query
2022-09-06 11:58:26 +03:00
| md5-query
2022-06-14 15:45:14 +03:00
status-query: "status"
2022-10-16 10:35:54 +03:00
url-query: "url"
2022-06-14 15:45:14 +03:00
header-query: "header" sp quoted-string
cookie-query: "cookie" sp quoted-string
body-query: "body"
xpath-query: "xpath" sp quoted-string
jsonpath-query: "jsonpath" sp quoted-string
regex-query: "regex" sp (quoted-string | regex)
variable-query: "variable" sp quoted-string
duration-query: "duration"
sha256-query: "sha256"
2022-09-06 11:58:26 +03:00
md5-query: "md5"
2022-06-14 15:45:14 +03:00
bytes-query: "bytes"
# Predicates
predicate: ("not" sp )? predicate-func
predicate-func:
equal-predicate
| not-equal-predicate
| greater-predicate
| greater-or-equal-predicate
| less-predicate
| less-or-equal-predicate
| start-with-predicate
| end-with-predicate
| contain-predicate
| match-predicate
| exist-predicate
| include-predicate
| integer-predicate
| float-predicate
| boolean-predicate
| string-predicate
| collection-predicate
equal-predicate: ("equals" | "==") sp predicate-value
not-equal-predicate: ("notEquals" | "!=") sp predicate-value
2022-09-09 17:54:28 +03:00
greater-predicate: ("greaterThan" | ">") sp (integer | float | quoted-string)
2022-06-14 15:45:14 +03:00
2022-09-09 17:54:28 +03:00
greater-or-equal-predicate: ("greaterThanOrEquals" | ">=") sp sp* (integer | float | quoted-string)
2022-06-14 15:45:14 +03:00
2022-09-09 17:54:28 +03:00
less-predicate: ("lessThan" | "<") sp (integer | float | quoted-string)
2022-06-14 15:45:14 +03:00
2022-09-09 17:54:28 +03:00
less-or-equal-predicate: ("lessThanOrEquals" | "<=") sp (integer | float | quoted-string)
2022-06-14 15:45:14 +03:00
start-with-predicate: "startsWith" sp (quoted-string | oneline-hex | oneline-base64)
end-with-predicate: "endsWith" sp (quoted-string | oneline-hex | oneline-base64)
contain-predicate: "contains" sp quoted-string
match-predicate: "matches" sp (quoted-string | regex)
exist-predicate: "exists"
include-predicate: "includes" sp predicate-value
integer-predicate: "isInteger"
float-predicate: "isFloat"
boolean-predicate: "isBoolean"
string-predicate: "isString"
collection-predicate: "isCollection"
predicate-value:
null
| boolean
| integer
| float
| quoted-string
| oneline-hex
| oneline-base64
| oneline-file
| multiline-string
| template
# Bytes
bytes:
json-value
| xml
| multiline-string
| oneline-string
| oneline-base64
| oneline-file
| oneline-hex
xml: "<" "To Be Defined" ">"
oneline-base64: "base64," [A-Z0-9+-= \n]+ ";"
oneline-file: "file," filename ";"
oneline-hex: "hex," hexdigit* ";"
# Strings
quoted-string: "\"" (quoted-string-content | template)* "\""
quoted-string-content: (quoted-string-text | quoted-string-escaped-char)*
quoted-string-text: ~["\\]+
quoted-string-escaped-char: "\\" ("\"" | "\\" | "\b" | "\f" | "\n" | "\r" | "\t" | "\u" unicode-char)
key-string: (key-string-content | template)+
key-string-content: (key-string-text | key-string-escaped-char)*
2022-12-10 19:58:50 +03:00
key-string-text: (alphanum | "_" | "-" | "." | "[" | "]" | "@" | "$") +
2022-06-14 15:45:14 +03:00
key-string-escaped-char: "\\" ("#" | ":" | "\\" | "\b" | "\f" | "\n" | "\r" | "\t" | "\u" unicode-char )
value-string: (value-string-content | template)*
value-string-content: (value-string-text | value-string-escaped-char)*
value-string-text: ~[#\n\\]+
value-string-escaped-char: "\\" ("#" | "\\" | "\b" | "\f" | "\n" | "\r" | "\t" | "\u" unicode-char )
oneline-string: "`" (oneline-string-content | template)* "`"
2022-06-14 15:45:14 +03:00
oneline-string-content: (oneline-string-text | oneline-string-escaped-char)*
oneline-string-text: ~[#\n\\] ~"`"
2022-06-14 15:45:14 +03:00
oneline-string-escaped-char: "\\" ("`" | "#" | "\\" | "b" | "f" | "u" unicode-char )
2022-06-14 15:45:14 +03:00
multiline-string:
"```" multiline-string-type? lt
(multiline-string-content | template)* lt
"```"
multiline-string-type:
"base64"
| "hex"
| "json"
| "xml"
| "graphql"
multiline-string-content: (multiline-string-text | multiline-string-escaped-char)*
multiline-string-text: ~[\\]+ ~"```"
multiline-string-escaped-char: "\\" ( "\\" | "b" | "f" | "n" | "r" | "t" | "`" | "u" unicode-char)
filename: (filename-content | template)*
filename-content: (filename-text | filename-escaped-char)*
filename-text: ~[#; \n\\]+
filename-escaped-char: "\\" (";" | "#" | [ ])
unicode-char: "{" hexdigit+ "}"
# JSON
json-value:
template
| json-object
| json-array
| json-string
| json-number
| boolean
| null
json-object: "{" json-key-value ("," json-key-value)* "}"
json-key-value: json-string ":" json-value
json-array: "[" json-value ("," json-value)* "]"
json-string: "\"" (json-string-content | template)* "\""
json-string-content: json-string-text | json-string-escaped-char
json-string-text: ~["\\]
json-string-escaped-char:
"\\" ("\"" | "\\" | "b" | "f" | "n" | "r" | "t" | "u" hexdigit hexdigit hexdigit hexdigit)
json-number: integer fraction? exponent?
# Template / Expression
template: "{{" expr "}}"
2022-10-18 22:59:54 +03:00
expr: variable-name (sp filter)*
2022-06-14 15:45:14 +03:00
variable-name: [A-Za-z] [A-Za-z_-0-9]*
2022-10-18 22:59:54 +03:00
# Filter
2022-06-14 15:45:14 +03:00
2022-10-18 22:59:54 +03:00
filter:
2023-01-06 11:39:26 +03:00
count-filter
| html-escape-filter
| html-unescape-filter
| nth-filter
| regex-filter
| replace-filter
| split-filter
2022-12-10 19:58:50 +03:00
| to-int-filter
2023-01-06 11:39:26 +03:00
| url-decode-filter
| url-encode-filter
2022-10-18 22:59:54 +03:00
count-filter: "count"
2023-01-06 11:39:26 +03:00
html-escape-filter: "htmlEscape"
2022-10-18 22:59:54 +03:00
2023-01-06 11:39:26 +03:00
html-unescape-filter: "htmlUnescape"
2022-10-18 22:59:54 +03:00
2023-01-06 11:39:26 +03:00
nth-filter: "nth" sp integer
2023-01-06 11:39:26 +03:00
regex-filter: "regex" sp (quoted-string | regex)
replace-filter: "replace" sp (quoted-string | regex) sp quoted-string
split-filter: "split" sp quoted-string
2022-12-03 13:30:11 +03:00
2022-12-10 19:58:50 +03:00
to-int-filter: "toInt"
2022-10-18 22:59:54 +03:00
2023-01-06 11:39:26 +03:00
url-decode-filter: "urlDecode"
url-encode-filter: "urlEncode"
2022-10-18 22:59:54 +03:00
# Lexical Grammar
2022-06-14 15:45:14 +03:00
boolean: "true" | "false"
null: "null"
2022-12-10 19:58:50 +03:00
alphanum: [A-Za-z0-9]
2022-06-14 15:45:14 +03:00
integer: digit+
float: integer fraction
digit: [0-9]
hexdigit: [0-9A-Fa-f]
fraction: "." digit+
exponent: ("e" | "E") ("+"|"-")? digit+
sp: [ \t]
lt: sp* comment? [\n]?
comment: "#" ~[\n]*
regex: "/" regex-content "/"
regex-content: (regex-text|regex-escaped-char)*
regex-text: ~[\n\/]+
regex-escaped-char: "\\" ~[\n]