; ---------------------------------------------------------------------------- ;
;  Type                                                                        ;
; ---------------------------------------------------------------------------- ;

Type
	= Atomic [Union / Intersection]
	/ Nullable

ParenthesizedType
	= Atomic [Union / Intersection / Conditional]
	/ Nullable

Union
	= 1*(TokenUnion Atomic)

Intersection
	= 1*(TokenIntersection Atomic)

Conditional
    = 1*ByteHorizontalWs TokenIs [TokenNot] Atomic TokenNullable Atomic TokenColon Atomic

Nullable
	= TokenNullable Atomic

Atomic
	= TokenIdentifier [Generic / Callable / Array]
	/ TokenThisVariable
	/ TokenParenthesesOpen ParenthesizedType TokenParenthesesClose [Array]

Generic
	= TokenAngleBracketOpen Type *(TokenComma Type) TokenAngleBracketClose

Callable
	= TokenParenthesesOpen [CallableParameters] TokenParenthesesClose TokenColon CallableReturnType

CallableParameters
	= CallableParameter *(TokenComma CallableParameter)

CallableParameter
	= Type [CallableParameterIsReference] [CallableParameterIsVariadic] [CallableParameterName] [CallableParameterIsOptional]

CallableParameterIsReference
	= TokenIntersection

CallableParameterIsVariadic
	= TokenVariadic

CallableParameterName
	= TokenVariable

CallableParameterIsOptional
	= TokenEqualSign

CallableReturnType
	= TokenIdentifier [Generic]
	/ Nullable
	/ TokenParenthesesOpen Type TokenParenthesesClose

Array
	= 1*(TokenSquareBracketOpen TokenSquareBracketClose)

ArrayShape
    = TokenCurlyBracketOpen ArrayShapeItem *(TokenComma ArrayShapeItem) TokenCurlyBracketClose

ArrayShapeItem
    = (ConstantString / ConstantInt / TokenIdentifier) TokenNullable TokenColon Type
    / Type

; ---------------------------------------------------------------------------- ;
;  ConstantExpr                                                                ;
; ---------------------------------------------------------------------------- ;

ConstantExpr
	= ConstantFloat *ByteHorizontalWs
	/ ConstantInt *ByteHorizontalWs
	/ ConstantTrue *ByteHorizontalWs
	/ ConstantFalse *ByteHorizontalWs
	/ ConstantNull *ByteHorizontalWs
	/ ConstantString *ByteHorizontalWs
	/ ConstantArray *ByteHorizontalWs
	/ ConstantFetch *ByteHorizontalWs

ConstantFloat
	= ["-"] 1*ByteDecDigit "." *ByteDecDigit [ConstantFloatExp]
	/ ["-"] 1*ByteDecDigit ConstantFloatExp
	/ ["-"] "." 1*ByteDecDigit [ConstantFloatExp]

ConstantFloatExp
	= "e" ["-"] 1*ByteDecDigit

ConstantInt
	= ["-"] "0b" 1*ByteBinDigit
	/ ["-"] "0o" 1*ByteOctDigit
	/ ["-"] "0x" 1*ByteHexDigit
	/ ["-"] 1*ByteDecDigit

ConstantTrue
	= "true"

ConstantFalse
	= "false"

ConstantNull
	= "null"

ConstantString
	= ByteSingleQuote *(ByteBackslash ByteNotEol / ByteNotEolAndNotBackslashAndNotSingleQuote) ByteSingleQuote
	/ ByteDoubleQuote *(ByteBackslash ByteNotEol / ByteNotEolAndNotBackslashAndNotDoubleQuote) ByteDoubleQuote

ConstantArray
	= TokenSquareBracketOpen [ConstantArrayItems] TokenSquareBracketClose
	/ "array" TokenParenthesesOpen [ConstantArrayItems] TokenParenthesesClose

ConstantArrayItems
	= ConstantArrayItem *(TokenComma ConstantArrayItem) [TokenComma]

