Last active
August 29, 2015 14:22
-
-
Save benediktkr/52d33ca982e29916a8aa to your computer and use it in GitHub Desktop.
VCL.BNF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### | |
### Non-terminals | |
### | |
VCL ::= ACL | SUB | BACKEND | DIRECTOR | PROBE | IMPORT | CSRC | |
ACL ::= 'acl' identifier '{' {ACLENTRY} '}' | |
SUB ::= 'sub' identifier COMPOUND | |
BACKEND ::= 'backend' identifier '{' { ['set|backend'] BACKENDSPEC } '}' | |
PROBE ::= 'probe' identifier '{' PROBESPEC '}' | |
# VMod imports are new in 3.0 | |
IMPORT ::= 'import' identifier [ 'from' string ] ';' | |
CSRC ::= 'C{' inline-c '}C' | |
RESERVED-ID-V4 ::= vcl_backend_response | vcl_backend_error | vcl_synth | |
RESERVED-ID-V3 ::= vcl_fetch | vcl_error | remove | purge | |
RESERVED-ID ::= set | |
# director definitions - simple variant | |
DIRECTOR ::= 'director' dirtype identifier '{' DIRSPEC '}' | |
dirtype ::= 'hash' | 'random' | 'client' | 'round-robin' | 'dns' | |
# can do better: specify production rule for every director type | |
DIRECTOR ::= | |
'director' ('hash'|'random'|'client') identifier '{' DIRSPEC '}' | |
'director' identifier 'round-robin' '{' DIRSPEC '}' | |
'director' 'dns' identifier '{' DNSSPEC '}' | |
DIRSPEC ::= | |
[ '.' 'retries' '=' uintval ';' ] | |
{ '{' '.' BACKENDEF [ '.' 'weight' '=' numval ';' ] '}' } | |
DNSSPEC ::= | |
{ '.' BACKENDEF } | |
[ '.' 'ttl' '=' timeval ';' ] | |
[ '.' 'suffix' '=' string ';' ] | |
[ '.' DNSLIST ] | |
DNSLIST ::= '{' { iprange ';' [ BACKENDSPEC ] } '}' | |
BACKENDEF ::= 'backend' '=' ( BACKENDSPEC | identifier ';' ) | |
# field spec as used in backend and probe definitions | |
SPEC ::= '{' { '.' identifier = fieldval ';' } '}' | |
# can do better: devil is in the detail on this one | |
BACKENDSPEC ::= | |
'.' 'host' '=' string ';' | |
| '.' 'port' '=' string ';' | |
# wow I had no idea... | |
| '.' 'host_header' '=' string ';' | |
| '.' 'connect_timeout' '=' timeval ';' | |
| '.' 'first_byte_timeout' '=' timeval ';' | |
| '.' 'between_bytes_timeout' '=' timeval ';' | |
| '.' 'max_connections '=' uintval ';' | |
| '.' 'saintmode_treshold '=' uintval ';' | |
| '.' 'probe' '{' {PROBESPEC} '}' ';' | |
# another woww \0/ | |
| '.' 'probe' identifier; | |
PROBESPEC ::= | |
'.' 'url' = string ';' | |
| '.' 'request' = string ';' | |
| '.' 'expected_response' = uintval ';' | |
| '.' 'timeout' = timeval ';' | |
| '.' 'interval' = timeval ';' | |
| '.' 'window' = uintval ';' | |
| '.' 'treshold' = uintval ';' | |
| '.' 'initial' = uintval ';' | |
ACLENTRY ::= ['!'] iprange ';' | '(' ['!'] iprange ')' ';' | ['!'] '(' iprange ')' ';' | |
# totally avoids dangling else yarr | |
IFSTMT ::= 'if' CONDITIONAL COMPOUND [ { ('elsif'|'elseif') CONDITIONAL COMPOUND } [ 'else' COMPOUND ]] | |
CONDITIONAL ::= '(' EXPR ')' | |
COMPOUND ::= '{' {STMT} '}' | |
STMT ::= COMPOUND | IFSTMT | CSRC | ACTIONSTMT ';' | |
ACTIONSTMT ::= ACTION | FUNCALL | |
ACTION :== | |
| 'ban' '(' EXPRESSION ')' | |
| 'call' identifier | |
# in vcl_fetch only | |
# V2.1 esi, 'req.do_esi = true' in later versions | |
| 'esi' | |
# in vcl_hash only | |
| 'hash_data' '(' EXPRESSION ')' | |
# V4.0 new is new | |
| 'new' identifier | |
# V2.1 - V3.0:'panic' keyword moved into vmod_debug in 2012 | |
| 'panic' EXPRESSION | |
# V2.1: purge expressions are semantically special and correspond to 'ban' in V3 | |
| 'purge' '(' EXPRESSION ')' | |
| 'purge_url' '(' EXPRESSION ')' | |
# V3.0: purge _this_, moved to RETURNACTION in V4.0 | |
| 'purge' | |
# rollback the request to before any header changes | |
| 'rollback' | |
| 'set' variable assoper EXPRESSION | |
| 'synthetic' EXPRESSION | |
| 'unset' variable | |
# remove is removed in 4.0 | |
| 'remove' variable | |
# log moved into std vmod in 3.0 and did not work thereafter | |
| 'log' EXPRESSION | |
| RETURNSTMT | |
RETURNSTMT := | |
| 'return' '(' ( RETURNACTION ) ')' | |
# V2.0: could do actions without return keyword | |
RETURNACTION ::= 'deliver' | 'fetch' | 'hash' | 'lookup' | 'pass' | 'pipe' | 'restart' | |
# V3.0 error statements | |
| 'error' [ '(' EXPR(int) [ ',' EXPR(string) ] ')' | EXPR(int) [ EXPR(string) ] | |
# V4.0: instead of error statement, still gets special handling | |
| 'synth' '(' EXPR(int) [',' EXPR(string)] ')' | |
# V4.0: purge is an action only callable in vcl_recv | |
| 'purge' | |
FUNCALL ::= variable '(' [ { FUNCALL | expr | string-list } ] ')' | |
EXPRESSION ::= 'true' | 'false' | constant | FUNCALL | variable | |
| '(' EXPRESSION ')' | |
| number '*' number | |
| number '/' number | |
| duration '*' doubleval | |
# add two strings without operator in 2.x series | |
| string '+' string | |
| number '+' number | |
| number '-' number | |
| timeval '+' duration | |
| timeval '-' duration | |
| timeval '-' timeval | |
| duration '+' duration | |
| duration '-' duration | |
| EXPRESSION comparison EXPRESSION | |
| '!' EXPRESSION | |
| EXPRESSION '&&' EXPRESSION | |
| EXPRESSION '||' EXPRESSION | |
### | |
### Terminals | |
### | |
timeval ::= doubleval timeunit | |
duration ::= ['-'] timeval | |
doubleval ::= { number [ '.' [number] ] } | |
timeunit ::= 'ms' | 's' | 'm' | 'h' | 'd' | 'w' | |
uintval ::= { number } # unsigned | |
fieldval ::= timeval | doubleval | timeunit | uintval | |
constant ::= string | fieldval | |
iprange ::= string [ '/' number ] | |
variable ::= identifier [ '.' identifier ] | |
comparison ::= '==' | '!=' | '<' | '>' | '<= | '>=' | '~' | '!~' | |
assoper ::= '=' | '+=' | '-=' | '*=' | '/=' | | |
comment ::= | |
/* !(/*|*/)* */ | |
// !(\n)* $ | |
# !(\n)* $ | |
long-string ::= | |
'{"' !("})* '"}' | |
shortstring ::= | |
'"' !(\")* '"' | |
inline-c ::= | |
!(('}C') | |
string ::= shortstring | longstring | |
identifier ::= [a-zA-Z][a-zA-Z0-9_-]* | |
number ::= [0-9]+ | |
### | |
### Lexer tokens | |
### | |
! % & + * , - . / ; < = > { | } ~ ( ) | |
!= NEQ | |
!~ NOMATCH | |
++ INC | |
+= INCR | |
*= MUL | |
-- DEC | |
-= DECR | |
/= DIV | |
<< SHL | |
<= LEQ | |
== EQ | |
>= GEQ | |
>> SHR | |
|| COR | |
&& CAND | |
elseif ELSEIF | |
elsif ELSIF | |
include INCLUDE | |
if IF |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment