swiftlang / swift-book

The Swift Programming Language book
Apache License 2.0
1.75k stars 159 forks source link

Grammar railroad diagram #337

Open mingodad opened 3 hours ago

mingodad commented 3 hours ago

Location

https://github.com/swiftlang/swift-book/blob/main/TSPL.docc/ReferenceManual/SummaryOfTheGrammar.md

Description

Using an EBNF understood by https://github.com/GuntherRademacher/rr we can have a nice navigable railroad diagram (see a manual conversion that already works, although still need some work on it).

//
// EBNF to be viewd at
//    (IPV6) https://www.bottlecaps.de/rr/ui
//    (IPV4) https://rr.red-dove.com/ui
//
// Copy and paste this at one of the urls shown above in the 'Edit Grammar' tab
// then click the 'View Diagram' tab.
//

//Summary of the Grammar

//Lexical Structure
//Grammar of whitespace

whitespace ::= whitespace-item whitespace?
whitespace-item ::= line-break
whitespace-item ::= inline-space
whitespace-item ::= comment
whitespace-item ::= multiline-comment
///whitespace-item ::= U+0000, U+000B, or U+000C

///line-break ::= U+000A
///line-break ::= U+000D
///line-break ::= U+000D followed by U+000A

inline-spaces ::= inline-space inline-spaces?
///inline-space ::= U+0009 or U+0020

comment ::= "//" comment-text line-break
multiline-comment ::= "/*" multiline-comment-text "*/"

comment-text ::= comment-text-item comment-text?
///comment-text-item ::= Any Unicode scalar value except U+000A or U+000D

multiline-comment-text ::= multiline-comment-text-item multiline-comment-text?
multiline-comment-text-item ::= multiline-comment
multiline-comment-text-item ::= comment-text-item
///multiline-comment-text-item ::= Any Unicode scalar value except /* or */

//Grammar of an identifier

identifier ::= identifier-head identifier-characters?
identifier ::= '`' identifier-head identifier-characters? '`'
identifier ::= implicit-parameter-name
identifier ::= property-wrapper-projection
identifier-list ::= identifier | identifier ',' identifier-list

///identifier-head ::= Upper- or lowercase letter A through Z
identifier-head ::= '_'
///identifier-head ::= U+00A8, U+00AA, U+00AD, U+00AF, U+00B2–U+00B5, or U+00B7–U+00BA
///identifier-head ::= U+00BC–U+00BE, U+00C0–U+00D6, U+00D8–U+00F6, or U+00F8–U+00FF
///identifier-head ::= U+0100–U+02FF, U+0370–U+167F, U+1681–U+180D, or U+180F–U+1DBF
///identifier-head ::= U+1E00–U+1FFF
///identifier-head ::= U+200B–U+200D, U+202A–U+202E, U+203F–U+2040, U+2054, or U+2060–U+206F
///identifier-head ::= U+2070–U+20CF, U+2100–U+218F, U+2460–U+24FF, or U+2776–U+2793
///identifier-head ::= U+2C00–U+2DFF or U+2E80–U+2FFF
///identifier-head ::= U+3004–U+3007, U+3021–U+302F, U+3031–U+303F, or U+3040–U+D7FF
///identifier-head ::= U+F900–U+FD3D, U+FD40–U+FDCF, U+FDF0–U+FE1F, or U+FE30–U+FE44
///identifier-head ::= U+FE47–U+FFFD
///identifier-head ::= U+10000–U+1FFFD, U+20000–U+2FFFD, U+30000–U+3FFFD, or U+40000–U+4FFFD
///identifier-head ::= U+50000–U+5FFFD, U+60000–U+6FFFD, U+70000–U+7FFFD, or U+80000–U+8FFFD
///identifier-head ::= U+90000–U+9FFFD, U+A0000–U+AFFFD, U+B0000–U+BFFFD, or U+C0000–U+CFFFD
///identifier-head ::= U+D0000–U+DFFFD or U+E0000–U+EFFFD

identifier-character ::= [0-9]
///identifier-character ::= U+0300–U+036F, U+1DC0–U+1DFF, U+20D0–U+20FF, or U+FE20–U+FE2F
identifier-character ::= identifier-head
identifier-characters ::= identifier-character identifier-characters?

implicit-parameter-name ::= '$' decimal-digits
property-wrapper-projection ::= '$' identifier-characters

//Grammar of a literal

literal ::= numeric-literal | string-literal | regular-expression-literal | boolean-literal | nil-literal

numeric-literal ::= '-'? integer-literal | '-'? floating-point-literal
boolean-literal ::= "true" | "false"
nil-literal ::= "nil"

//Grammar of an integer literal

integer-literal ::= binary-literal
integer-literal ::= octal-literal
integer-literal ::= decimal-literal
integer-literal ::= hexadecimal-literal

binary-literal ::= "0b" binary-digit binary-literal-characters?
binary-digit ::= [01]
binary-literal-character ::= binary-digit | '_'
binary-literal-characters ::= binary-literal-character binary-literal-characters?

octal-literal ::= "0o" octal-digit octal-literal-characters?
octal-digit ::= [0-7]
octal-literal-character ::= octal-digit | '_'
octal-literal-characters ::= octal-literal-character octal-literal-characters?

decimal-literal ::= decimal-digit decimal-literal-characters?
decimal-digit ::= [0-9]
decimal-digits ::= decimal-digit decimal-digits?
decimal-literal-character ::= decimal-digit | '_'
decimal-literal-characters ::= decimal-literal-character decimal-literal-characters?

hexadecimal-literal ::= "0x" hexadecimal-digit hexadecimal-literal-characters?
hexadecimal-digit ::= [0-9a-fA-F]
hexadecimal-literal-character ::= hexadecimal-digit | '_'
hexadecimal-literal-characters ::= hexadecimal-literal-character hexadecimal-literal-characters?

//Grammar of a floating-point literal

floating-point-literal ::= decimal-literal decimal-fraction? decimal-exponent?
floating-point-literal ::= hexadecimal-literal hexadecimal-fraction? hexadecimal-exponent

decimal-fraction ::= '.' decimal-literal
decimal-exponent ::= floating-point-e sign? decimal-literal

hexadecimal-fraction ::= '.' hexadecimal-digit hexadecimal-literal-characters?
hexadecimal-exponent ::= floating-point-p sign? decimal-literal

floating-point-e ::= [eE]
floating-point-p ::= [pP]
sign ::= [+-]

//Grammar of a string literal

string-literal ::= static-string-literal | interpolated-string-literal

string-literal-opening-delimiter ::= extended-string-literal-delimiter? '"'
string-literal-closing-delimiter ::= '"' extended-string-literal-delimiter?

static-string-literal ::= string-literal-opening-delimiter quoted-text? string-literal-closing-delimiter
static-string-literal ::= multiline-string-literal-opening-delimiter multiline-quoted-text? multiline-string-literal-closing-delimiter

multiline-string-literal-opening-delimiter ::= extended-string-literal-delimiter? '"""'
multiline-string-literal-closing-delimiter ::= '"""' extended-string-literal-delimiter?
extended-string-literal-delimiter ::= '#' extended-string-literal-delimiter?

quoted-text ::= quoted-text-item quoted-text?
quoted-text-item ::= escaped-character
///quoted-text-item ::= Any Unicode scalar value except ", \, U+000A, or U+000D

multiline-quoted-text ::= multiline-quoted-text-item multiline-quoted-text?
multiline-quoted-text-item ::= escaped-character
///multiline-quoted-text-item ::= Any Unicode scalar value except \
multiline-quoted-text-item ::= escaped-newline

interpolated-string-literal ::= string-literal-opening-delimiter interpolated-text? string-literal-closing-delimiter
interpolated-string-literal ::= multiline-string-literal-opening-delimiter multiline-interpolated-text? multiline-string-literal-closing-delimiter

interpolated-text ::= interpolated-text-item interpolated-text?
interpolated-text-item ::= '(' expression ')' | quoted-text-item

multiline-interpolated-text ::= multiline-interpolated-text-item multiline-interpolated-text?
multiline-interpolated-text-item ::= '(' expression ')' | multiline-quoted-text-item

escape-sequence ::= '\' extended-string-literal-delimiter
escaped-character ::= escape-sequence '0' | escape-sequence '\' | escape-sequence 't' | escape-sequence 'n' | escape-sequence 'r' | escape-sequence '"' | escape-sequence "'"
escaped-character ::= escape-sequence "u{" unicode-scalar-digits '}'
unicode-scalar-digits ::= Between one and eight hexadecimal digits

escaped-newline ::= escape-sequence inline-spaces? line-break

//Grammar of a regular expression literal

regular-expression-literal ::= regular-expression-literal-opening-delimiter regular-expression regular-expression-literal-closing-delimiter
regular-expression ::= Any regular expression

regular-expression-literal-opening-delimiter ::= extended-regular-expression-literal-delimiter? '/'
regular-expression-literal-closing-delimiter ::= '/' extended-regular-expression-literal-delimiter?

extended-regular-expression-literal-delimiter ::= '#' extended-regular-expression-literal-delimiter?

//Grammar of operators

operator ::= operator-head operator-characters?
operator ::= dot-operator-head dot-operator-characters

