Type
  ::= Atomic (Union | Intersection)?
    | Nullable

Union
  ::= ('|' Atomic)+

Intersection
  ::= ('&' Atomic)+

Nullable
  ::= '?' Identifier Generic?

Atomic
  ::= Identifier (Generic | Array)?
    | ThisType
    | '(' Type ')' Array?

Generic
  ::= '<' Type (',' Type)* '>'

Array
  ::= ('[' ']')+

ThisType
  ::= '$this'

Identifier
  ::= ('\\'? Word)+

Word
  ::= [a-zA-Z_#x7F-#x10FFFF][0-9a-zA-Z_#x7F-#x10FFFF]*
