Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Токены

Lexer
Token
      RESERVED_TOKEN
    | RAW_IDENTIFIER
    | CHAR_LITERAL
    | STRING_LITERAL
    | RAW_STRING_LITERAL
    | BYTE_LITERAL
    | BYTE_STRING_LITERAL
    | RAW_BYTE_STRING_LITERAL
    | C_STRING_LITERAL
    | RAW_C_STRING_LITERAL
    | INTEGER_LITERAL
    | FLOAT_LITERAL
    | LIFETIME_TOKEN
    | PUNCTUATION
    | IDENTIFIER_OR_KEYWORD

Токены — это примитивные конструкции в грамматике, определяемые регулярными (нерекурсивными) языками. Исходный код Rust может быть разбит на следующие виды токенов:

В грамматике этой документации “простые” токены представлены в форме продукций таблицы строк и отображаются шрифтом monospace.

Литералы

Литералы — это токены, используемые в литеральных выражениях.

Примеры

Символы и строки

ПримерКол-во #1СимволыЭкранирования
Символьный'H'0Все UnicodeКавычки & ASCII & Unicode
Строковый"hello"0Все UnicodeКавычки & ASCII & Unicode
Сырая строкаr#"hello"#<256Все UnicodeN/A
Байтовыйb'H'0Все ASCIIКавычки & Байтовые
Байтовая строкаb"hello"0Все ASCIIКавычки & Байтовые
Сырая байтовая строкаbr#"hello"#<256Все ASCIIN/A
C-строкаc"hello"0Все UnicodeКавычки & Байтовые & Unicode
Сырая C-строкаcr#"hello"#<256Все UnicodeN/A

Экранирования ASCII

Имя
\x417-битный код символа (ровно 2 цифры, до 0x7F)
\nПеревод строки (Newline)
\rВозврат каретки (Carriage return)
\tТабуляция (Tab)
\\Обратная косая черта (Backslash)
\0Нуль (Null)

Байтовые экранирования

Имя
\x7F8-битный код символа (ровно 2 цифры)
\nПеревод строки (Newline)
\rВозврат каретки (Carriage return)
\tТабуляция (Tab)
\\Обратная косая черта (Backslash)
\0Нуль (Null)

Экранирования Unicode

Имя
\u{7FFF}24-битный код символа Unicode (до 6 цифр)

Экранирования кавычек

Имя
\'Одинарная кавычка
\"Двойная кавычка

Числа

Числовые литералы2ПримерЭкспонента
Десятичное целое98_222N/A
Шестнадцатеричное целое0xffN/A
Восьмеричное целое0o77N/A
Двоичное целое0b1111_0000N/A
Число с плавающей точкой123.0E+77Опционально

Суффиксы

Суффикс — это последовательность символов, следующая за основной частью литерала (без пробелов между ними), имеющая ту же форму, что и несырой идентификатор или ключевое слово.

Lexer
SUFFIXIDENTIFIER_OR_KEYWORDкроме _

SUFFIX_NO_ESUFFIXне начинающийся с e или E

SUFFIX_NO_E не начинающийся с `e` или `E` SUFFIX

Любой вид литерала (строковый, целочисленный и т.д.) с любым суффиксом является допустимым токеном.

Токен литерала с любым суффиксом может быть передан в макрос без возникновения ошибки. Сам макрос решит, как интерпретировать такой токен и следует ли выдавать ошибку. В частности, спецификатор фрагмента literal для макросов по примеру сопоставляет токены литералов с произвольными суффиксами.

#![allow(unused)]
fn main() {
macro_rules! blackhole { ($tt:tt) => () }
macro_rules! blackhole_lit { ($l:literal) => () }

blackhole!("string"suffix); // OK
blackhole_lit!(1suffix); // OK
}

Однако суффиксы на токенах литералов, которые интерпретируются как литеральные выражения или шаблоны, ограничены. Любые суффиксы отвергаются на нечисловых токенах литералов, а числовые токены литералов принимаются только с суффиксами из списка ниже.

Целые числаС плавающей точкой
u8, i8, u16, i16, u32, i32, u64, i64, u128, i128, usize, isizef32, f64

Символьные и строковые литералы

Символьные литералы