operator-head ::= '/' | '=' | '-' | '+' | '!' | '*' | '%' | '<' | '>' | '&' | '|' | '^' | '~' | '?'
///operator-head ::= U+00A1–U+00A7
///operator-head ::= U+00A9 or U+00AB
///operator-head ::= U+00AC or U+00AE
///operator-head ::= U+00B0–U+00B1
///operator-head ::= U+00B6, U+00BB, U+00BF, U+00D7, or U+00F7
///operator-head ::= U+2016–U+2017
///operator-head ::= U+2020–U+2027
///operator-head ::= U+2030–U+203E
///operator-head ::= U+2041–U+2053
///operator-head ::= U+2055–U+205E
///operator-head ::= U+2190–U+23FF
///operator-head ::= U+2500–U+2775
///operator-head ::= U+2794–U+2BFF
///operator-head ::= U+2E00–U+2E7F
///operator-head ::= U+3001–U+3003
///operator-head ::= U+3008–U+3020
///operator-head ::= U+3030

operator-character ::= operator-head
///operator-character ::= U+0300–U+036F
///operator-character ::= U+1DC0–U+1DFF
///operator-character ::= U+20D0–U+20FF
///operator-character ::= U+FE00–U+FE0F
///operator-character ::= U+FE20–U+FE2F
///operator-character ::= U+E0100–U+E01EF
operator-characters ::= operator-character operator-characters?

dot-operator-head ::= '.'
dot-operator-character ::= '.' | operator-character
dot-operator-characters ::= dot-operator-character dot-operator-characters?

infix-operator ::= operator
prefix-operator ::= operator
postfix-operator ::= operator

//Types
//Grammar of a type

type ::= function-type
type ::= array-type
type ::= dictionary-type
type ::= type-identifier
type ::= tuple-type
type ::= optional-type
type ::= implicitly-unwrapped-optional-type
type ::= protocol-composition-type
type ::= opaque-type
type ::= metatype-type
type ::= any-type
type ::= self-type
type ::= '(' type ')'

//Grammar of a type annotation

type-annotation ::= ':' attributes? "inout"? type

//Grammar of a type identifier

type-identifier ::= type-name generic-argument-clause? | type-name generic-argument-clause? '.' type-identifier
type-name ::= identifier

//Grammar of a tuple type

tuple-type ::= '(' ')' | '(' tuple-type-element ',' tuple-type-element-list ')'
tuple-type-element-list ::= tuple-type-element | tuple-type-element ',' tuple-type-element-list
tuple-type-element ::= element-name type-annotation | type
element-name ::= identifier

//Grammar of a function type

function-type ::= attributes? function-type-argument-clause "async"? throws-clause? "->" type

function-type-argument-clause ::= '(' ')'
function-type-argument-clause ::= '(' function-type-argument-list "..."? ')'

function-type-argument-list ::= function-type-argument | function-type-argument ',' function-type-argument-list
function-type-argument ::= attributes? "inout"? type | argument-label type-annotation
argument-label ::= identifier

throws-clause ::= "throws" | "throws" '(' type ')'

//Grammar of an array type

array-type ::= '[' type ']'

//Grammar of a dictionary type

dictionary-type ::= '[' type ':' type ']'

//Grammar of an optional type

optional-type ::= type ?

//Grammar of an implicitly unwrapped optional type

implicitly-unwrapped-optional-type ::= type '!'

//Grammar of a protocol composition type

protocol-composition-type ::= type-identifier '&' protocol-composition-continuation
protocol-composition-continuation ::= type-identifier | protocol-composition-type

//Grammar of an opaque type

opaque-type ::= "some" type

//Grammar of a boxed protocol type

boxed-protocol-type ::= "any" type

//Grammar of a metatype type

metatype-type ::= type '.' "Type" | type '.' "Protocol"

//Grammar of an Any type

any-type ::= "Any"

//Grammar of a Self type

self-type ::= "Self"

//Grammar of a type inheritance clause

type-inheritance-clause ::= ':' type-inheritance-list
type-inheritance-list ::= attributes? type-identifier | attributes? type-identifier ',' type-inheritance-list

//Expressions
//Grammar of an expression

expression ::= try-operator? await-operator? prefix-expression infix-expressions? '\'

//Grammar of a prefix expression

prefix-expression ::= prefix-operator? postfix-expression
prefix-expression ::= in-out-expression

//Grammar of an in-out expression

in-out-expression ::= '&' primary-expression

//Grammar of a try expression

try-operator ::= "try" | "try" '?' | "try" '!'

//Grammar of an await expression

await-operator ::= "await"

//Grammar of an infix expression

infix-expression ::= infix-operator prefix-expression
infix-expression ::= assignment-operator try-operator? await-operator? prefix-expression
infix-expression ::= conditional-operator try-operator? await-operator? prefix-expression
infix-expression ::= type-casting-operator
infix-expressions ::= infix-expression infix-expressions?

//Grammar of an assignment operator

assignment-operator ::= '='

//Grammar of a conditional operator

conditional-operator ::= '?' expression ':'

//Grammar of a type-casting operator

type-casting-operator ::= 'is' type
type-casting-operator ::= 'as' type
type-casting-operator ::= 'as' '?' type
type-casting-operator ::= 'as' '!' type

//Grammar of a primary expression

primary-expression ::= identifier generic-argument-clause?
primary-expression ::= literal-expression
primary-expression ::= self-expression
primary-expression ::= superclass-expression
primary-expression ::= conditional-expression
primary-expression ::= closure-expression
primary-expression ::= parenthesized-expression
primary-expression ::= tuple-expression
primary-expression ::= implicit-member-expression
primary-expression ::= wildcard-expression
primary-expression ::= macro-expansion-expression
primary-expression ::= key-path-expression
primary-expression ::= selector-expression
primary-expression ::= key-path-string-expression

//Grammar of a literal expression

literal-expression ::= literal
literal-expression ::= array-literal | dictionary-literal | playground-literal

array-literal ::= '[' array-literal-items? ']'
array-literal-items ::= array-literal-item ','? | array-literal-item ',' array-literal-items
array-literal-item ::= expression

dictionary-literal ::= '[' dictionary-literal-items ']' | '[' ':' ']'
dictionary-literal-items ::= dictionary-literal-item ','? | dictionary-literal-item ',' dictionary-literal-items
dictionary-literal-item ::= expression ':' expression

playground-literal ::= "#colorLiteral" '(' "red" ':' expression ',' "green" ':' expression ',' "blue" ':' expression ',' "alpha" ':' expression ')'
playground-literal ::= "#fileLiteral" '(' "resourceName" ':' expression ')'
playground-literal ::= "#imageLiteral" '(' "resourceName" ':' expression ')'

//Grammar of a self expression

self-expression ::= "self" | self-method-expression | self-subscript-expression | self-initializer-expression

self-method-expression ::= "self" '.' identifier
self-subscript-expression ::= "self" '[' function-call-argument-list ']'
self-initializer-expression ::= "self" '.' "init"

//Grammar of a superclass expression

superclass-expression ::= superclass-method-expression | superclass-subscript-expression | superclass-initializer-expression

superclass-method-expression ::= "super" '.' identifier
superclass-subscript-expression ::= "super" '[' function-call-argument-list ']'
superclass-initializer-expression ::= "super" '.' "init"

//Grammar of a conditional expression

conditional-expression ::= if-expression | switch-expression

if-expression ::= "if" condition-list '{' statement '}' if-expression-tail
if-expression-tail ::= "else" if-expression
if-expression-tail ::= "else" '{' statement '}'

switch-expression ::= "switch" expression '{' switch-expression-cases '}'
switch-expression-cases ::= switch-expression-case switch-expression-cases?
switch-expression-case ::= case-label statement
switch-expression-case ::= default-label statement

//Grammar of a closure expression

closure-expression ::= '{' attributes? closure-signature? statements? '}'

closure-signature ::= capture-list? closure-parameter-clause "async"? throws-clause? function-result? "in"
closure-signature ::= capture-list "in"

closure-parameter-clause ::= '(' ')' | '(' closure-parameter-list ')' | identifier-list
closure-parameter-list ::= closure-parameter | closure-parameter ',' closure-parameter-list
closure-parameter ::= closure-parameter-name type-annotation?
closure-parameter ::= closure-parameter-name type-annotation "..."
closure-parameter-name ::= identifier

capture-list ::= '[' capture-list-items ']'
capture-list-items ::= capture-list-item | capture-list-item ',' capture-list-items
capture-list-item ::= capture-specifier? identifier
capture-list-item ::= capture-specifier? identifier '=' expression
capture-list-item ::= capture-specifier? self-expression
capture-specifier ::= "weak" | "unowned" | "unowned(safe)" | "unowned(unsafe)"

//Grammar of an implicit member expression

implicit-member-expression ::= '.' identifier
implicit-member-expression ::= '.' identifier '.' postfix-expression

//Grammar of a parenthesized expression

parenthesized-expression ::= '(' expression ')'

//Grammar of a tuple expression

tuple-expression ::= '(' ')' | '(' tuple-element ',' tuple-element-list ')'
tuple-element-list ::= tuple-element | tuple-element ',' tuple-element-list
tuple-element ::= expression | identifier ':' expression

//Grammar of a wildcard expression

wildcard-expression ::= '_'

//Grammar of a macro-expansion expression

macro-expansion-expression ::= '#' identifier generic-argument-clause? function-call-argument-clause? trailing-closures?

//Grammar of a key-path expression

