; This grammar describes the Humble Type Instruction format.
; It uses the ABNF notation (https://tools.ietf.org/html/rfc5234).
;
; NOTE: ABNF strings are case insensitive. For the sake of sanity,
; all strings must be considered case sensitive for this grammar.
;
; NOTE: The <root> rule is strictly ordered, because it is infeasible
; to define an unordered permutation. However, interpreters should
; allow independent blocks to appear in any order.


; Main structure

root  = ws [flags] [head] [maxp] [gasp] [cvt] [stor] *program

flags = "flags" open *(flagbits s flagname nl) close
head  = "head"    open *(num s id nl) close
maxp  = "maxp"    open *(num s id nl) close
gasp  = "gasp"    open *(num *(s id) nl) close
cvt   = "cvt"     open *(num s id nl) close
stor  = "storage" open *(num s id nl) close


; Instructions

program   = id open *(instr nl) close
open      = ws "{" ws
close     = "}" ws

instr     = instrname [flag] *(s arg)
instrname = 1*(ALPHA / DIGIT)
flag      = "[" (flagbits / flagname) "]"
flagname  = 1*(ALPHA / DIGIT / "_" / "." / "<" / ">" / ",")
flagbits  = 1*5BIT

arg       = id / delta / val
id        = 1*(ALPHA / DIGIT / "_" / "." / "#")
delta     = 1*DIGIT ("+" / "-") DIGIT
val       = num / nested
nested    = "(" (instr / operation) ")"
operation = val s operator s val
operator  = "+" / "-" / "<" / "<=" / "==" / "and"
          / "*" / "/" / ">" / ">=" / "!=" / "or"


; Numbers

num   = bint / xint / int / fixed / f2d14
bint  = "0b" 1*BIT
xint  = "0x" 1*HEXDIG
int   = ["-"] 1*DIGIT
fixed = ["-"] 1*DIGIT "." 1*DIGIT
f2d14 = ["-"] 1*DIGIT ":" 1*DIGIT


; Whitespace

s       = 1*space         ; Mandatory space
nl      = *space eol ws   ; Mandatory newline
ws      = *(space / eol)  ; Optional whitespace
space   = SP / HTAB / CR
eol     = LF / comment
comment = "#" *nonlf LF
nonlf   = space / %x21-10FFFF


; ABNF core rules, included for clarity

HTAB   = %x09  ; Horizontal tab
LF     = %x0A  ; Line feed
CR     = %x0D  ; Carriage return
SP     = %x20  ; Space

BIT    = %x30-31  ; 0-1
DIGIT  = %x30-39  ; 0-9
HEXDIG = %x30-39  ; 0-9
       / %x41-46  ; A-F
       / %x61-66  ; a-f
ALPHA  = %x41-5A  ; A-Z
       / %x61-7A  ; a-z