ConstantArrayItem
	= ConstantExpr [TokenDoubleArrow ConstantExpr]

ConstantFetch
	= TokenIdentifier [TokenDoubleColon ByteIdentifierFirst *ByteIdentifierSecond *ByteHorizontalWs]


; ---------------------------------------------------------------------------- ;
;  Tokens                                                                      ;
; ---------------------------------------------------------------------------- ;

TokenUnion
	= "|" *ByteHorizontalWs

TokenIntersection
	= "&" *ByteHorizontalWs

TokenNullable
	= "?" *ByteHorizontalWs

TokenParenthesesOpen
	= "(" *ByteHorizontalWs

TokenParenthesesClose
	= ")" *ByteHorizontalWs

TokenAngleBracketOpen
	= "<" *ByteHorizontalWs

TokenAngleBracketClose
	= ">" *ByteHorizontalWs

TokenSquareBracketOpen
	= "[" *ByteHorizontalWs

TokenSquareBracketClose
	= "]" *ByteHorizontalWs

TokenCurlyBracketOpen
    = "{" *ByteHorizontalWs

TokenCurlyBracketClose
    = "}" *ByteHorizontalWs

TokenComma
	= "," *ByteHorizontalWs

TokenColon
	= ":" *ByteHorizontalWs

TokenVariadic
	= "..." *ByteHorizontalWs

TokenEqualSign
	= "=" *ByteHorizontalWs

TokenVariable
	= "$" ByteIdentifierFirst *ByteIdentifierSecond *ByteHorizontalWs

TokenDoubleArrow
	= "=>" *ByteHorizontalWs

TokenDoubleColon
	= "::" *ByteHorizontalWs

TokenThisVariable
	= %x24.74.68.69.73 *ByteHorizontalWs

TokenIs
    = %x69.73 1*ByteHorizontalWs

TokenNot
    = %x6E.6F.74 1*ByteHorizontalWs

TokenIdentifier
	= [ByteBackslash] ByteIdentifierFirst *ByteIdentifierSecond *(ByteBackslash ByteIdentifierFirst *ByteIdentifierSecond) *ByteHorizontalWs


; ---------------------------------------------------------------------------- ;
;  Bytes                                                                       ;
; ---------------------------------------------------------------------------- ;

ByteHorizontalWs
	= %x09 ; horizontal tab
	/ %x20 ; space

ByteBinDigit
	= %x30-31 ; 0-1

ByteOctDigit
	= %x30-37 ; 0-7

ByteDecDigit
	= %x30-39 ; 0-9

ByteHexDigit
	= %x30-39 ; 0-9
	/ %x41-46 ; A-F
	/ %x61-66 ; a-f

ByteIdentifierFirst
	= %x41-5A ; A-Z
	/ %x5F    ; _
	/ %x61-7A ; a-z
	/ %x80-FF

ByteIdentifierSecond
	= %x30-39 ; 0-9
	/ %x41-5A ; A-Z
	/ %x5F    ; _
	/ %x61-7A ; a-z
	/ %x80-FF

ByteSingleQuote
	= %x27    ; '

ByteDoubleQuote
	= %x22    ; "

ByteBackslash
	= %x5C    ; \

ByteNotEol
	= %x00-09 ; skip LF
	/ %x0B-0C ; skip CR
	/ %x0E-FF

ByteNotEolAndNotBackslashAndNotSingleQuote
	= %x00-09 ; skip LF
	/ %x0B-0C ; skip CR
	/ %x0E-26 ; skip single quote
	/ %x28-5B ; skip backslash
	/ %x5D-FF

ByteNotEolAndNotBackslashAndNotDoubleQuote
	= %x00-09 ; skip LF
	/ %x0B-0C ; skip CR
	/ %x0E-21 ; skip double quote
	/ %x23-5B ; skip backslash
	/ %x5D-FF
