Lexical Structure

The lexical structure of Swift describes the lowest-level pieces of source code: the characters and tokens the compiler reads before it ever thinks about meaning. This reference covers whitespace, comments, identifiers, keywords, literals, and how operators are recognized.

Whitespace and comments

Whitespace (spaces, tabs, newlines) separates tokens and is otherwise insignificant — Swift does not use indentation to define blocks. Whitespace is, however, used to disambiguate whether an operator is a prefix, postfix, or infix operator (see below).

Comments are treated as whitespace. Single-line comments begin with //; multiline comments are delimited by /* and */ and, unlike C, may be nested.

// A single-line comment
/* A multiline comment
   /* that nests cleanly */
   and continues here */

Identifiers

An identifier names a constant, variable, type, function, or other entity. It begins with a Unicode letter, an underscore, or certain other Unicode scalars, and may continue with letters, digits, underscores, and combining marks. Identifiers are case-sensitive.

To use a reserved word as an identifier, wrap it in backticks. Identifiers beginning with $ (such as $0) are reserved for the compiler — for closure shorthand arguments and projected property-wrapper values.

let `class` = "named with a backtick-escaped keyword"
let café = 42          // Unicode letters are allowed

Keywords and punctuation

Keywords are reserved words with a fixed meaning. They fall into rough groups: declarations (let, var, func, struct, class, actor, enum, protocol, extension), statements (if, guard, for, while, switch, return, defer), expressions and types (self, Self, super, nil, true, any, some), and concurrency (async, await).

Some words are keywords only in particular contexts (for example get, set, willSet, didSet, convenience, nonisolated). Outside that context they may be used as identifiers without backticks.

Punctuation tokens include ( ) { } [ ] . , : ; = @ # & -> and the backtick. These are not operators and cannot be overloaded or used to form custom operators.

Literals

A literal is the source-code representation of a value. Swift supports the following kinds:

KindExamples
Integer42, 0b1010, 0o52, 0x2A, 1_000_000
Floating-point3.14, 6.022e23, 0x1p4
String"hi", multiline """...""", raw #"...\n..."#
Regex/\d+/, extended #/ a b /#
Booleantrue, false
Nilnil

Numeric literals are untyped until used — the same 42 can be an Int, Double, or any type conforming to the relevant ExpressibleBy…Literal protocol. Underscores anywhere in a numeric literal are ignored and aid readability.

let hex = 0xFF            // → 255
let million = 1_000_000
let pattern = /\d{3}-\d{4}/  // a Regex literal
let raw = #"C:\path\to\file"# // no escaping needed

Note: Regex literals were stabilized in Swift 5.7 and are a normal part of Swift 6. Use the extended #/…/# delimiter when a bare /…/ would be ambiguous with division.

Operators

Operators are built from a set of operator characters such as + - * / = ! < > & | ^ ~ ? %. Swift lets you define custom operators from these characters, so the lexer must decide what each operator is from how it's spelled and the whitespace around it:

This is why a+b, a + b, and a +b can parse differently. The tokens =, ->, //, /*, */, ., the lone ? and the prefix & are reserved and cannot be redefined as custom operators.

Watch out: a dot (.) may appear in a custom operator only if the operator begins with a dot. So .+. is a valid operator name, but +.+ is parsed as + followed by .+.

Summary

At the lexical level, Swift source is a stream of identifiers, keywords, literals, operators, and punctuation, with whitespace and comments acting as separators. The most distinctly Swift-flavored rules here are backtick escaping for keywords, the rich literal set (including regex and raw strings), and the whitespace-sensitive classification of operators.