Lexer
CHAR_LITERAL
    '
        ( ~[' \ LF CR TAB] | QUOTE_ESCAPE | ASCII_ESCAPE | UNICODE_ESCAPE )
    ' SUFFIX?

QUOTE_ESCAPE\' | \"

ASCII_ESCAPE
      \x OCT_DIGIT HEX_DIGIT
    | \n | \r | \t | \\ | \0

UNICODE_ESCAPE
    \u{ ( HEX_DIGIT _* )1..6 }

Символьный литерал — это одиночный символ Unicode, заключённый между двумя символами U+0027 (одинарная кавычка), за исключением самого U+0027, который должен быть экранирован предшествующим символом U+005C (\).

Строковые литералы

Lexer
STRING_LITERAL
    " (
        ~[" \ CR]
      | QUOTE_ESCAPE
      | ASCII_ESCAPE
      | UNICODE_ESCAPE
      | STRING_CONTINUE
    )* " SUFFIX?

STRING_CONTINUE\ LF

Строковый литерал — это последовательность любых символов Unicode, заключённая между двумя символами U+0022 (двойная кавычка), за исключением самого U+0022, который должен быть экранирован предшествующим символом U+005C (\).

Разрывы строк, представленные символом U+000A (LF), допускаются в строковых литералах. Символ U+000D (CR) не может появляться в строковом литерале. Когда неэкранированный символ U+005C (\) встречается непосредственно перед разрывом строки, разрыв строки не появляется в строке, представленной токеном. Подробнее см. Экранирования продолжения строки.

Символьные экранирования

Некоторые дополнительные экранирования доступны либо в символьных, либо в несырых строковых литералах. Экранирование начинается с U+005C (\) и продолжается одной из следующих форм:

  • 7-битное экранирование кодовой точки начинается с U+0078 (x) и следует ровно две шестнадцатеричные цифры со значением до 0x7F. Оно обозначает символ ASCII со значением, равным предоставленному шестнадцатеричному значению. Более высокие значения не допускаются, поскольку неясно, означают ли они кодовые точки Unicode или байтовые значения.
  • 24-битное экранирование кодовой точки начинается с U+0075 (u) и следует до шести шестнадцатеричных цифр, окружённых фигурными скобками U+007B ({) и U+007D (}). Оно обозначает кодовую точку Unicode, равную предоставленному шестнадцатеричному значению.
  • Экранирование пробельного символа — это один из символов U+006E (n), U+0072 (r) или U+0074 (t), обозначающих значения Unicode U+000A (LF), U+000D (CR) или U+0009 (HT) соответственно.
  • Нулевое экранирование — это символ U+0030 (0) и обозначает значение Unicode U+0000 (NUL).
  • Экранирование обратной косой черты — это символ U+005C (\), который должен быть экранирован, чтобы обозначить сам себя.

Сырые строковые литералы

Lexer
RAW_STRING_LITERALr RAW_STRING_CONTENT SUFFIX?

RAW_STRING_CONTENT
      " ( ~CR )* (non-greedy) "
    | # RAW_STRING_CONTENT #

Сырые строковые литералы не обрабатывают никакие экранирования. Они начинаются с символа U+0072 (r), за которым следует менее 256 символов U+0023 (#) и символ U+0022 (двойная кавычка).

Тело сырой строки может содержать любую последовательность символов Unicode, кроме U+000D (CR). Оно завершается только другим символом U+0022 (двойная кавычка), за которым следует то же количество символов U+0023 (#), которое предшествовало открывающему символу U+0022 (двойная кавычка).

Все символы Unicode, содержащиеся в теле сырой строки, представляют самих себя, символы U+0022 (двойная кавычка) (кроме случая, когда за ними следует по крайней мере столько же символов U+0023 (#), сколько было использовано для начала сырого строкового литерала) или U+005C (\) не имеют никакого специального значения.

Примеры строковых литералов:

#![allow(unused)]
fn main() {
"foo"; r"foo";                     // foo
"\"foo\""; r#""foo""#;             // "foo"

"foo #\"# bar";
r##"foo #"# bar"##;                // foo #"# bar

"\x52"; "R"; r"R";                 // R
"\\x52"; r"\x52";                  // \x52
}

Байтовые и байтовые строковые литералы

Байтовые литералы

Lexer
BYTE_LITERAL
    b' ( ASCII_FOR_CHAR | BYTE_ESCAPE ) ' SUFFIX?

ASCII_FOR_CHAR
    <любой ASCII (т.е. 0x00 до 0x7F) кроме ', \, LF, CR или TAB>

BYTE_ESCAPE
      \x HEX_DIGIT HEX_DIGIT
    | \n | \r | \t | \\ | \0 | \' | \"

ASCII_FOR_CHAR любой ASCII (т.е. 0x00 до 0x7F) кроме `'`, `\`, LF, CR или TAB

Байтовый литерал — это одиночный символ ASCII (в диапазоне U+0000 до U+007F) или одиночное экранирование, перед которым стоят символы U+0062 (b) и U+0027 (одинарная кавычка), и после которого следует символ U+0027. Если символ U+0027 присутствует внутри литерала, он должен быть экранирован предшествующим символом U+005C (\). Он эквивалентен числовому литералу беззнакового 8-битного целого числа u8.

Байтовые строковые литералы

Lexer
BYTE_STRING_LITERAL
    b" ( ASCII_FOR_STRING | BYTE_ESCAPE | STRING_CONTINUE )* " SUFFIX?

ASCII_FOR_STRING
    <любой ASCII (т.е 0x00 до 0x7F) кроме ", \ или CR>

ASCII_FOR_STRING любой ASCII (т.е 0x00 до 0x7F) кроме `"`, `\` или CR

Несырой байтовый строковый литерал — это последовательность символов ASCII и экранирований, перед которой стоят символы U+0062 (b) и U+0022 (двойная кавычка), и после которой следует символ U+0022. Если символ U+0022 присутствует внутри литерала, он должен быть экранирован предшествующим символом U+005C (\). Альтернативно, байтовый строковый литерал может быть сырым байтовым строковым литералом, определённым ниже.

Разрывы строк, представленные символом U+000A (LF), допускаются в байтовых строковых литералах. Символ U+000D (CR) не может появляться в байтовом строковом литерале. Когда неэкранированный символ U+005C (\) встречается непосредственно перед разрывом строки, разрыв строки не появляется в строке, представленной токеном. Подробнее см. Экранирования продолжения строки.

Некоторые дополнительные экранирования доступны либо в байтовых, либо в несырых байтовых строковых литералах. Экранирование начинается с U+005C (\) и продолжается одной из следующих форм:

  • Байтовое экранирование начинается с U+0078 (x) и следует ровно две шестнадцатеричные цифры. Оно обозначает байт, равный предоставленному шестнадцатеричному значению.
  • Экранирование пробельного символа — это один из символов U+006E (n), U+0072 (r) или U+0074 (t), обозначающих байтовые значения 0x0A (ASCII LF), 0x0D (ASCII CR) или 0x09 (ASCII HT) соответственно.
  • Нулевое экранирование — это символ U+0030 (0) и обозначает байтовое значение 0x00 (ASCII NUL).
  • Экранирование обратной косой черты — это символ U+005C (\), который должен быть экранирован, чтобы обозначить своё ASCII-представление 0x5C.

Сырые байтовые строковые литералы

Lexer
RAW_BYTE_STRING_LITERAL
    br RAW_BYTE_STRING_CONTENT SUFFIX?

RAW_BYTE_STRING_CONTENT
      " ASCII_FOR_RAW* (non-greedy) "
    | # RAW_BYTE_STRING_CONTENT #

ASCII_FOR_RAW
    <любой ASCII (т.е. 0x00 до 0x7F) кроме CR>

Сырые байтовые строковые литералы не обрабатывают никакие экранирования. Они начинаются с символа U+0062 (b), за которым следует U+0072 (r), за которым следует менее 256 символов U+0023 (#) и символ U+0022 (двойная кавычка).

Тело сырой строки может содержать любую последовательность символов ASCII, кроме U+000D (CR). Оно завершается только другим символом U+0022 (двойная кавычка), за которым следует то же количество символов U+0023 (#), которое предшествовало открывающему символу U+0022 (двойная кавычка). Сырой байтовый строковый литерал не может содержать никаких не-ASCII байтов.

Все символы, содержащиеся в теле сырой строки, представляют своё ASCII-представление, символы U+0022 (двойная кавычка) (кроме случая, когда за ними следует по крайней мере столько же символов U+0023 (#), сколько было использовано для начала сырого строкового литерала) или U+005C (\) не имеют никакого специального значения.

Примеры байтовых строковых литералов:

#![allow(unused)]
fn main() {
b"foo"; br"foo";                     // foo
b"\"foo\""; br#""foo""#;             // "foo"

b"foo #\"# bar";
br##"foo #"# bar"##;                 // foo #"# bar

b"\x52"; b"R"; br"R";                // R
b"\\x52"; br"\x52";                  // \x52
}

C-строковые и сырые C-строковые литералы

C-строковые литералы

Lexer
C_STRING_LITERAL
    c" (
        ~[" \ CR NUL]
      | BYTE_ESCAPEкроме \0 или \x00
      | UNICODE_ESCAPEкроме \u{0}, \u{00}, …, \u{000000}
      | STRING_CONTINUE
    )* " SUFFIX?

C_STRING_LITERAL c" ⚠️ with the exception of " \ CR NUL CHAR кроме `\0` или `\x00` BYTE_ESCAPE кроме `\u{0}`, `\u{00}`, …, `\u{000000}` UNICODE_ESCAPE STRING_CONTINUE " SUFFIX

C-строковый литерал — это последовательность символов Unicode и экранирований, перед которой стоят символы U+0063 (c) и U+0022 (двойная кавычка), и после которой следует символ U+0022. Если символ U+0022 присутствует внутри литерала, он должен быть экранирован предшествующим символом U+005C (\). Альтернативно, C-строковый литерал может быть сырым C-строковым литералом, определённым ниже.

C-строки неявно завершаются байтом 0x00, поэтому C-строковый литерал c"" эквивалентен ручному созданию &CStr из байтового строкового литерала b"\x00". Кроме неявного терминатора, байт 0x00 не допускается внутри C-строки.

Разрывы строк, представленные символом U+000A (LF), допускаются в C-строковых литералах. Символ U+000D (CR) не может появляться в C-строковом литерале. Когда неэкранированный символ U+005C (\) встречается непосредственно перед разрывом строки, разрыв строки не появляется в строке, представленной токеном. Подробнее см. Экранирования продолжения строки.

Некоторые дополнительные экранирования доступны в несырых C-строковых литералах. Экранирование начинается с U+005C (\) и продолжается одной из следующих форм:

  • Байтовое экранирование начинается с U+0078 (x) и следует ровно две шестнадцатеричные цифры. Оно обозначает байт, равный предоставленному шестнадцатеричному значению.
  • 24-битное экранирование кодовой точки начинается с U+0075 (u) и следует до шести шестнадцатеричных цифр, окружённых фигурными скобками U+007B ({) и U+007D (}). Оно обозначает кодовую точку Unicode, равную предоставленному шестнадцатеричному значению, закодированную как UTF-8.
  • Экранирование пробельного символа — это один из символов U+006E (n), U+0072 (r) или U+0074 (t), обозначающих байтовые значения 0x0A (ASCII LF), 0x0D (ASCII CR) или 0x09 (ASCII HT) соответственно.
  • Экранирование обратной косой черты — это символ U+005C (\), который должен быть экранирован, чтобы обозначить своё ASCII-представление 0x5C.

C-строка представляет байты без определённой кодировки, но C-строковый литерал может содержать символы Unicode выше U+007F. Такие символы будут заменены байтами UTF-8 представления этого символа.

Следующие C-строковые литералы эквивалентны:

#![allow(unused)]
fn main() {
c"æ";        // LATIN SMALL LETTER AE (U+00E6)
c"\u{00E6}";
c"\xC3\xA6";
}

2021 Edition differences

C-строковые литералы принимаются в редакции 2021 или позже. В более ранних редакциях токен c"" лексируется как c "".

Сырые C-строковые литералы

Lexer
RAW_C_STRING_LITERAL
    cr RAW_C_STRING_CONTENT SUFFIX?

RAW_C_STRING_CONTENT
      " ( ~[CR NUL] )* (non-greedy) "
    | # RAW_C_STRING_CONTENT #

Сырые C-строковые литералы не обрабатывают никакие экранирования. Они начинаются с символа U+0063 (c), за которым следует U+0072 (r), за которым следует менее 256 символов U+0023 (#) и символ U+0022 (двойная кавычка).

Тело сырой C-строки может содержать любую последовательность символов Unicode, кроме U+0000 (NUL) и U+000D (CR). Оно завершается только другим символом U+0022 (двойная кавычка), за которым следует то же количество символов U+0023 (#), которое предшествовало открывающему символу U+0022 (двойная кавычка).

Все символы, содержащиеся в теле сырой C-строки, представляют самих себя в кодировке UTF-8. Символы U+0022 (двойная кавычка) (кроме случая, когда за ними следует по крайней мере столько же символов U+0023 (#), сколько было использовано для начала сырого C-строкового литерала) или U+005C (\) не имеют никакого специального значения.

2021 Edition differences

Сырые C-строковые литералы принимаются в редакции 2021 или позже. В более ранних редакциях токен cr"" лексируется как cr "", а cr#""# лексируется как cr #""# (что неграмматично).

Примеры C-строковых и сырых C-строковых литералов

#![allow(unused)]
fn main() {
c"foo"; cr"foo";                     // foo
c"\"foo\""; cr#""foo""#;             // "foo"

c"foo #\"# bar";
cr##"foo #"# bar"##;                 // foo #"# bar

c"\x52"; c"R"; cr"R";                // R
c"\\x52"; cr"\x52";                  // \x52
}

Целочисленные литералы

Lexer
INTEGER_LITERAL
    ( DEC_LITERAL | BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) SUFFIX_NO_E?

DEC_LITERALDEC_DIGIT ( DEC_DIGIT | _ )*

BIN_LITERAL0b ( BIN_DIGIT | _ )* BIN_DIGIT ( BIN_DIGIT | _ )*

OCT_LITERAL0o ( OCT_DIGIT | _ )* OCT_DIGIT ( OCT_DIGIT | _ )*

HEX_LITERAL0x ( HEX_DIGIT | _ )* HEX_DIGIT ( HEX_DIGIT | _ )*

BIN_DIGIT → [0-1]

OCT_DIGIT → [0-7]

DEC_DIGIT → [0-9]

HEX_DIGIT → [0-9 a-f A-F]

Целочисленный литерал имеет одну из четырёх форм:

  • Десятичный литерал начинается с десятичной цифры и продолжается любым сочетанием десятичных цифр и знаков подчёркивания.
  • Шестнадцатеричный литерал начинается с последовательности символов U+0030 U+0078 (0x) и продолжается любым сочетанием (с как минимум одной цифрой) шестнадцатеричных цифр и знаков подчёркивания.
  • Восьмеричный литерал начинается с последовательности символов U+0030 U+006F (0o) и продолжается любым сочетанием (с как минимум одной цифрой) восьмеричных цифр и знаков подчёркивания.
  • Двоичный литерал начинается с последовательности символов U+0030 U+0062 (0b) и продолжается любым сочетанием (с как минимум одной цифрой) двоичных цифр и знаков подчёркивания.

Как и любой литерал, целочисленный литерал может следовать (непосредственно, без пробелов) за суффиксом, как описано выше. Суффикс не может начинаться с e или E, так как это будет интерпретировано как экспонента литерала с плавающей точкой. См. Целочисленные литеральные выражения для получения информации о влиянии этих суффиксов.

Примеры целочисленных литералов, которые принимаются как литеральные выражения:

#![allow(unused)]
fn main() {
#![allow(overflowing_literals)]
123;
123i32;
123u32;
123_u32;

0xff;
0xff_u8;
0x01_f32; // целое число 7986, не число с плавающей точкой 1.0
0x01_e3;  // целое число 483, не число с плавающей точкой 1000.0

0o70;
0o70_i16;

0b1111_1111_1001_0000;
0b1111_1111_1001_0000i64;
0b________1;

0usize;

// Эти числа слишком велики для своего типа, но принимаются как литеральные выражения.
128_i8;
256_u8;

// Это целочисленный литерал, принимаемый как литеральное выражение с плавающей точкой.
5f32;
}

Обратите внимание, что -1i8, например, анализируется как два токена: - followed by 1i8.

Примеры целочисленных литералов, которые не принимаются как литеральные выражения:

#![allow(unused)]
fn main() {
#[cfg(false)] {
0invalidSuffix;
123AFB43;
0b010a;
0xAB_CD_EF_GH;
0b1111_f32;
}
}

Индекс кортежа

Индекс кортежа используется для обращения к полям кортежей, кортежных структур и кортежных вариантов перечислений.

Индексы кортежа сравниваются с токеном литерала напрямую. Индексы кортежа начинаются с 0, и каждый последующий индекс увеличивает значение на 1 как десятичное значение. Таким образом, совпадут только десятичные значения, и значение не должно иметь никаких лишних префиксных символов 0.

Индексы кортежа не могут включать никакие суффиксы (такие как usize).

#![allow(unused)]
fn main() {
let example = ("dog", "cat", "horse");
let dog = example.0;
let cat = example.1;
// Следующие примеры недопустимы.
let cat = example.01;  // ОШИБКА: нет поля с именем `01`
let horse = example.0b10;  // ОШИБКА: нет поля с именем `0b10`
let unicorn = example.0usize; // ОШИБКА: суффиксы в индексе кортежа недопустимы
let underscore = example.0_0; // ОШИБКА: нет поля `0_0` в типе `(&str, &str, &str)`
}

Литералы с плавающей точкой

Lexer
FLOAT_LITERAL
      DEC_LITERAL .not immediately followed by ., _ or an XID_Start character
    | DEC_LITERAL . DEC_LITERAL SUFFIX_NO_E?
    | DEC_LITERAL ( . DEC_LITERAL )? FLOAT_EXPONENT SUFFIX?

FLOAT_EXPONENT
    ( e | E ) ( + | - )? ( DEC_DIGIT | _ )* DEC_DIGIT ( DEC_DIGIT | _ )*

Литерал с плавающей точкой имеет одну из двух форм:

  • Десятичный литерал, за которым следует символ точки U+002E (.). За этим может следовать другой десятичный литерал, с необязательной экспонентой.
  • Одиночный десятичный литерал, за которым следует экспонента.

Как и целочисленные литералы, литерал с плавающей точкой может следовать за суффиксом, при условии, что часть до суффикса не заканчивается на U+002E (.). Суффикс не может начинаться с e или E, если литерал не включает экспоненту. См. Выражения литералов с плавающей точкой для получения информации о влиянии этих суффиксов.

Примеры литералов с плавающей точкой, которые принимаются как литеральные выражения:

#![allow(unused)]
fn main() {
123.0f64;
0.1f64;
0.1f32;
12E+99_f64;
let x: f64 = 2.;
}

Последний пример отличается, потому что невозможно использовать синтаксис суффикса с литералом с плавающей точкой, заканчивающимся на точку. 2.f64 попытается вызвать метод с именем f64 на 2.

Обратите внимание, что -1.0, например, анализируется как два токена: - followed by 1.0.

Примеры литералов с плавающей точкой, которые не принимаются как литеральные выражения:

#![allow(unused)]
fn main() {
#[cfg(false)] {
2.0f80;
2e5f80;
2e5e6;
2.0e5e6;
1.3e10u64;
}
}

Зарезервированные формы, похожие на числовые литералы

Lexer
RESERVED_NUMBER
      BIN_LITERAL [2-9]
    | OCT_LITERAL [8-9]
    | ( BIN_LITERAL | OCT_LITERAL | HEX_LITERAL ) .not immediately followed by ., _ or an XID_Start character
    | ( BIN_LITERAL | OCT_LITERAL ) ( e | E )
    | 0b _* <end of input or not BIN_DIGIT>
    | 0o _* <end of input or not OCT_DIGIT>
    | 0x _* <end of input or not HEX_DIGIT>
    | DEC_LITERAL ( . DEC_LITERAL )? ( e | E ) ( + | - )? <end of input or not DEC_DIGIT>

RESERVED_NUMBER BIN_LITERAL 2-9 OCT_LITERAL 8-9 BIN_LITERAL OCT_LITERAL HEX_LITERAL not immediately followed by `.`, `_` or an XID_Start character . BIN_LITERAL OCT_LITERAL e E 0b _ end of input or not BIN_DIGIT 0o _ end of input or not OCT_DIGIT 0x _ end of input or not HEX_DIGIT DEC_LITERAL . DEC_LITERAL e E + - end of input or not DEC_DIGIT

Следующие лексические формы, похожие на числовые литералы, являются зарезервированными формами. Из-за возможной неоднозначности, которую они вызывают, они отвергаются токенизатором вместо того, чтобы интерпретироваться как отдельные токены.

  • Несуффиксированный двоичный или восьмеричный литерал, за которым, без пробелов, следует десятичная цифра вне диапазона его системы счисления.
  • Несуффиксированный двоичный, восьмеричный или шестнадцатеричный литерал, за которым, без пробелов, следует символ точки (с теми же ограничениями на то, что следует за точкой, как для литералов с плавающей точкой).
  • Несуффиксированный двоичный или восьмеричный литерал, за которым, без пробелов, следует символ e или E.
  • Ввод, который начинается с одного из префиксов системы счисления, но не является допустимым двоичным, восьмеричным или шестнадцатеричным литералом (потому что не содержит цифр).
  • Ввод, который имеет форму литерала с плавающей точкой без цифр в экспоненте.

Примеры зарезервированных форм:

#![allow(unused)]
fn main() {
0b0102;  // это не `0b010` followed by `2`
0o1279;  // это не `0o127` followed by `9`
0x80.0;  // это не `0x80` followed by `.` и `0`
0b101e;  // это не суффиксированный литерал, или `0b101` followed by `e`
0b;      // это не целочисленный литерал, или `0` followed by `b`
0b_;     // это не целочисленный литерал, или `0` followed by `b_`
2e;      // это не литерал с плавающей точкой, или `2` followed by `e`
2.0e;    // это не литерал с плавающей точкой, или `2.0` followed by `e`
2em;     // это не суффиксированный литерал, или `2` followed by `em`
2.0em;   // это не суффиксированный литерал, или `2.0` followed by `em`
}

Времена жизни и метки циклов

Lexer
LIFETIME_TOKEN
      ' IDENTIFIER_OR_KEYWORDnot immediately followed by '
    | RAW_LIFETIME

LIFETIME_OR_LABEL
      ' NON_KEYWORD_IDENTIFIERnot immediately followed by '
    | RAW_LIFETIME

RAW_LIFETIME
    'r# IDENTIFIER_OR_KEYWORDnot immediately followed by '

RESERVED_RAW_LIFETIME'r# ( _ | crate | self | Self | super )not immediately followed by '

RAW_LIFETIME 'r# not immediately followed by `'` IDENTIFIER_OR_KEYWORD
RESERVED_RAW_LIFETIME 'r# not immediately followed by `'` _ crate self Self super

Параметры времени жизни и метки циклов используют токены LIFETIME_OR_LABEL. Любой токен LIFETIME_TOKEN будет принят лексером и, например, может быть использован в макросах.

Сырое время жизни похоже на обычное время жизни, но его идентификатор имеет префикс r#. (Обратите внимание, что префикс r# не включается в состав самого времени жизни.)

В отличие от обычного времени жизни, сырым временем жизни может быть любое строгое или зарезервированное ключевое слово, кроме перечисленных выше для RESERVED_RAW_LIFETIME.

Ошибкой является использование токена RESERVED_RAW_LIFETIME.

2021 Edition differences

Сырые времена жизни принимаются в редакции 2021 или позже. В более ранних редакциях токен 'r#lt лексируется как 'r # lt.

Знаки пунктуации

Токены пунктуации используются как операторы, разделители и другие части грамматики.

Lexer
PUNCTUATION
      =
    | <
    | <=
    | ==
    | !=
    | >=
    | >
    | &&
    | ||
    | !
    | ~
    | +
    | -
    | *
    | /
    | %
    | ^
    | &
    | |
    | <<
    | >>
    | +=
    | -=
    | *=
    | /=
    | %=
    | ^=
    | &=
    | |=
    | <<=
    | >>=
    | @
    | .
    | ..
    | ...
    | ..=
    | ,
    | ;
    | :
    | ::
    | ->
    | <-
    | =>
    | #
    | $
    | ?
    | {
    | }
    | [
    | ]
    | (
    | )

PUNCTUATION = < <= == != >= > && || ! ~ + - * / % ^ & | << >> += -= *= /= %= ^= &= |= <<= >>= @ . .. ... ..= , ; : :: -> <- => # $ ? { } [ ] ( )

Note

См. синтаксический указатель для ссылок на то, как используются символы пунктуации.

Разделители

Скобочные знаки пунктуации используются в различных частях грамматики. Открывающая скобка всегда должна быть парной с закрывающей скобкой. Скобки и токены внутри них называются “деревьями токенов” в macros. Три типа скобок:

СкобкаТип
{ }Фигурные скобки
[ ]Квадратные скобки
( )Круглые скобки

Зарезервированные токены

Несколько форм токенов зарезервированы для будущего использования или чтобы избежать путаницы. Ошибкой является совпадение исходного ввода с одной из этих форм.

Зарезервированные префиксы

Lexer
RESERVED_TOKEN_DOUBLE_QUOTE
    IDENTIFIER_OR_KEYWORDкроме b или c или r или br или cr "

RESERVED_TOKEN_SINGLE_QUOTE
    IDENTIFIER_OR_KEYWORDкроме b '

RESERVED_TOKEN_POUND
    IDENTIFIER_OR_KEYWORDкроме r или br или cr #

RESERVED_TOKEN_LIFETIME
    ' IDENTIFIER_OR_KEYWORDкроме r #

RESERVED_TOKEN_DOUBLE_QUOTE кроме `b` или `c` или `r` или `br` или `cr` IDENTIFIER_OR_KEYWORD "
RESERVED_TOKEN_POUND кроме `r` или `br` или `cr` IDENTIFIER_OR_KEYWORD #

Некоторые лексические формы, известные как зарезервированные префиксы, зарезервированы для будущего использования.

Исходный ввод, который в противном случае лексически интерпретировался бы как несырой идентификатор (или ключевое слово), за которым непосредственно следует символ #, ' или " (без пробелов между ними), идентифицируется как зарезервированный префикс.

Обратите внимание, что сырые идентификаторы, сырые строковые литералы и сырые байтовые строковые литералы могут содержать символ #, но не интерпретируются как содержащие зарезервированный префикс.

Аналогично, префиксы r, b, br, c и cr, используемые в сырых строковых литералах, байтовых литералах, байтовых строковых литералах, сырых байтовых строковых литералах, C-строковых литералах и сырых C-строковых литералах, не интерпретируются как зарезервированные префиксы.

Исходный ввод, который в противном случае лексически интерпретировался бы как несырое время жизни (или ключевое слово), за которым непосредственно следует символ # (без пробелов между ними), идентифицируется как зарезервированный префикс времени жизни.

2021 Edition differences

Начиная с редакции 2021, зарезервированные префиксы сообщаются лексером как ошибка (в частности, они не могут быть переданы в макросы).

До редакции 2021, зарезервированные префиксы принимаются лексером и интерпретируются как несколько токенов (например, один токен для идентификатора или ключевого слова, за которым следует токен #).

Примеры, принимаемые во всех редакциях:

#![allow(unused)]
fn main() {
macro_rules! lexes {($($_:tt)*) => {}}
lexes!{a #foo}
lexes!{continue 'foo}
lexes!{match "..." {}}
lexes!{r#let#foo}         // три токена: r#let # foo
lexes!{'prefix #lt}
}

Примеры, принимаемые до редакции 2021, но отвергаемые позже:

#![allow(unused)]
fn main() {
macro_rules! lexes {($($_:tt)*) => {}}
lexes!{a#foo}
lexes!{continue'foo}
lexes!{match"..." {}}
lexes!{'prefix#lt}
}

Зарезервированные ограничители

Lexer
RESERVED_GUARDED_STRING_LITERAL#+ STRING_LITERAL

RESERVED_POUNDS#2..

Зарезервированные ограничители — это синтаксис, зарезервированный для будущего использования, и они вызовут ошибку компиляции, если будут использованы.

Зарезервированный ограниченный строковый литерал — это токен из одного или более U+0023 (#), за которым непосредственно следует STRING_LITERAL.

Зарезервированные решётки — это токен из двух или более U+0023 (#).

2024 Edition differences

До редакции 2024, зарезервированные ограничители принимаются лексером и интерпретируются как несколько токенов. Например, форма #"foo"# интерпретируется как три токена. ## интерпретируется как два токена.


  1. Количество символов # с каждой стороны одного и того же литерала должно быть одинаковым.

  2. Все числовые литералы допускают _ как визуальный разделитель: 1_234.0E+18f64