key-path-expression ::= '\' type? '.' key-path-components
key-path-components ::= key-path-component | key-path-component '.' key-path-components
key-path-component ::= identifier key-path-postfixes? | key-path-postfixes

key-path-postfixes ::= key-path-postfix key-path-postfixes?
key-path-postfix ::= '?' | '!' | "self" | '[' function-call-argument-list ']'

//Grammar of a selector expression

selector-expression ::= "#selector" '(' expression ')'
selector-expression ::= "#selector" '(' "getter:" expression ')'
selector-expression ::= "#selector" '(' "setter:" expression ')'

//Grammar of a key-path string expression

key-path-string-expression ::= "#keyPath" '(' expression ')'

//Grammar of a postfix expression

postfix-expression ::= primary-expression
postfix-expression ::= postfix-expression postfix-operator
postfix-expression ::= function-call-expression
postfix-expression ::= initializer-expression
postfix-expression ::= explicit-member-expression
postfix-expression ::= postfix-self-expression
postfix-expression ::= subscript-expression
postfix-expression ::= forced-value-expression
postfix-expression ::= optional-chaining-expression

//Grammar of a function call expression

function-call-expression ::= postfix-expression function-call-argument-clause
function-call-expression ::= postfix-expression function-call-argument-clause? trailing-closures

function-call-argument-clause ::= '(' ')' | '(' function-call-argument-list ')'
function-call-argument-list ::= function-call-argument | function-call-argument ',' function-call-argument-list
function-call-argument ::= expression | identifier ':' expression
function-call-argument ::= operator | identifier ':' operator

trailing-closures ::= closure-expression labeled-trailing-closures?
labeled-trailing-closures ::= labeled-trailing-closure labeled-trailing-closures?
labeled-trailing-closure ::= identifier ':' closure-expression

//Grammar of an initializer expression

initializer-expression ::= postfix-expression '.' "init"
initializer-expression ::= postfix-expression '.' "init" '(' argument-names ')'

//Grammar of an explicit member expression

explicit-member-expression ::= postfix-expression '.' decimal-digits
explicit-member-expression ::= postfix-expression '.' identifier generic-argument-clause?
explicit-member-expression ::= postfix-expression '.' identifier '(' argument-names ')'
explicit-member-expression ::= postfix-expression conditional-compilation-block

argument-names ::= argument-name argument-names?
argument-name ::= identifier ':'

//Grammar of a postfix self expression

postfix-self-expression ::= postfix-expression '.' "self"

//Grammar of a subscript expression

subscript-expression ::= postfix-expression '[' function-call-argument-list ']'

//Grammar of a forced-value expression

forced-value-expression ::= postfix-expression '!'

//Grammar of an optional-chaining expression

optional-chaining-expression ::= postfix-expression '?'

//Statements
//Grammar of a statement

statement ::= expression ';'?
statement ::= declaration ';'?
statement ::= loop-statement ';'?
statement ::= branch-statement ';'?
statement ::= labeled-statement ';'?
statement ::= control-transfer-statement ';'?
statement ::= defer-statement ';'?
statement ::= do-statement ';'?
statement ::= compiler-control-statement
statements ::= statement statements?

//Grammar of a loop statement

loop-statement ::= for-in-statement
loop-statement ::= while-statement
loop-statement ::= repeat-while-statement

//Grammar of a for-in statement

for-in-statement ::= "for" "case"? pattern "in" expression where-clause? code-block

//Grammar of a while statement

while-statement ::= "while" condition-list code-block

condition-list ::= condition | condition ',' condition-list
condition ::= expression | availability-condition | case-condition | optional-binding-condition

case-condition ::= "case" pattern initializer
optional-binding-condition ::= "let" pattern initializer? | "var" pattern initializer?

//Grammar of a repeat-while statement

repeat-while-statement ::= "repeat" code-block "while" expression

//Grammar of a branch statement

branch-statement ::= if-statement
branch-statement ::= guard-statement
branch-statement ::= switch-statement

//Grammar of an if statement

if-statement ::= "if" condition-list code-block else-clause?
else-clause ::= "else" code-block | "else" if-statement

//Grammar of a guard statement

guard-statement ::= "guard" condition-list "else" code-block

//Grammar of a switch statement

switch-statement ::= "switch" expression '{' switch-cases? '}'
switch-cases ::= switch-case switch-cases?
switch-case ::= case-label statements
switch-case ::= default-label statements
switch-case ::= conditional-switch-case

case-label ::= attributes? "case" case-item-list ':'
case-item-list ::= pattern where-clause? | pattern where-clause? ',' case-item-list
default-label ::= attributes? "default" ':'

where-clause ::= "where" where-expression
where-expression ::= expression

conditional-switch-case ::= switch-if-directive-clause switch-elseif-directive-clauses? switch-else-directive-clause? endif-directive
switch-if-directive-clause ::= if-directive compilation-condition switch-cases?
switch-elseif-directive-clauses ::= elseif-directive-clause switch-elseif-directive-clauses?
switch-elseif-directive-clause ::= elseif-directive compilation-condition switch-cases?
switch-else-directive-clause ::= else-directive switch-cases?

//Grammar of a labeled statement

labeled-statement ::= statement-label loop-statement
labeled-statement ::= statement-label if-statement
labeled-statement ::= statement-label switch-statement
labeled-statement ::= statement-label do-statement

statement-label ::= label-name ':'
label-name ::= identifier

//Grammar of a control transfer statement

control-transfer-statement ::= break-statement
control-transfer-statement ::= continue-statement
control-transfer-statement ::= fallthrough-statement
control-transfer-statement ::= return-statement
control-transfer-statement ::= throw-statement

//Grammar of a break statement

break-statement ::= "break" label-name?

//Grammar of a continue statement

continue-statement ::= "continue" label-name?

//Grammar of a fallthrough statement

fallthrough-statement ::= "fallthrough"

//Grammar of a return statement

return-statement ::= "return" expression?

//Grammar of a throw statement

throw-statement ::= "throw" expression

//Grammar of a defer statement

defer-statement ::= "defer" code-block

//Grammar of a do statement

do-statement ::= "do" throws-clause? code-block catch-clauses?
catch-clauses ::= catch-clause catch-clauses?
catch-clause ::= "catch" catch-pattern-list? code-block
catch-pattern-list ::= catch-pattern | catch-pattern ',' catch-pattern-list
catch-pattern ::= pattern where-clause?

//Grammar of a compiler control statement

compiler-control-statement ::= conditional-compilation-block
compiler-control-statement ::= line-control-statement
compiler-control-statement ::= diagnostic-statement

//Grammar of a conditional compilation block

conditional-compilation-block ::= if-directive-clause elseif-directive-clauses? else-directive-clause? endif-directive

if-directive-clause ::= if-directive compilation-condition statements?
elseif-directive-clauses ::= elseif-directive-clause elseif-directive-clauses?
elseif-directive-clause ::= elseif-directive compilation-condition statements?
else-directive-clause ::= else-directive statements?
if-directive ::= "#if"
elseif-directive ::= "#elseif"
else-directive ::= "#else"
endif-directive ::= "#endif"

compilation-condition ::= platform-condition
compilation-condition ::= identifier
compilation-condition ::= boolean-literal
compilation-condition ::= '(' compilation-condition ')'
compilation-condition ::= '!' compilation-condition
compilation-condition ::= compilation-condition "&&" compilation-condition
compilation-condition ::= compilation-condition "||" compilation-condition

platform-condition ::= "os" '(' operating-system ')'
platform-condition ::= "arch" '(' architecture ')'
platform-condition ::= "swift" '(' ">=" swift-version ')' | "swift" '(' '<' swift-version ')'
platform-condition ::= "compiler" '(' ">=" swift-version ')' | "compiler" '(' '<' swift-version ')'
platform-condition ::= "canImport" '(' import-path ')'
platform-condition ::= "targetEnvironment" '(' environment ')'

operating-system ::= "macOS" | "iOS" | "watchOS" | "tvOS" | "visionOS" | "Linux" | "Windows"
architecture ::= "i386" | "x86_64" | "arm" | "arm64"
swift-version ::= decimal-digits swift-version-continuation?
swift-version-continuation ::= '.' decimal-digits swift-version-continuation?
environment ::= "simulator" | "macCatalyst"

//Grammar of a line control statement

line-control-statement ::= "#sourceLocation" '(' "file:" file-path ',' "line:" line-number ')'
line-control-statement ::= "#sourceLocation" '(' ')'
///line-number ::= A decimal integer greater than zero
file-path ::= static-string-literal

//Grammar of an availability condition

availability-condition ::= "#available" '(' availability-arguments ')'
availability-condition ::= "#unavailable" '(' availability-arguments ')'
availability-arguments ::= availability-argument | availability-argument ',' availability-arguments
availability-argument ::= platform-name platform-version
availability-argument ::= '*'

platform-name ::= "iOS" | "iOSApplicationExtension"
platform-name ::= "macOS" | "macOSApplicationExtension"
platform-name ::= "macCatalyst" | "macCatalystApplicationExtension"
platform-name ::= "watchOS" | "watchOSApplicationExtension"
platform-name ::= "tvOS" | "tvOSApplicationExtension"
platform-name ::= "visionOS" | "visionOSApplicationExtension"
platform-version ::= decimal-digits
platform-version ::= decimal-digits '.' decimal-digits
platform-version ::= decimal-digits '.' decimal-digits '.' decimal-digits

