//
// Lexical Grammar
//

SourceCharacter::
  > Any unicode code point

WhiteSpace::
  <TAB>
  <VT>
  <FF>
  <SP>
  <NBSP>
  <ZWNBSP>
  <USP>

LineTerminator::
  <LF>
  <CR>
  <LS>
  <PS>

UidMeaning: one of
  `class`                                       // SymbolFlags.Class
  `interface`                                   // SymbolFlags.Interface
  `typealias`                                   // SymbolFlags.TypeAlias
  `enum`                                        // SymbolFlags.Enum
  `namespace`                                   // SymbolFlags.Module
  `function`                                    // SymbolFlags.Function
  `variable`                                    // SymbolFlags.Variable
  `constructor`                                 // SymbolFlags.Constructor
  `member`                                      // SymbolFlags.ClassMember
  `event`                                       //
  `enummember`                                  // SymbolFlags.EnumMember
  `type`                                        // Any complex type

Punctuator:: one of
  `{` `}` `(` `)` `[` `]` `!` `.` `#` `~` `:` `@` `,`

UidNavigationPunctuator: one of
  `.`                                           // Navigate via 'exports' of symbol
  `#`                                           // Navigate via 'members' of symbol
  `~`                                           // Navigate via 'locals' of symbol

DecimalDigits::
  DecimalDigit
  DecimalDigits DecimalDigit

DecimalDigit:: one of
  `0` `1` `2` `3` `4` `5` `6` `7` `8` `9`

HexDigits::
  HexDigit HexDigits?

HexDigit:: one of
  `0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `a` `b` `c` `d` `e` `f` `A` `B` `C` `D` `E` `F`

UidString::
  `"` StringCharacters? `"`

StringCharacters::
  StringCharacter StringCharacters?

StringCharacter::
  SourceCharacter but not one of `"` or `\` or LineTerminator
  `\` EscapeSequence

EscapeSequence::
  CharacterEscapeSequence
  `0` [lookahead != DecimalDigit]
  HexEscapeSequence
  UnicodeEscapeSequence

CharacterEscapeSequence::
  SingleEscapeCharacter
  NonEscapeCharacter

SingleEscapeCharacter:: one of
  `'` `"` `\` `b` `f` `n` `r` `t` `v`

NonEscapeCharacter::
  SourceCharacter but not one of EscapeCharacter or LineTerminator

EscapeCharacter::
  SingleEscapeCharacter
  DecimalDigit
  `x`
  `u`

HexEscapeSequence::
  `x` HexDigit HexDigit

UnicodeEscapeSequence::
  `u` Hex4Digits
  `u` `{` CodePoint `}`

Hex4Digits::
  HexDigit HexDigit HexDigit HexDigit

CodePoint::
  > |HexDigits| but only if MV of |HexDigits| ≤ 0x10FFFF

// Represents the name of a symbol. The [Path] parameter is used to determine whether a `@` is permitted in the
// component.
UidComponent[Path]::
  UidString
  UidComponentAtoms[?Path]

UidComponentAtoms[Path]::
  UidComponentAtom[?Path] UidComponentAtoms[?Path]?

UidComponentAtom[Path]::
  [+Path] `@`
  SourceCharacter but not one of `"` or Punctuator or WhiteSpace or LineTerminator
  UidBracketedComponent[?Path]

UidBracketedComponent[Path]::
  `[` UidBracketedAtoms[?Path] `]`

UidBracketedAtoms[Path]::
  UidBracketedAtom[?Path] UidBracketedAtoms[?Path]?

UidBracketedAtom[Path]::
  UidString
  UidComponentAtom[?Path]

//
// Syntactic Grammar
//

Uid:
  [empty]
  UidSymbol                                     // Shorthand reference to symbol
  UidModuleSource `!`                           // Reference to the module
  UidModuleSource `!` UidSymbol                 // Reference to an export of a module
  UidModuleSource `|` `~` UidSymbol             // Reference to a local of a module
  `!` UidSymbol                                 // Reference to global symbol

// Represents the path for a module
UidModuleSource:
  UidComponent[+Path]

UidSymbol:
  UidComponents UidInstantiation? UidMeaningSuffix? UidAliasSuffix?
  `{` UidComponent[~Path] `}`                   // Type Parameter

UidComponents:
  UidComponent[~Path]
  UidComponents `.` UidComponent[~Path]         // Navigate via 'exports' of |UidComponents|
  UidComponents `#` UidComponent[~Path]         // Navigate via 'members' of |UidComponents|
  UidComponents `~` UidComponent[~Path]         // Navigate via 'locals' of |UidComponents|

UidInstantiation:
  `{` UidTypeArgumentList `}`

UidTypeArgumentList:
  Uid
  UidTypeArgumentList `,` Uid

UidMeaningSuffix:
  `:` UidMeaning                                // Indicates the meaning of a symbol (i.e. ':class')
  `:` UidMeaning `(` DecimalDigits `)`          // Indicates an overloaded meaning (i.e. ':function(1)')
  `:` `(` DecimalDigits `)`                     // Shorthand for an overloaded meaning (i.e. `:(1)`)
  `:` DecimalDigits                             // Shorthand for an overloaded meaning (i.e. ':1')

UidAliasSuffix:
  `@` DecimalDigits                             // Related type alias (i.e. '@0')