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_\\127-\\255][a-zA-Z0-9_\\127-\\255]*