//Declarations
//Grammar of a declaration

declaration ::= import-declaration
declaration ::= constant-declaration
declaration ::= variable-declaration
declaration ::= typealias-declaration
declaration ::= function-declaration
declaration ::= enum-declaration
declaration ::= struct-declaration
declaration ::= class-declaration
declaration ::= actor-declaration
declaration ::= protocol-declaration
declaration ::= initializer-declaration
declaration ::= deinitializer-declaration
declaration ::= extension-declaration
declaration ::= subscript-declaration
declaration ::= operator-declaration
declaration ::= precedence-group-declaration '\'

//Grammar of a top-level declaration

top-level-declaration ::= statements?

//Grammar of a code block

code-block ::= '{' statements? '}'

//Grammar of an import declaration

import-declaration ::= attributes? "import" import-kind? import-path

import-kind ::= "typealias" | "struct" | "class" | "enum" | "protocol" | "let" | "var" | "func"
import-path ::= identifier | identifier '.' import-path

//Grammar of a constant declaration

constant-declaration ::= attributes? declaration-modifiers? "let" pattern-initializer-list

pattern-initializer-list ::= pattern-initializer | pattern-initializer ',' pattern-initializer-list
pattern-initializer ::= pattern initializer?
initializer ::= '=' expression

//Grammar of a variable declaration

variable-declaration ::= variable-declaration-head pattern-initializer-list
variable-declaration ::= variable-declaration-head variable-name type-annotation code-block
variable-declaration ::= variable-declaration-head variable-name type-annotation getter-setter-block
variable-declaration ::= variable-declaration-head variable-name type-annotation getter-setter-keyword-block
variable-declaration ::= variable-declaration-head variable-name initializer willSet-didSet-block
variable-declaration ::= variable-declaration-head variable-name type-annotation initializer? willSet-didSet-block

variable-declaration-head ::= attributes? declaration-modifiers? "var"
variable-name ::= identifier

getter-setter-block ::= code-block
getter-setter-block ::= '{' getter-clause setter-clause? '}'
getter-setter-block ::= '{' setter-clause getter-clause '}'
getter-clause ::= attributes? mutation-modifier? "get" code-block
setter-clause ::= attributes? mutation-modifier? "set" setter-name? code-block
setter-name ::= '(' identifier ')'

getter-setter-keyword-block ::= '{' getter-keyword-clause setter-keyword-clause? '}'
getter-setter-keyword-block ::= '{' setter-keyword-clause getter-keyword-clause '}'
getter-keyword-clause ::= attributes? mutation-modifier? "get"
setter-keyword-clause ::= attributes? mutation-modifier? "set"

willSet-didSet-block ::= '{' willSet-clause didSet-clause? '}'
willSet-didSet-block ::= '{' didSet-clause willSet-clause? '}'
willSet-clause ::= attributes? "willSet" setter-name? code-block
didSet-clause ::= attributes? "didSet" setter-name? code-block

//Grammar of a type alias declaration

typealias-declaration ::= attributes? access-level-modifier? "typealias" typealias-name generic-parameter-clause? typealias-assignment
typealias-name ::= identifier
typealias-assignment ::= '=' type

//Grammar of a function declaration

function-declaration ::= function-head function-name generic-parameter-clause? function-signature generic-where-clause? function-body?

function-head ::= attributes? declaration-modifiers? "func"
function-name ::= identifier | operator

function-signature ::= parameter-clause "async"? throws-clause? function-result?
function-signature ::= parameter-clause "async"? "rethrows" function-result?
function-result ::= "->" attributes? type
function-body ::= code-block

parameter-clause ::= '(' ')' | '(' parameter-list ')'
parameter-list ::= parameter | parameter ',' parameter-list
parameter ::= external-parameter-name? local-parameter-name parameter-type-annotation default-argument-clause?
parameter ::= external-parameter-name? local-parameter-name parameter-type-annotation
parameter ::= external-parameter-name? local-parameter-name parameter-type-annotation "..."

external-parameter-name ::= identifier
local-parameter-name ::= identifier
parameter-type-annotation ::= ':' attributes? parameter-modifier? type
parameter-modifier ::= "inout" | "borrowing" | "consuming"
default-argument-clause ::= '=' expression

//Grammar of an enumeration declaration

enum-declaration ::= attributes? access-level-modifier? union-style-enum
enum-declaration ::= attributes? access-level-modifier? raw-value-style-enum

union-style-enum ::= "indirect"? "enum" enum-name generic-parameter-clause? type-inheritance-clause? generic-where-clause? '{' union-style-enum-members? '}'
union-style-enum-members ::= union-style-enum-member union-style-enum-members?
union-style-enum-member ::= declaration | union-style-enum-case-clause | compiler-control-statement
union-style-enum-case-clause ::= attributes? "indirect"? "case" union-style-enum-case-list
union-style-enum-case-list ::= union-style-enum-case | union-style-enum-case ',' union-style-enum-case-list
union-style-enum-case ::= enum-case-name tuple-type?
enum-name ::= identifier
enum-case-name ::= identifier

raw-value-style-enum ::= "enum" enum-name generic-parameter-clause? type-inheritance-clause generic-where-clause? '{' raw-value-style-enum-members '}'
raw-value-style-enum-members ::= raw-value-style-enum-member raw-value-style-enum-members?
raw-value-style-enum-member ::= declaration | raw-value-style-enum-case-clause | compiler-control-statement
raw-value-style-enum-case-clause ::= attributes? "case" raw-value-style-enum-case-list
raw-value-style-enum-case-list ::= raw-value-style-enum-case | raw-value-style-enum-case ',' raw-value-style-enum-case-list
raw-value-style-enum-case ::= enum-case-name raw-value-assignment?
raw-value-assignment ::= '=' raw-value-literal
raw-value-literal ::= numeric-literal | static-string-literal | boolean-literal

//Grammar of a structure declaration

struct-declaration ::= attributes? access-level-modifier? "struct" struct-name generic-parameter-clause? type-inheritance-clause? generic-where-clause? struct-body
struct-name ::= identifier
struct-body ::= '{' struct-members? '}'

struct-members ::= struct-member struct-members?
struct-member ::= declaration | compiler-control-statement

//Grammar of a class declaration

class-declaration ::= attributes? access-level-modifier? "final"? "class" class-name generic-parameter-clause? type-inheritance-clause? generic-where-clause? class-body
class-declaration ::= attributes? "final" access-level-modifier? "class" class-name generic-parameter-clause? type-inheritance-clause? generic-where-clause? class-body
class-name ::= identifier
class-body ::= '{' class-members? '}'

class-members ::= class-member class-members?
class-member ::= declaration | compiler-control-statement

//Grammar of an actor declaration

actor-declaration ::= attributes? access-level-modifier? "actor" actor-name generic-parameter-clause? type-inheritance-clause? generic-where-clause? actor-body
actor-name ::= identifier
actor-body ::= '{' actor-members? '}'

actor-members ::= actor-member actor-members?
actor-member ::= declaration | compiler-control-statement

//Grammar of a protocol declaration

protocol-declaration ::= attributes? access-level-modifier? "protocol" protocol-name type-inheritance-clause? generic-where-clause? protocol-body
protocol-name ::= identifier
protocol-body ::= '{' protocol-members? '}'

protocol-members ::= protocol-member protocol-members?
protocol-member ::= protocol-member-declaration | compiler-control-statement

protocol-member-declaration ::= protocol-property-declaration
protocol-member-declaration ::= protocol-method-declaration
protocol-member-declaration ::= protocol-initializer-declaration
protocol-member-declaration ::= protocol-subscript-declaration
protocol-member-declaration ::= protocol-associated-type-declaration
protocol-member-declaration ::= typealias-declaration

//Grammar of a protocol property declaration

protocol-property-declaration ::= variable-declaration-head variable-name type-annotation getter-setter-keyword-block

//Grammar of a protocol method declaration

protocol-method-declaration ::= function-head function-name generic-parameter-clause? function-signature generic-where-clause?

//Grammar of a protocol initializer declaration

protocol-initializer-declaration ::= initializer-head generic-parameter-clause? parameter-clause throws-clause? generic-where-clause?
protocol-initializer-declaration ::= initializer-head generic-parameter-clause? parameter-clause "rethrows" generic-where-clause?

//Grammar of a protocol subscript declaration

protocol-subscript-declaration ::= subscript-head subscript-result generic-where-clause? getter-setter-keyword-block

//Grammar of a protocol associated type declaration

protocol-associated-type-declaration ::= attributes? access-level-modifier? associatedtype typealias-name type-inheritance-clause? typealias-assignment? generic-where-clause?

//Grammar of an initializer declaration

initializer-declaration ::= initializer-head generic-parameter-clause? parameter-clause "async"? throws-clause? generic-where-clause? initializer-body
initializer-declaration ::= initializer-head generic-parameter-clause? parameter-clause "async"? "rethrows" generic-where-clause? initializer-body
initializer-head ::= attributes? declaration-modifiers? "init"
initializer-head ::= attributes? declaration-modifiers? "init" '?'
initializer-head ::= attributes? declaration-modifiers? "init" '!'
initializer-body ::= code-block

//Grammar of a deinitializer declaration

deinitializer-declaration ::= attributes? "deinit" code-block

//Grammar of an extension declaration

extension-declaration ::= attributes? access-level-modifier? "extension" type-identifier type-inheritance-clause? generic-where-clause? extension-body
extension-body ::= '{' extension-members? '}'

extension-members ::= extension-member extension-members?
extension-member ::= declaration | compiler-control-statement

//Grammar of a subscript declaration

subscript-declaration ::= subscript-head subscript-result generic-where-clause? code-block
subscript-declaration ::= subscript-head subscript-result generic-where-clause? getter-setter-block
subscript-declaration ::= subscript-head subscript-result generic-where-clause? getter-setter-keyword-block
subscript-head ::= attributes? declaration-modifiers? "subscript" generic-parameter-clause? parameter-clause
subscript-result ::= "->" attributes? type

//Grammar of a macro declaration

macro-declaration ::= macro-head identifier generic-parameter-clause? macro-signature macro-definition? generic-where-clause
macro-head ::= attributes? declaration-modifiers? "macro"
macro-signature ::= parameter-clause macro-function-signature-result?
macro-function-signature-result ::= "->" type
macro-definition ::= '=' expression

//Grammar of an operator declaration

operator-declaration ::= prefix-operator-declaration | postfix-operator-declaration | infix-operator-declaration

prefix-operator-declaration ::= "prefix" operator operator
postfix-operator-declaration ::= "postfix" operator operator
infix-operator-declaration ::= "infix" operator operator infix-operator-group?

infix-operator-group ::= ':' precedence-group-name

//Grammar of a precedence group declaration

precedence-group-declaration ::= precedencegroup precedence-group-name '{' precedence-group-attributes? '}'

precedence-group-attributes ::= precedence-group-attribute precedence-group-attributes?
precedence-group-attribute ::= precedence-group-relation
precedence-group-attribute ::= precedence-group-assignment
precedence-group-attribute ::= precedence-group-associativity

precedence-group-relation ::= "higherThan" ':' precedence-group-names
precedence-group-relation ::= "lowerThan" ':' precedence-group-names

precedence-group-assignment ::= assignment ':' boolean-literal

precedence-group-associativity ::= "associativity" ':' "left"
precedence-group-associativity ::= "associativity" ':' "right"
precedence-group-associativity ::= "associativity" ':' "none"

precedence-group-names ::= precedence-group-name | precedence-group-name ',' precedence-group-names
precedence-group-name ::= identifier

//Grammar of a declaration modifier

declaration-modifier ::= "class" | "convenience" | "dynamic" | "final" | "infix" | "lazy" | "optional" | "override" | "postfix" | "prefix" | "required" | "static" | "unowned" | "unowned(safe)" | "unowned(unsafe)" | "weak"
declaration-modifier ::= access-level-modifier
declaration-modifier ::= mutation-modifier
declaration-modifier ::= actor-isolation-modifier
declaration-modifiers ::= declaration-modifier declaration-modifiers?

access-level-modifier ::= "private" | "private(set)"
access-level-modifier ::= "fileprivate" | "fileprivate(set)"
access-level-modifier ::= "internal" | "internal(set)"
access-level-modifier ::= "package" | "package(set)"
access-level-modifier ::= "public" | "public(set)"
access-level-modifier ::= "open" | "open(set)"

mutation-modifier ::= "mutating" | "nonmutating"

actor-isolation-modifier ::= "nonisolated"

//Attributes
//Grammar of an attribute

attribute ::= '@' attribute-name attribute-argument-clause?
attribute-name ::= identifier
attribute-argument-clause ::= '(' balanced-tokens? ')'
attributes ::= attribute attributes?

balanced-tokens ::= balanced-token balanced-tokens?
balanced-token ::= '(' balanced-tokens? ')'
balanced-token ::= '[' balanced-tokens? ']'
balanced-token ::= '{' balanced-tokens? '}'
///balanced-token ::= Any identifier, keyword, literal, or operator
///balanced-token ::= Any punctuation except (, ), [, ], {, or }

//Patterns
//Grammar of a pattern

pattern ::= wildcard-pattern type-annotation?
pattern ::= identifier-pattern type-annotation?
pattern ::= value-binding-pattern
pattern ::= tuple-pattern type-annotation?
pattern ::= enum-case-pattern
pattern ::= optional-pattern
pattern ::= type-casting-pattern
pattern ::= expression-pattern

//Grammar of a wildcard pattern

wildcard-pattern ::= '_'

//Grammar of an identifier pattern

identifier-pattern ::= identifier

//Grammar of a value-binding pattern

value-binding-pattern ::= "var" pattern | "let" pattern

//Grammar of a tuple pattern

tuple-pattern ::= '(' tuple-pattern-element-list? ')'
tuple-pattern-element-list ::= tuple-pattern-element | tuple-pattern-element ',' tuple-pattern-element-list
tuple-pattern-element ::= pattern | identifier ':' pattern

//Grammar of an enumeration case pattern

enum-case-pattern ::= type-identifier? '.' enum-case-name tuple-pattern?

//Grammar of an optional pattern

optional-pattern ::= identifier-pattern ?

//Grammar of a type casting pattern

type-casting-pattern ::= is-pattern | as-pattern
is-pattern ::= "is" type
as-pattern ::= pattern "as" type

//Grammar of an expression pattern

expression-pattern ::= expression

//Generic Parameters and Arguments
//Grammar of a generic parameter clause

generic-parameter-clause ::= '<' generic-parameter-list '>'
generic-parameter-list ::= generic-parameter | generic-parameter ',' generic-parameter-list
generic-parameter ::= type-name
generic-parameter ::= type-name ':' type-identifier
generic-parameter ::= type-name ':' protocol-composition-type

generic-where-clause ::= "where" requirement-list
requirement-list ::= requirement | requirement ',' requirement-list
requirement ::= conformance-requirement | same-type-requirement

conformance-requirement ::= type-identifier ':' type-identifier
conformance-requirement ::= type-identifier ':' protocol-composition-type
same-type-requirement ::= type-identifier "==" type

//Grammar of a generic argument clause

generic-argument-clause ::= '<' generic-argument-list '>'
generic-argument-list ::= generic-argument | generic-argument ',' generic-argument-list
generic-argument ::= type

Motivation

No response

Alternatives Considered

No response

mingodad commented 2 hours ago

Comparing with the EBNF generated from https://github.com/alex-pinkus/tree-sitter-swift with https://github.com/mingodad/plgh/blob/main/json2ebnf.js the grammar here seems to be missing several pieces (or the other way around).

//
// From tree-sitter-swift-alex-pinkus/src/grammar.json
//
//
// EBNF to generate railroad diagram at 
//      (IPV6) https://www.bottlecaps.de/rr/ui
//      (IPV4) https://rr.red-dove.com/ui
//

source_file ::=
     shebang_line? ( _top_level_statement ( _semi _top_level_statement )* _semi? )?

_semi ::=
     _implicit_semi
    | _explicit_semi

shebang_line ::=
     '#!' [^#x0D#x0A]*

comment ::=
     '//' '.'*

simple_identifier ::=
    /* [_\p{XID_Start}\p{Emoji}&&[^0-9#x23*]]('\p{EMod}'|'\x{FE0F}\x{20E3}'?)?([_\p{XID_Continue}\p{Emoji}\x{200D}]('\p{EMod}'|'\x{FE0F}\x{20E3}'?)?)*
    |*/ '`'[^#x0D#x0A` ]*'`'
    | '\$'[0-9]+
    //| ( '$' [_\p{XID_Start}\p{Emoji}&&[^0-9#x23*]]('\p{EMod}'|'\x{FE0F}\x{20E3}'?)?([_\p{XID_Continue}\p{Emoji}\x{200D}]('\p{EMod}'|'\x{FE0F}\x{20E3}'?)?)* )
    | _contextual_simple_identifier

_contextual_simple_identifier ::=
     'actor'
    | 'async'
    | 'each'
    | 'lazy'
    | 'repeat'
    | 'package'
    | _parameter_ownership_modifier

identifier ::=
     simple_identifier ( _dot simple_identifier )*

_basic_literal ::=
     integer_literal
    | hex_literal
    | oct_literal
    | bin_literal
    | real_literal
    | boolean_literal
    | _string_literal
    | regex_literal
    | 'nil'

real_literal ::=
     ( ( [0-9]+ ( '_'+ [0-9]+ )* ) ( [eE] [+-]? ( [0-9]+ ( '_'+ [0-9]+ )* ) ) | ( [0-9]+ ( '_'+ [0-9]+ )* )? '.' ( [0-9]+ ( '_'+ [0-9]+ )* ) ( [eE] [+-]? ( [0-9]+ ( '_'+ [0-9]+ )* ) )? )

integer_literal ::=
     ( [1-9]? ( [0-9]+ ( '_'+ [0-9]+ )* ) )

hex_literal ::=
     ( '0' [xX] ( [0-9a-fA-F]+ ( '_'+ [0-9a-fA-F]+ )* ) )

oct_literal ::=
     ( '0' [oO] ( [0-7]+ ( '_'+ [0-7]+ )* ) )

bin_literal ::=
     ( '0' [bB] ( [01]+ ( '_'+ [01]+ )* ) )

boolean_literal ::=
     'true'
    | 'false'

_string_literal ::=
     line_string_literal
    | multi_line_string_literal
    | raw_string_literal

line_string_literal ::=
     '"'  ( _line_string_content | _interpolation )* '"' 

_line_string_content ::=
     line_str_text
    | str_escaped_char

line_str_text ::=
     [^\"]+

str_escaped_char ::=
     _escaped_identifier
    | _uni_character_literal

_uni_character_literal ::=
     '\\'  'u' '\{'[0-9a-fA-F]+'\}'

multi_line_string_literal ::=
     '"""' ( _multi_line_string_content | _interpolation )* '"""'

raw_string_literal ::=
     ( raw_str_part raw_str_interpolation raw_str_continuing_indicator? )* raw_str_end_part

raw_str_interpolation ::=
     raw_str_interpolation_start _interpolation_contents ')'

raw_str_interpolation_start ::=
     "#*("

_multi_line_string_content ::=
     multi_line_str_text
    | str_escaped_char
    | '"' 

_interpolation ::=
     '\(' _interpolation_contents ')'

_interpolation_contents ::=
     value_argument ( ',' value_argument )*

_escaped_identifier ::=
     '\'[0\tnr"'#x0A]

multi_line_str_text ::=
     [^\"]+

regex_literal ::=
     _extended_regex_literal
    | _multiline_regex_literal
    | _oneline_regex_literal

_extended_regex_literal ::=
     '#\/'(('\/'[^#x23])|[^#x0A])+'\/#'

_multiline_regex_literal ::=
     '#\/#x0A' ('\/'[^#x23]|[^/])*?'#x0A\/#'

_oneline_regex_literal ::=
     '/' [^ #x09#x0A]?[^/#x0A]*[^ #x09#x0A/] '/'

type_annotation ::=
     ':' _possibly_implicitly_unwrapped_type

_possibly_implicitly_unwrapped_type ::=
     _type '!'?

_type ::=
     type_modifiers? _unannotated_type

_unannotated_type ::=
     user_type | tuple_type | function_type | array_type | dictionary_type | optional_type | metatype | opaque_type | existential_type | protocol_composition_type | type_parameter_pack | type_pack_expansion

user_type ::=
     _simple_user_type ( _dot _simple_user_type )*

_simple_user_type ::=
     simple_identifier type_arguments?

tuple_type ::=
     '(' ( tuple_type_item ( ',' tuple_type_item )* )? ')'
    | _parenthesized_type

tuple_type_item ::=
     _tuple_type_item_identifier? parameter_modifiers? _type

_tuple_type_item_identifier ::=
     wildcard_pattern? simple_identifier ':'

function_type ::=
     ( tuple_type | _unannotated_type ) _async_keyword? throws? _arrow_operator _type

array_type ::=
     '[' _type ']'

dictionary_type ::=
     '[' _type ':' _type ']'

optional_type ::=
     ( user_type | tuple_type | array_type | dictionary_type ) _immediate_quest+

metatype ::=
     _unannotated_type '.' ( 'Type' | 'Protocol' )

_quest ::=
     '?'

_immediate_quest ::=
     '?'

opaque_type ::=
     'some' _unannotated_type

existential_type ::=
     'any' _unannotated_type

type_parameter_pack ::=
     'each' _unannotated_type

type_pack_expansion ::=
     'repeat' _unannotated_type

protocol_composition_type ::=
     _unannotated_type ( '&' _unannotated_type )+

_expression ::=
     simple_identifier | _unary_expression | _binary_expression | ternary_expression | _primary_expression | if_statement | switch_statement | assignment | value_parameter_pack | value_pack_expansion | _expression _immediate_quest

_unary_expression ::=
     postfix_expression
    | call_expression
    | constructor_expression
    | navigation_expression
    | prefix_expression
    | as_expression
    | selector_expression
    | open_start_range_expression
    | open_end_range_expression

postfix_expression ::=
     _expression _postfix_unary_operator

constructor_expression ::=
     ( array_type | dictionary_type | user_type ) constructor_suffix

_parenthesized_type ::=
     '(' ( opaque_type | existential_type | dictionary_type ) ')'

navigation_expression ::=
     ( _navigable_type_expression | _expression | _parenthesized_type ) navigation_suffix

_navigable_type_expression ::=
     user_type
    | array_type
    | dictionary_type

open_start_range_expression ::=
     _range_operator _expression

_range_operator ::=
     _open_ended_range_operator
    | _three_dot_operator

open_end_range_expression ::=
     _expression _three_dot_operator

prefix_expression ::=
     _prefix_unary_operator ( _expression | ( 'async' | 'if' | 'switch' ) )

as_expression ::=
     _expression as_operator _type

selector_expression ::=
     '#selector' '(' ( 'getter:' | 'setter:' )? _expression ')'

_binary_expression ::=
     multiplicative_expression
    | additive_expression
    | range_expression
    | infix_expression
    | nil_coalescing_expression
    | check_expression
    | equality_expression
    | comparison_expression
    | conjunction_expression
    | disjunction_expression
    | bitwise_operation

multiplicative_expression ::=
     _expression _multiplicative_operator _expression

additive_expression ::=
     _expression _additive_operator _expression

range_expression ::=
     _expression _range_operator _expr_hack_at_ternary_binary_suffix

infix_expression ::=
     _expression custom_operator _expr_hack_at_ternary_binary_suffix

nil_coalescing_expression ::=
     _expression _nil_coalescing_operator _expr_hack_at_ternary_binary_suffix

check_expression ::=
     _expression _is_operator _type

comparison_expression ::=
     _expression _comparison_operator _expr_hack_at_ternary_binary_suffix

equality_expression ::=
     _expression _equality_operator _expr_hack_at_ternary_binary_suffix

conjunction_expression ::=
     _expression _conjunction_operator _expr_hack_at_ternary_binary_suffix

disjunction_expression ::=
     _expression _disjunction_operator _expr_hack_at_ternary_binary_suffix

bitwise_operation ::=
     _expression _bitwise_binary_operator _expr_hack_at_ternary_binary_suffix

custom_operator ::=
     [\/]+[*]+
    | _custom_operator

navigation_suffix ::=
     _dot ( simple_identifier | integer_literal )

call_suffix ::=
     value_arguments | _fn_call_lambda_arguments | value_arguments _fn_call_lambda_arguments

constructor_suffix ::=
     _constructor_value_arguments | _fn_call_lambda_arguments | _constructor_value_arguments _fn_call_lambda_arguments

_constructor_value_arguments ::=
     '(' ( value_argument ( ',' value_argument )* )? ')'

_fn_call_lambda_arguments ::=
     lambda_literal ( simple_identifier ':' lambda_literal )*

type_arguments ::=
     '<' _type ( ',' _type )* '>'

value_arguments ::=
     ( '(' ( value_argument ( ',' value_argument )* )? ')' | '[' ( value_argument ( ',' value_argument )* )? ']' )

value_argument_label ::=
     simple_identifier | 'if' | 'switch'

value_argument ::=
     type_modifiers? ( ( value_argument_label ':' )+ | ( value_argument_label ':' )? _expression )

try_expression ::=
     try_operator ( _expression | _binary_expression | call_expression | ternary_expression )

await_expression ::=
     _await_operator ( _expression | call_expression | ternary_expression )

_await_operator ::=
     'await'

ternary_expression ::=
     _expression _quest _expression ':' _expr_hack_at_ternary_binary_suffix

_expr_hack_at_ternary_binary_suffix ::=
     _expression | expr_hack_at_ternary_binary_call

expr_hack_at_ternary_binary_call ::=
     _expression expr_hack_at_ternary_binary_call_suffix

expr_hack_at_ternary_binary_call_suffix ::=
     value_arguments

call_expression ::=
     _expression call_suffix

_primary_expression ::=
     tuple_expression
    | _basic_literal
    | lambda_literal
    | _special_literal
    | _playground_literal
    | array_literal
    | dictionary_literal
    | self_expression
    | super_expression
    | try_expression
    | await_expression
    | _referenceable_operator
    | key_path_expression
    | key_path_string_expression
    | _three_dot_operator

tuple_expression ::=
     '(' ( simple_identifier ':' )? _expression ( ',' ( simple_identifier ':' )? _expression )* ')'

array_literal ::=
     '[' ( _expression ( ',' _expression )* )? ','? ']'

dictionary_literal ::=
     '[' ( ':' | _dictionary_literal_item ( ',' _dictionary_literal_item )* ) ','? ']'

_dictionary_literal_item ::=
     _expression ':' _expression

_special_literal ::=
     '#file'
    | '#fileID'
    | '#filePath'
    | '#line'
    | '#column'
    | '#function'
    | '#dsohandle'

_playground_literal ::=
     ( '#colorLiteral' | '#fileLiteral' | '#imageLiteral' ) '(' simple_identifier ':' _expression ( ',' simple_identifier ':' _expression )* ')'

lambda_literal ::=
     ( '{' | '^{' ) _lambda_type_declaration? statements? '}'

_lambda_type_declaration ::=
     attribute* capture_list lambda_function_type? 'in'

capture_list ::=
     '[' capture_list_item ( ',' capture_list_item )* ']'

capture_list_item ::=
     self_expression
    | ownership_modifier? simple_identifier ( _equal_sign _expression )?

lambda_function_type ::=
     ( lambda_function_type_parameters | '(' lambda_function_type_parameters? ')' ) _async_keyword? throws? ( _arrow_operator _possibly_implicitly_unwrapped_type )?

lambda_function_type_parameters ::=
     lambda_parameter ( ',' lambda_parameter )*

lambda_parameter ::=
     ( self_expression | simple_identifier | simple_identifier? simple_identifier ':' parameter_modifiers? _possibly_implicitly_unwrapped_type )

self_expression ::=
     'self'

super_expression ::=
     'super'

_else_options ::=
     _block
    | if_statement

if_statement ::=
     'if' _if_condition_sequence_item ( ',' _if_condition_sequence_item )* _block ( else _else_options )?

_if_condition_sequence_item ::=
     _if_let_binding
    | _expression
    | availability_condition

_if_let_binding ::=
     _direct_or_indirect_binding ( _equal_sign _expression )? where_clause?

guard_statement ::=
     'guard' _if_condition_sequence_item ( ',' _if_condition_sequence_item )* else _block

switch_statement ::=
     'switch' _expression '{' switch_entry* '}'

switch_entry ::=
     modifiers? ( 'case' switch_pattern ( where_keyword _expression )? ( ',' switch_pattern )* | default_keyword ) ':' statements 'fallthrough'?

switch_pattern ::=
     _binding_pattern_with_expr

do_statement ::=
     'do' _block catch_block*

catch_block ::=
     catch_keyword _binding_pattern_no_expr? where_clause? _block

where_clause ::=
     where_keyword _expression

key_path_expression ::=
     '\\'  ( _simple_user_type | array_type | dictionary_type )? ( '.' _key_path_component )*

key_path_string_expression ::=
     '#keyPath' '(' _expression ')'

_key_path_component ::=
     simple_identifier _key_path_postfixes* | _key_path_postfixes+

_key_path_postfixes ::=
     '?'
    | bang
    | 'self'
    | '[' ( value_argument ( ',' value_argument )* )? ']'

try_operator ::=
     'try' ( _try_operator_type | _fake_try_bang )

_try_operator_type ::=
     '!'
    | '?'

_assignment_and_operator ::=
     '+='
    | '-='
    | '*='
    | '/='
    | '%='
    | _equal_sign

_equality_operator ::=
     '!='
    | '!=='
    | _eq_eq
    | '==='

_comparison_operator ::=
     '<'
    | '>'
    | '<='
    | '>='

_three_dot_operator ::=
     '...'

_open_ended_range_operator ::=
     '..<'

_is_operator ::=
     'is'

_additive_operator ::=
     _plus_then_ws
    | _minus_then_ws
    | '+'
    | '-'

_multiplicative_operator ::=
     '*'
    | '/'
    | '%'

as_operator ::=
     _as
    | _as_quest
    | _as_bang

_prefix_unary_operator ::=
     '++' | '--' | '-' | '+' | bang | '&' | '~' | _dot | custom_operator

_bitwise_binary_operator ::=
     '&'
    | '|'
    | '^'
    | '<<'
    | '>>'

_postfix_unary_operator ::=
     '++'
    | '--'
    | bang

directly_assignable_expression ::=
     _expression

statements ::=
     _local_statement ( _semi _local_statement )* _semi?

_local_statement ::=
     _expression
    | _local_declaration
    | _labeled_statement
    | control_transfer_statement

_top_level_statement ::=
     _expression
    | _global_declaration
    | _labeled_statement
    | _throw_statement

_block ::=
     '{' statements? '}'

_labeled_statement ::=
     statement_label? ( for_statement | while_statement | repeat_while_statement | do_statement | if_statement | guard_statement | switch_statement )

statement_label ::=
     [a-zA-Z_][a-zA-Z_0-9]*':'

for_statement ::=
     'for' try_operator? _await_operator? _binding_pattern_no_expr type_annotation? 'in' _for_statement_collection where_clause? _block

_for_statement_collection ::=
     _expression
    | for_statement_await

for_statement_await ::=
     _await_operator _expression

while_statement ::=
     'while' _if_condition_sequence_item ( ',' _if_condition_sequence_item )* '{' statements? '}'

repeat_while_statement ::=
     'repeat' '{' statements? '}' _implicit_semi* 'while' _if_condition_sequence_item ( ',' _if_condition_sequence_item )*

control_transfer_statement ::=
     _throw_statement
    | _optionally_valueful_control_keyword _expression?

_throw_statement ::=
     throw_keyword _expression

throw_keyword ::=
     'throw'

_optionally_valueful_control_keyword ::=
     'return'
    | 'continue'
    | 'break'
    | 'yield'

assignment ::=
     directly_assignable_expression _assignment_and_operator _expression

value_parameter_pack ::=
     'each' _expression

value_pack_expansion ::=
     'repeat' _expression

availability_condition ::=
     ( '#available' | '#unavailable' ) '(' _availability_argument ( ',' _availability_argument )* ')'

_availability_argument ::=
     identifier integer_literal ( '.' integer_literal )*
    | '*'

_global_declaration ::=
     import_declaration
    | property_declaration
    | typealias_declaration
    | function_declaration
    | init_declaration
    | class_declaration
    | protocol_declaration
    | operator_declaration
    | precedence_group_declaration
    | associatedtype_declaration
    | macro_declaration

_type_level_declaration ::=
     import_declaration
    | property_declaration
    | typealias_declaration
    | function_declaration
    | init_declaration
    | class_declaration
    | protocol_declaration
    | deinit_declaration
    | subscript_declaration
    | operator_declaration
    | precedence_group_declaration
    | associatedtype_declaration

_local_declaration ::=
     _local_property_declaration
    | _local_typealias_declaration
    | _local_function_declaration
    | _local_class_declaration

_local_property_declaration ::=
     _locally_permitted_modifiers? _modifierless_property_declaration

_local_typealias_declaration ::=
     _locally_permitted_modifiers? _modifierless_typealias_declaration

_local_function_declaration ::=
     _locally_permitted_modifiers? _modifierless_function_declaration

_local_class_declaration ::=
     _locally_permitted_modifiers? _modifierless_class_declaration

import_declaration ::=
     modifiers? 'import' _import_kind? identifier

_import_kind ::=
     'typealias'
    | 'struct'
    | 'class'
    | 'enum'
    | 'protocol'
    | 'let'
    | 'var'
    | 'func'

protocol_property_declaration ::=
     modifiers? _binding_kind_and_pattern type_annotation? type_constraints? protocol_property_requirements

protocol_property_requirements ::=
     '{' ( getter_specifier | setter_specifier )* '}'

property_declaration ::=
     modifiers? _modifierless_property_declaration

_modifierless_property_declaration ::=
     _possibly_async_binding_pattern_kind _single_modifierless_property_declaration ( ',' _single_modifierless_property_declaration )*

_single_modifierless_property_declaration ::=
     _no_expr_pattern_already_bound type_annotation? type_constraints? ( _expression_with_willset_didset | _expression_without_willset_didset | willset_didset_block | computed_property )?

_expression_with_willset_didset ::=
     _equal_sign _expression willset_didset_block

_expression_without_willset_didset ::=
     _equal_sign _expression

willset_didset_block ::=
     '{' willset_clause didset_clause? '}'
    | '{' didset_clause willset_clause? '}'

willset_clause ::=
     modifiers? 'willSet' ( '(' simple_identifier ')' )? _block

didset_clause ::=
     modifiers? 'didSet' ( '(' simple_identifier ')' )? _block

typealias_declaration ::=
     modifiers? _modifierless_typealias_declaration

_modifierless_typealias_declaration ::=
     'typealias' simple_identifier type_parameters? _equal_sign _type

function_declaration ::=
     _bodyless_function_declaration function_body

_modifierless_function_declaration ::=
     _modifierless_function_declaration_no_body function_body

_bodyless_function_declaration ::=
     modifiers? 'class'? _modifierless_function_declaration_no_body

_modifierless_function_declaration_no_body ::=
     _non_constructor_function_decl type_parameters? _function_value_parameters _async_keyword? throws? ( _arrow_operator _possibly_implicitly_unwrapped_type )? type_constraints?

function_body ::=
     _block

macro_declaration ::=
     _macro_head simple_identifier type_parameters? _macro_signature macro_definition? type_constraints?

_macro_head ::=
     modifiers? 'macro'

_macro_signature ::=
     _function_value_parameters ( _arrow_operator _unannotated_type )?

macro_definition ::=
     _equal_sign ( _expression | external_macro_definition )

external_macro_definition ::=
     '#externalMacro' value_arguments

class_declaration ::=
     modifiers? _modifierless_class_declaration

_modifierless_class_declaration ::=
     ( 'class' | 'struct' | 'actor' ) simple_identifier type_parameters? ( ':' _inheritance_specifiers )? type_constraints? class_body | 'extension' _unannotated_type type_parameters? ( ':' _inheritance_specifiers )? type_constraints? class_body | 'indirect'? 'enum' simple_identifier type_parameters? ( ':' _inheritance_specifiers )? type_constraints? enum_class_body

class_body ::=
     '{' _class_member_declarations? '}'

_inheritance_specifiers ::=
     _annotated_inheritance_specifier ( ( ',' | '&' ) _annotated_inheritance_specifier )*

inheritance_specifier ::=
     ( user_type | function_type )

_annotated_inheritance_specifier ::=
     attribute* inheritance_specifier

type_parameters ::=
     '<' type_parameter ( ',' type_parameter )* type_constraints? '>'

type_parameter ::=
     type_parameter_modifiers? _type_parameter_possibly_packed ( ':' _type )?

_type_parameter_possibly_packed ::=
     simple_identifier
    | type_parameter_pack

type_constraints ::=
     where_keyword type_constraint ( ',' type_constraint )*

type_constraint ::=
     inheritance_constraint
    | equality_constraint

inheritance_constraint ::=
     attribute* _constrained_type ':' _possibly_implicitly_unwrapped_type

equality_constraint ::=
     attribute* _constrained_type ( _equal_sign | _eq_eq ) _type

_constrained_type ::=
     identifier
    | _unannotated_type ( '.' simple_identifier ( '.' simple_identifier )* )?

_class_member_separator ::=
     _semi
    | multiline_comment

_class_member_declarations ::=
     _type_level_declaration ( _class_member_separator _type_level_declaration )* _class_member_separator?

_function_value_parameters ::=
     ( '(' ( _function_value_parameter ( ',' _function_value_parameter )* )? ')' )+

_function_value_parameter ::=
     attribute? parameter ( _equal_sign _expression )?

parameter ::=
     simple_identifier? simple_identifier ':' parameter_modifiers? _possibly_implicitly_unwrapped_type _three_dot_operator?

_non_constructor_function_decl ::=
     'func' ( simple_identifier | _referenceable_operator )

_referenceable_operator ::=
     custom_operator
    | _comparison_operator
    | _additive_operator
    | _multiplicative_operator
    | _equality_operator
    | _comparison_operator
    | _assignment_and_operator
    | '++'
    | '--'
    | bang
    | '~'
    | '|'
    | '^'
    | '<<'
    | '>>'
    | '&'

_equal_sign ::=
     _eq_custom

_eq_eq ::=
     _eq_eq_custom

_dot ::=
     _dot_custom

_arrow_operator ::=
     _arrow_operator_custom

_conjunction_operator ::=
     _conjunction_operator_custom

_disjunction_operator ::=
     _disjunction_operator_custom

_nil_coalescing_operator ::=
     _nil_coalescing_operator_custom

_as ::=
     _as_custom

_as_quest ::=
     _as_quest_custom

_as_bang ::=
     _as_bang_custom

bang ::=
     _bang_custom
    | '!'

_async_keyword ::=
     _async_keyword_custom

_async_modifier ::=
     'async'

throws ::=
     _throws_keyword
    | _rethrows_keyword

enum_class_body ::=
     '{' ( enum_entry | _type_level_declaration )* '}'

enum_entry ::=
     modifiers? 'indirect'? 'case' simple_identifier _enum_entry_suffix? ( ',' simple_identifier _enum_entry_suffix? )* ';'?

_enum_entry_suffix ::=
     enum_type_parameters
    | _equal_sign _expression

enum_type_parameters ::=
     '(' ( ( wildcard_pattern? simple_identifier ':' )? _type ( _equal_sign _expression )? ( ',' ( wildcard_pattern? simple_identifier ':' )? _type ( _equal_sign _expression )? )* )? ')'

protocol_declaration ::=
     modifiers? 'protocol' simple_identifier type_parameters? ( ':' _inheritance_specifiers )? type_constraints? protocol_body

protocol_body ::=
     '{' _protocol_member_declarations? '}'

_protocol_member_declarations ::=
     _protocol_member_declaration ( _semi _protocol_member_declaration )* _semi?

_protocol_member_declaration ::=
     ( _bodyless_function_declaration function_body? )
    | init_declaration
    | deinit_declaration
    | protocol_property_declaration
    | typealias_declaration
    | associatedtype_declaration
    | subscript_declaration

init_declaration ::=
     modifiers? 'class'? 'init' ( _quest | bang )? type_parameters? _function_value_parameters _async_keyword? throws? type_constraints? function_body?

deinit_declaration ::=
     modifiers? 'deinit' function_body

subscript_declaration ::=
     modifiers? 'subscript' type_parameters? _function_value_parameters ( _arrow_operator _possibly_implicitly_unwrapped_type )? type_constraints? computed_property

computed_property ::=
     '{' ( statements | ( computed_getter | computed_setter | computed_modify )* ) '}'

computed_getter ::=
     attribute* getter_specifier _block?

computed_modify ::=
     attribute* modify_specifier _block?

computed_setter ::=
     attribute* setter_specifier ( '(' simple_identifier ')' )? _block?

getter_specifier ::=
     mutation_modifier? 'get' _getter_effects?

setter_specifier ::=
     mutation_modifier? 'set'

modify_specifier ::=
     mutation_modifier? '_modify'

_getter_effects ::=
     ( _async_keyword | throws )+

operator_declaration ::=
     ( 'prefix' | 'infix' | 'postfix' ) 'operator' _referenceable_operator ( ':' simple_identifier )? deprecated_operator_declaration_body?

deprecated_operator_declaration_body ::=
     '{' ( simple_identifier | _basic_literal )* '}'

precedence_group_declaration ::=
     'precedencegroup' simple_identifier '{' precedence_group_attributes? '}'

precedence_group_attributes ::=
     precedence_group_attribute+

precedence_group_attribute ::=
     simple_identifier ':' ( simple_identifier | boolean_literal )

associatedtype_declaration ::=
     modifiers? 'associatedtype' simple_identifier ( ':' _type )? type_constraints? ( _equal_sign _type )?

attribute ::=
     '@' user_type ( '(' _attribute_argument ( ',' _attribute_argument )* ')' )?

_attribute_argument ::=
     simple_identifier ':' _expression
    | _expression
    | ( simple_identifier ':' )+
    | simple_identifier+ integer_literal ( '.' integer_literal )*

_universally_allowed_pattern ::=
     wildcard_pattern
    | _tuple_pattern
    | _type_casting_pattern
    | _case_pattern

_bound_identifier ::=
     simple_identifier

_binding_pattern_no_expr ::=
     ( _universally_allowed_pattern | _binding_pattern | _bound_identifier ) _quest?

_no_expr_pattern_already_bound ::=
     ( _universally_allowed_pattern | _bound_identifier ) _quest?

_binding_pattern_with_expr ::=
     ( _universally_allowed_pattern | _binding_pattern | _expression ) _quest?

_non_binding_pattern_with_expr ::=
     ( _universally_allowed_pattern | _expression ) _quest?

_direct_or_indirect_binding ::=
     ( _binding_kind_and_pattern | 'case' _binding_pattern_no_expr ) type_annotation?

value_binding_pattern ::=
     ( 'var' | 'let' )

_possibly_async_binding_pattern_kind ::=
     _async_modifier? value_binding_pattern

_binding_kind_and_pattern ::=
     _possibly_async_binding_pattern_kind _no_expr_pattern_already_bound

wildcard_pattern ::=
     '_'

_tuple_pattern_item ::=
     simple_identifier ':' _binding_pattern_with_expr
    | _binding_pattern_with_expr

_tuple_pattern ::=
     '(' _tuple_pattern_item ( ',' _tuple_pattern_item )* ')'

_case_pattern ::=
     'case'? user_type? _dot simple_identifier _tuple_pattern?

_type_casting_pattern ::=
     'is' _type
    | _binding_pattern_no_expr _as _type

_binding_pattern ::=
     'case'? value_binding_pattern _no_expr_pattern_already_bound

modifiers ::=
     _non_local_scope_modifier | _locally_permitted_modifiers+

_locally_permitted_modifiers ::=
     ( attribute | _locally_permitted_modifier )+

parameter_modifiers ::=
     parameter_modifier+

_modifier ::=
     _non_local_scope_modifier
    | _locally_permitted_modifier

_non_local_scope_modifier ::=
     member_modifier
    | visibility_modifier
    | function_modifier
    | mutation_modifier
    | property_modifier
    | parameter_modifier

_locally_permitted_modifier ::=
     ownership_modifier
    | inheritance_modifier
    | property_behavior_modifier

property_behavior_modifier ::=
     'lazy'

type_modifiers ::=
     attribute+

member_modifier ::=
     'override'
    | 'convenience'
    | 'required'
    | 'nonisolated'

visibility_modifier ::=
     ( 'public' | 'private' | 'internal' | 'fileprivate' | 'open' | 'package' ) ( '(' 'set' ')' )?

type_parameter_modifiers ::=
     attribute+

function_modifier ::=
     'infix'
    | 'postfix'
    | 'prefix'

mutation_modifier ::=
     'mutating'
    | 'nonmutating'

property_modifier ::=
     'static'
    | 'dynamic'
    | 'optional'
    | 'class'
    | 'distributed'

inheritance_modifier ::=
     'final'

parameter_modifier ::=
     'inout'
    | '@escaping'
    | '@autoclosure'
    | _parameter_ownership_modifier

ownership_modifier ::=
     'weak'
    | 'unowned'
    | 'unowned(safe)'
    | 'unowned(unsafe)'

_parameter_ownership_modifier ::=
     'borrowing'
    | 'consuming'

use_site_target ::=
     ( 'property' | 'get' | 'set' | 'receiver' | 'param' | 'setparam' | 'delegate' ) ':'

directive ::=
     '#if' '.'* | '#elseif' '.'* | '#else' '.'* | '#endif' '.'* | '#sourceLocation'([^#x0D#x0A]*)

diagnostic ::=
     '#error'([^#x0D#x0A]*) | '#warning'([^#x0D#x0A]*)

unused_for_backward_compatibility ::=
     'unused1'
    | 'unused2'