|
|
@@ -1,124 +1,112 @@
|
|
|
-# Chapter 12. Lexical analysis
|
|
|
+# Глава 12. Лексический анализ
|
|
|
|
|
|
-Lexical analysis describes how letters and other characters form the “words” of a programming language in general. These “words” are technically called tokens and the rest of the compiler’s transformation pipeline works on tokens and not on single characters. The transformation pipeline is usually called phases of translation.
|
|
|
+_Лексический анализ_ описывает, как буквы и другие символы образуют «слова» в языке программирования в целом. Эти «слова» технически называются _лексемами_, и остальная часть конвейера преобразований компилятора работает с лексемами, а не с отдельными символами. Конвейер преобразований обычно называют _фазой трансляции_.
|
|
|
|
|
|
-A Nim compiler uses the following phases of translation:
|
|
|
+Компилятор **Nim** использует следующие этапы трансляции:
|
|
|
|
|
|
-- 1 Lexing: Turn a stream of characters into a stream of tokens.
|
|
|
-- 2 Parsing: Turn a stream of tokens into an abstract syntax tree (AST).
|
|
|
-- 3 Semantic analysis: Turn an AST to an annotated AST. The annotations are primarily type annotations as Nim is a statically typed language every expression needs to have a type.
|
|
|
+- 1 Лексический анализ: преобразование потока символов в поток лексем.
|
|
|
+- 2 Парсинг: преобразование потока лексем в абстрактное синтаксическое дерево (**AST**).
|
|
|
+- 3 Семантический анализ: преобразование **AST** в аннотированный **AST**. Аннотации в основном касаются типов, поскольку **Nim** — это язык со статической типизацией, и каждое выражение должно иметь тип.
|
|
|
|
|
|
-This chapter describes in detail the first phase, lexing.
|
|
|
+В этой главе подробно описан первый этап — лексический анализ.
|
|
|
|
|
|
-## 12.1. Notation used in this chapter
|
|
|
+## 12.1. Обозначения, используемые в этой главе
|
|
|
|
|
|
-The language constructs are explained using an extended Backus–Naur form (EBNF), in which a* means 0 or more a's, a+ means 1 or more a's, and a? means an optional a (either no a or one a). Parentheses may be used to group elements.
|
|
|
+Языковые конструкции объясняются с помощью _расширенной формы Бэкуса—Наура_ (**РБНФ**), в которой `a*` означает 0 или более элементов `a`, `a+` означает 1 или более элементов `a`, а `a?` означает необязательный элемент `a` (либо ни одного элемента `a`, либо один элемент `a`). Для группировки элементов могут использоваться скобки.
|
|
|
|
|
|
-& is the lookahead operator; &a means that an a is expected but not consumed.
|
|
|
+`&` — это опережающий оператор; `&a` означает, что ожидается буква `a`, но она не используется.
|
|
|
|
|
|
-The |, / symbols are used to mark alternatives and have the lowest precedence. / is the ordered choice that requires the parser to try the alternatives in the given order. / is often used to ensure that the grammar is not ambiguous.
|
|
|
+Символы `|` и `/` используются для обозначения альтернатив и имеют самый низкий приоритет. `/` — это упорядоченный выбор, который требует, чтобы парсер пробовал альтернативные варианты в указанном порядке. `/` часто используется для устранения неоднозначности грамматики.
|
|
|
|
|
|
-Non-terminals start with a lowercase letter, abstract terminal symbols are in UPPERCASE. Verbatim terminal symbols (including keywords) are quoted with '. An example:
|
|
|
+Нетерминалы начинаются со строчной буквы, абстрактные терминальные символы — с заглавной. Дословные терминальные символы (включая ключевые слова) заключаются в кавычки `'`. Пример:
|
|
|
|
|
|
```rbnf
|
|
|
ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)?
|
|
|
```
|
|
|
|
|
|
-The binary ^* operator is used as a shorthand for 0 or more occurrences separated by its second argument; likewise ^`` means 1 or more occurrences:
|
|
|
-
|
|
|
-```rbnf
|
|
|
-a^b is short for a (b a)* and a ^* b
|
|
|
-```
|
|
|
-
|
|
|
-is short for
|
|
|
-
|
|
|
-```rbnf
|
|
|
-(a (b a)*)?
|
|
|
-```
|
|
|
-
|
|
|
-For example:
|
|
|
+Бинарный оператор `^*` используется как сокращение для обозначения 0 или более вхождений, разделенных вторым аргументом; аналогично `^''` означает 1 или более вхождений: `a^b` is short for `a (b a)*` and `a ^* b` это сокращение для `(a (b a)*)?`. Например:
|
|
|
|
|
|
```rbnf
|
|
|
arrayConstructor = '[' expr ^* ',' ']'
|
|
|
```
|
|
|
|
|
|
-A Nim program consists of one or more text source files containing Nim code. The text has to be encoded in UTF-8. Nim’s grammar is not defined directly on the Unicode input text. Instead, it is defined on a list of separate, non-overlapping tokens. A token can be classified to be one of the following:
|
|
|
+Программа на языке **Nim** состоит из одного или нескольких текстовых исходных файлов, содержащих код на языке **Nim**. Текст должен быть закодирован в `UTF-8`. Грамматика языка **Nim** не привязана напрямую к входному тексту в кодировке `Unicode`. Вместо этого она основана на списке отдельных непересекающихся лексем. Лексема может быть отнесена к одной из следующих категорий:
|
|
|
|
|
|
-- A comment.
|
|
|
-- An identifier.
|
|
|
-- A keyword like if or type.
|
|
|
-- A (character, string, integer, floating-point number) literal.
|
|
|
-- An operator.
|
|
|
-- A delimiter like (, ,, ). (It covers the semicolon, the comma and the different types of brackets.)
|
|
|
+- Комментарий.
|
|
|
+- Идентификатор.
|
|
|
+- Ключевое слово, например `if` или `type`.
|
|
|
+- Литерал (символ, строка, целое число, число с плавающей запятой).
|
|
|
+- Оператор.
|
|
|
+- Разделитель, например (, `, ). (Сюда входят точка с запятой, запятая и различные типы скобок.)
|
|
|
|
|
|
-## 12.2. Indentation
|
|
|
+## 12.2. Отступы
|
|
|
|
|
|
-Nim’s standard grammar describes an indentation sensitive language. This means that all the control structures are recognized by indentation.
|
|
|
+Стандартная грамматика языка **Nim** описывает язык с чувствительностью к отступам. Это означает, что все управляющие конструкции распознаются по отступам.
|
|
|
|
|
|
-Indentation consists only of spaces; tabulators are not allowed. The "use tabs for indentation, spaces for alignment" rule never works sufficiently well in larger code-bases and even if it does work, it adds yet another source of friction for developers. Things are easier without such a rule. Since Nim uses an indentation based syntax and only allows spaces, the source code layout is portable across editors.
|
|
|
+Отступы делаются _только с помощью пробелов_, **табуляция не допускается**. Правило «используй табуляцию для отступов, а пробелы — для выравнивания» никогда не работало достаточно хорошо в больших кодовых базах, а если и работало, то создавало дополнительные трудности для разработчиков. Без такого правила работать проще. Поскольку в языке **Nim** используется синтаксис на основе отступов и допускаются только пробелы, макет исходного кода совместим со всеми редакторами.
|
|
|
|
|
|
-The indentation handling is implemented as follows: The lexer annotates the following token with the preceding number of spaces; indentation is not a separate token. This trick allows parsing of Nim with only one token of lookahead.
|
|
|
+Обработка отступов реализована следующим образом: лексер аннотирует следующий токен количеством пробелов, предшествующих ему; отступ не является отдельным токеном. Этот прием позволяет анализировать **Nim**, просматривая только один токен.
|
|
|
|
|
|
-The parser uses a stack of indentation levels: the stack consists of integers counting the spaces. The indentation information is queried at strategic places in the parser but ignored otherwise: The pseudo-terminal IND{>} denotes an indentation that consists of more spaces than the entry at the top of the stack; IND{=} an indentation that has the same number of spaces. DED is another pseudo-terminal that describes the action of popping a value from the stack, IND{>} then implies to push onto the stack.
|
|
|
+Парсер использует стек уровней отступа: стек состоит из целых чисел, соответствующих количеству пробелов. Информация об отступе запрашивается в стратегически важных местах парсера, но в остальных случаях игнорируется: Псевдотерминал `IND{>}` обозначает отступ, состоящий из большего количества пробелов, чем запись в верхней части стека; `IND{=}` обозначает отступ, состоящий из того же количества пробелов. `DED` — еще один псевдотерминал, обозначающий действие _извлечения_ значения из стека. Тогда `IND{>}` означает _помещение_ значения в стек.
|
|
|
|
|
|
-With this notation we can now define the core of the grammar: A block of statements (simplified example):
|
|
|
+С помощью этих обозначений мы можем определить основу грамматики: блок операторов (упрощенный пример):
|
|
|
|
|
|
```rbnf
|
|
|
- ifStmt = 'if' expr ':' stmt
|
|
|
- (IND{=} 'elif' expr ':' stmt)*
|
|
|
- (IND{=} 'else' ':' stmt)?
|
|
|
- simpleStmt = ifStmt / ...
|
|
|
- stmt = IND{>} stmt ^+ IND{=} DED # list of statements
|
|
|
- / simpleStmt # or a simple statement
|
|
|
+ifStmt = 'if' expr ':' stmt
|
|
|
+ (IND{=} 'elif' expr ':' stmt)*
|
|
|
+ (IND{=} 'else' ':' stmt)?
|
|
|
+simpleStmt = ifStmt / ...
|
|
|
+stmt = IND{>} stmt ^+ IND{=} DED # список выражений
|
|
|
+ / simpleStmt # или простое выражение
|
|
|
```
|
|
|
|
|
|
-## 12.3. Comments
|
|
|
+## 12.3. Комментарии
|
|
|
|
|
|
-Comments start anywhere outside a string or character literal with the hash character (#). Comments consist of a concatenation of comment pieces. A comment piece starts with # and runs until the end of the line. The end of line characters belong to the piece. If the next line only consists of a comment piece with no other tokens between it and the preceding one, it does not start a new comment:
|
|
|
+Комментарии начинаются с символа решетки (`#`) в любом месте за пределами строкового или символьного литерала. Комментарии состоят из конкатенации фрагментов комментария. Фрагмент комментария начинается с `#` и продолжается до конца строки. Символы конца строки относятся к фрагменту. Если следующая строка состоит только из фрагмента комментария и между ней и предыдущей строкой нет других токенов, она не начинает новый комментарий:
|
|
|
|
|
|
```nim
|
|
|
- i = 0 # This is a single comment over multiple lines.
|
|
|
- # The scanner merges these pieces.
|
|
|
- # The same comment continues here.
|
|
|
+ i = 0 # Это единичный комментарий в конце строки".
|
|
|
+ # Сканер убирёт всё это.
|
|
|
+ # Другой комментарий и тоже будет удалён.
|
|
|
```
|
|
|
|
|
|
-Documentation comments are comments that start with two hash characters (##). Documentation comments are tokens; they are only allowed at certain places in the input file as they belong to the syntax tree.
|
|
|
+Комментарии в документации — это комментарии, которые начинаются с двух символов решетки (`##`). Комментарии в документации являются токенами и допускаются только в определенных местах входного файла, поскольку они относятся к синтаксическому дереву.
|
|
|
|
|
|
-## 12.4. Multiline comments
|
|
|
+## 12.4. Многострочные комментарии
|
|
|
|
|
|
-A multiline comment starts with #[ and ends with ]#:
|
|
|
+Многострочный комментарий начинается с `#[` и заканчивается `]#`:
|
|
|
|
|
|
```nim
|
|
|
-#[Comment here that can
|
|
|
- span
|
|
|
- multiple lines.]#
|
|
|
+#[Комментароий может быть
|
|
|
+ разнесён
|
|
|
+ на несколькострок.]#
|
|
|
```
|
|
|
|
|
|
-Multiline comments can be nested:
|
|
|
+Многострочные комментарии могут быть вложенными:
|
|
|
|
|
|
```nim
|
|
|
-#[ #[ Multiline comment in already
|
|
|
- commented out code. ]#
|
|
|
+#[ #[ Многострочный комментарий
|
|
|
+ также может включать код. ]#
|
|
|
proc p[T](x: T) = discard
|
|
|
]#
|
|
|
```
|
|
|
|
|
|
-Multiline documentation comments exist and support nesting too:
|
|
|
+Существуют многострочные комментарии к документации, которые также поддерживают вложенность:
|
|
|
|
|
|
```nim
|
|
|
proc foo =
|
|
|
- ##[Long documentation comment
|
|
|
- here.
|
|
|
+ ##[Длинный документирующий комментарий
|
|
|
+ помещается здесь.
|
|
|
]##
|
|
|
```
|
|
|
|
|
|
-## 12.5. Identifiers & Keywords
|
|
|
+## 12.5. Идентификаторы и ключевые слова
|
|
|
|
|
|
-Identifiers in Nim can be any string of letters, digits and underscores, with the following restrictions:
|
|
|
+Идентификаторы в языке **Nim** могут представлять собой любую последовательность букв, цифр и символов подчеркивания со следующими ограничениями:
|
|
|
|
|
|
-- It has to begin with a letter.
|
|
|
-- It is not allowed to end with an underscore _.
|
|
|
-- Two successive underscores __ are not allowed:
|
|
|
+- Оно должно начинаться с буквы.
|
|
|
+- Оно _не должно заканчиваться_ символом подчеркивания `_`.
|
|
|
+- Два последовательных подчеркивания `__` _недопустимы_:
|
|
|
|
|
|
```rbnf
|
|
|
letter ::= 'A'..'Z' | 'a'..'z' | '\x80'..'\xff'
|
|
|
@@ -126,9 +114,9 @@ digit ::= '0'..'9'
|
|
|
IDENTIFIER ::= letter ( ['_'] (letter | digit) )*
|
|
|
```
|
|
|
|
|
|
-Unicode characters with an ordinal value higher than 127 (non-ASCII) can be either classified as a letter or as operator. The details of this classification are not covered here as they might still change in the future.
|
|
|
+Символы **Юникода** с порядковым номером выше 127 (не входящие в **ASCII**) могут относиться как к буквам, так и к операторам. Подробности этой классификации здесь не рассматриваются, поскольку они могут измениться в будущем.
|
|
|
|
|
|
-The following keywords are reserved and cannot be used as identifiers:
|
|
|
+Следующие ключевые слова являются зарезервированными и не могут использоваться в качестве идентификаторов:
|
|
|
|
|
|
- addr and as asm
|
|
|
- bind block break
|
|
|
@@ -151,11 +139,11 @@ The following keywords are reserved and cannot be used as identifiers:
|
|
|
- xor
|
|
|
- yield
|
|
|
|
|
|
-Some keywords are currently unused; they are reserved for future developments of the language.
|
|
|
+Некоторые ключевые слова в настоящее время не используются; они зарезервированы для будущих версий языка.
|
|
|
|
|
|
-## 12.6. Identifier equality
|
|
|
+## 12.6. Равенство идентификаторов
|
|
|
|
|
|
-Two identifiers are considered equal if the following algorithm returns true:
|
|
|
+Два идентификатора считаются равными, если следующий алгоритм возвращает `true`:
|
|
|
|
|
|
```nim
|
|
|
proc sameIdentifier(a, b: string): bool =
|
|
|
@@ -163,125 +151,125 @@ proc sameIdentifier(a, b: string): bool =
|
|
|
a.replace("_", "").toLowerAscii == b.replace("_", "").toLowerAscii
|
|
|
```
|
|
|
|
|
|
-That means only the first letters are compared in a case-sensitive manner. Other letters are compared case-insensitively within the ASCII range and underscores are ignored.
|
|
|
+Это означает, что только первые буквы сравниваются с учетом регистра. Остальные буквы сравниваются без учета регистра в диапазоне **ASCII**, а символы подчеркивания игнорируются.
|
|
|
|
|
|
-This rule also applies to keywords, meaning that notin is the same as notIn and not_in.
|
|
|
+Это правило также применимо к ключевым словам, то есть `notin` — это то же самое, что `notIn` и `not_in`.
|
|
|
|
|
|
-The eccentric rules with respect to identifier equality try to ensure more sensible naming practices where different things have different names rather than only different spellings.
|
|
|
+Эксцентричные правила, касающиеся равенства идентификаторов, призваны обеспечить более разумный подход к именованию, при котором разные объекты имеют разные названия, а не только разное написание.
|
|
|
|
|
|
-Compare const ROOT = root(Root) to const RootUser = rootof(RootDir) to appreciate the benefits. Differences in spelling cannot be pronounced easily; as soon as two or more developers need to talk about their code-base the benefits of clearly distinctive names become apparent.
|
|
|
+Сравните `const ROOT = root(Root)` и `const RootUser = rootof(RootDir)`, чтобы оценить преимущества. Разницу в написании не так просто уловить на слух; как только двум или более разработчикам нужно обсудить свою кодовую базу, преимущества четко различимых имен становятся очевидными.
|
|
|
|
|
|
-## 12.7. String Literals
|
|
|
+## 12.7. Строковые литералы
|
|
|
|
|
|
-Terminal symbol in the grammar: STR_LIT.
|
|
|
+Терминальный символ в грамматике: **STR_LIT**.
|
|
|
|
|
|
-String literals can be delimited by matching double quotes, and can contain the following escape sequences :
|
|
|
+Строковые литералы могут быть заключены в двойные кавычки и содержать следующие управляющие последовательности:
|
|
|
|
|
|
-Table 1. Escape sequences for string literals
|
|
|
+**Таблица 1**. Управляющие последовательности для строковых литералов
|
|
|
|
|
|
-| Escape | sequence Meaning |
|
|
|
+| Код | значение кода |
|
|
|
| ------ | ---------------- |
|
|
|
-| \p | platform specific newline: CRLF on Windows, LF on Unix |
|
|
|
-| \r, \c | carriage return |
|
|
|
-| \n, \l | line feed (often called newline) |
|
|
|
-| \f | form feed|
|
|
|
-| \t | tabulator|
|
|
|
-| \v | vertical tabulator|
|
|
|
-| \\ | backslash|
|
|
|
-| \" | quotation mark|
|
|
|
-| \' | apostrophe|
|
|
|
-| \'0'..'9'+| character with decimal value d; all decimal digits directly following are used for the character |
|
|
|
-| \a | alert|
|
|
|
-| \b | backspace|
|
|
|
-| \e | escape [ESC]|
|
|
|
-| \xHH | character with hex value HH; exactly two hex digits are allowed|
|
|
|
-| \uHHHH | unicode codepoint with hex value HHHH; exactly fourhex digits are allowed|
|
|
|
-| \u{H+} | unicode codepoint; all hex digits enclosed in {} are usedfor the codepoint|
|
|
|
-
|
|
|
-Strings in Nim may contain any 8-bit value, even embedded zeros.
|
|
|
-
|
|
|
-## 12.8. Triple quoted string literals
|
|
|
-
|
|
|
-Terminal symbol in the grammar: TRIPLESTR_LIT.
|
|
|
-
|
|
|
-String literals can also be delimited by three double quotes """ ... """. Literals in this form may run for several lines, may contain " and do not interpret any escape sequences. For convenience, when the opening """ is followed by a newline (there may be whitespace between the opening """ and the newline), the newline (and the preceding whitespace) is not included in the string. The ending of the string literal is defined by the pattern """[^"].
|
|
|
-In other words, this:
|
|
|
+| \p | Специфичный для платформы символ перевода строки: `CRLF` в **Windows**, `LF` в **Unix** |
|
|
|
+| \r, \c | возврат каретки |
|
|
|
+| \n, \l | перевод строки (часто называемый новой строкой)|
|
|
|
+| \f | подача формы|
|
|
|
+| \t | табулятор|
|
|
|
+| \v | вертикальный табулятор|
|
|
|
+| \\ | обратная косая черта|
|
|
|
+| \" | кавычки|
|
|
|
+| \' | апостроф|
|
|
|
+| \'0'..'9'+| символ с десятичным значением d; все последующие десятичные цифры используются для символа |
|
|
|
+| \a | тревога (звонок)|
|
|
|
+| \b | бэкспейс (шаг назад, стирание)|
|
|
|
+| \e | отмена [ESC]|
|
|
|
+| \xHH | символ с шестнадцатеричным значением HH; допускаются только две шестнадцатеричные цифры|
|
|
|
+| \uHHHH | кодовая точка Юникода с шестнадцатеричным значением HHHH; допускаются ровно четыре шестнадцатеричные цифры|
|
|
|
+| \u{H+} | кодовая точка Юникода; все шестнадцатеричные цифры, заключенные в {}, используются для обозначения кодовой точки|
|
|
|
+
|
|
|
+Строки в языке **Nim** могут содержать любое 8-битное значение, даже встроенные нули.
|
|
|
+
|
|
|
+## 12.8. Строковые литералы в тройных кавычках
|
|
|
+
|
|
|
+Терминальный символ в грамматике: `TRIPLESTR_LIT`.
|
|
|
+
|
|
|
+Строковые литералы также могут быть заключены в две тройные кавычки `""" ... """`. Литералы в таком виде могут занимать несколько строк, могут содержать `"` и не интерпретируют никакие управляющие последовательности. Для удобства, если за открывающей `"""` следует символ новой строки (между открывающей `"""` и символом новой строки могут быть пробелы), символ новой строки (и предшествующие пробелы) не включается в строку. Конец строкового литерала определяется шаблоном `"""[^"]`. Другими словами, вот так:
|
|
|
|
|
|
```nim
|
|
|
- """"long string within quotes""""
|
|
|
+ """"Длинная строка с кавычками. """"
|
|
|
```
|
|
|
|
|
|
-Produces:
|
|
|
+Производит:
|
|
|
|
|
|
```nim
|
|
|
- "long string within quotes"
|
|
|
+ "Длинная строка с кавычками. "
|
|
|
```
|
|
|
|
|
|
-## 12.9. Raw string Literals
|
|
|
+## 12.9. Необработанные строковые литералы
|
|
|
|
|
|
-Terminal symbol in the grammar: RSTR_LIT.
|
|
|
+Терминальный символ в грамматике: **RSTR_LIT**.
|
|
|
|
|
|
-There are also raw string literals that are preceded with the letter r (or R) and are delimited by matching double quotes (just like ordinary string literals) and do not interpret the escape sequences. This is especially convenient for regular expressions or Windows paths:
|
|
|
+Существуют также необработанные строковые литералы, перед которыми ставится буква `r` (или `R`). Они заключаются в соответствующие двойные кавычки (как и обычные строковые литералы) и не интерпретируют управляющие последовательности. Это особенно удобно для регулярных выражений или путей в **Windows**.
|
|
|
|
|
|
```nim
|
|
|
- var f = openFile(r"C:\texts\text.txt") # a raw string, so ``\t`` is no tab
|
|
|
+ # сырая строка, таким образом ``\t`` не табуляция
|
|
|
+var f = openFile(r"C:\texts\text.txt")
|
|
|
```
|
|
|
|
|
|
-To produce a single " within a raw string literal, it has to be doubled:
|
|
|
+Чтобы в необработанном строковом литерале появился один символ `"`, его нужно продублировать:
|
|
|
|
|
|
```nim
|
|
|
r"a""b"
|
|
|
```
|
|
|
|
|
|
-Produces:
|
|
|
+Производит:
|
|
|
|
|
|
```nim
|
|
|
a"b
|
|
|
```
|
|
|
|
|
|
-r"""" is not possible with this notation, because the three leading quotes introduce a triple quoted string literal. r""" is the same as """ since triple quoted string literals do not interpret escape sequences either.
|
|
|
+`r""""` невозможно записать в таком виде, потому что три ведущие кавычки обозначают строковый литерал в тройных кавычках. `r"""` — это то же самое, что `"""`, поскольку строковые литералы в тройных кавычках также не интерпретируют управляющие последовательности.
|
|
|
|
|
|
-## 12.10. Generalized raw string literals
|
|
|
+## 12.10. Обобщенные необработанные строковые литералы
|
|
|
|
|
|
-Terminal symbols in the grammar: GENERALIZED_STR_LIT, GENERALIZED_TRIPLESTR_LIT.
|
|
|
+Терминальные символы в грамматике: `GENERALIZED_STR_LIT`, `GENERALIZED_TRIPLESTR_LIT`.
|
|
|
|
|
|
-The construct identifier"string literal" (without whitespace between the identifier and the opening quotation mark) is a generalized raw string literal.
|
|
|
+Идентификатор `имя"строковый литерал"` (без пробелов между именем и открывающей кавычкой) представляет собой обобщенный необработанный строковый литерал.
|
|
|
|
|
|
-It is a shortcut for the construct identifier(r"string literal"), so it denotes a routine call with a raw string literal as its only argument. Generalized raw string literals are especially convenient for embedding mini languages directly into Nim (for example regular expressions).
|
|
|
+Это сокращение от идентификатора конструкции (`r"строковый литерал"`), обозначающее вызов подпрограммы с необработанным строковым литералом в качестве единственного аргумента. Обобщенные необработанные строковые литералы особенно удобны для встраивания мини-языков непосредственно в **Nim** (например, регулярных выражений).
|
|
|
|
|
|
-The construct identifier """string literal""" exists too. It is a shortcut for identifier("""string literal""").
|
|
|
+Идентификатор `имя"""строковый литерал"""` тоже существует. Это сокращение от `identifier("""строковый литерал""")`.
|
|
|
|
|
|
-## 12.11. Character literals
|
|
|
+## 12.11. Символьные литералы
|
|
|
|
|
|
-Character literals are enclosed in single quotes '' and can contain the same escape sequences as strings - with one exception: the platform dependent newline (\p) is not allowed as it may be wider than one character (it can be the pair CR/LF). Here are the valid escape sequences for character literals:
|
|
|
+Символьные литералы заключаются в одинарные кавычки `'` и могут содержать те же управляющие последовательности, что и строки, за одним исключением: зависящая от платформы новая строка (`\p`) не допускается, так как она может состоять более чем из одного символа (это может быть пара символов `CR/LF`). Вот допустимые управляющие последовательности для символьных литералов:
|
|
|
|
|
|
-Table 2. Escape sequences for character literals
|
|
|
+**Таблица 2**. Управляющие последовательности для символьных литералов
|
|
|
|
|
|
-| Escape | sequence Meaning |
|
|
|
+| Код | Значение кода |
|
|
|
| ------ | ---------------- |
|
|
|
-|\r, \c | carriage return |
|
|
|
-|\n, \l | line feed |
|
|
|
-|\f | form feed |
|
|
|
-|\t | tabulator |
|
|
|
-|\v | vertical tabulator |
|
|
|
-|\\ | backslash
|
|
|
-|\" | quotation mark |
|
|
|
-|\' | apostrophe |
|
|
|
-|\'0'..'9'+| character with decimal value d; all decimal digits directly following are used for the character |
|
|
|
-|\a | alert|
|
|
|
-|\b | backspace|
|
|
|
-|\e | escape [ESC]|
|
|
|
-|\xHH | character with hex value HH; exactly two hex digits are allowed|
|
|
|
+|\r, \c | возврат каретки |
|
|
|
+|\n, \l | перевод строки |
|
|
|
+|\f | подача формы |
|
|
|
+|\t | табулятор |
|
|
|
+|\v | вертикальный табулятор |
|
|
|
+|\\ | обратная косая черта|
|
|
|
+|\" | кавычки |
|
|
|
+|\' | апостроф |
|
|
|
+|\'0'..'9'+| символ с десятичным значением d; все последующие десятичные цифры используются для символа |
|
|
|
+|\a | nhtdjuf (pdjyjr)|
|
|
|
+|\b | забой|
|
|
|
+|\e | отмена [ESC]|
|
|
|
+|\xHH | символ с шестнадцатеричным значением HH; допускаются только две шестнадцатеричные цифры |
|
|
|
|
|
|
-A char is not a Unicode character but a single byte.
|
|
|
+Символ — это не символ Юникода, а отдельный байт.
|
|
|
|
|
|
-A character literal that does not end in ' is interpreted as ' if there is a preceding backtick token. There must be no whitespace between the preceding backtick token and the character literal. This special case ensures that a declaration like proc ’'customLiteral`(s: string) is valid. proc ’'customLiteral`(s: string) is the same as proc '\''customLiteral`(s: string).
|
|
|
+Символьный литерал, не заканчивающийся на `'`, интерпретируется как `'`, если ему предшествует обратный апостроф. Между обратным апострофом и символьным литералом не должно быть пробелов. Этот особый случай гарантирует, что объявление вида `proc 'customLiteral'(s: string)` правильное, а `proc 'customLiteral'(s: string)` будет таким же, как `proc '\''customLiteral'(s: string)`.
|
|
|
|
|
|
-See also Section 12.12.1, “Custom Numeric Literals”.
|
|
|
+См. также раздел 12.12.1 «Пользовательские числовые литералы».
|
|
|
|
|
|
-## 12.12. Numeric Literals
|
|
|
+## 12.12. Числовые литералы
|
|
|
|
|
|
-Numeric literals have the form:
|
|
|
+Числовые литералы имеют следующий вид:
|
|
|
|
|
|
```rbnf
|
|
|
hexdigit = digit | 'A'..'F' | 'a'..'f'
|
|
|
@@ -320,13 +308,13 @@ CUSTOM_NUMERIC_LIT = (FLOAT_LIT | INT_LIT) '\'' CUSTOM_NUMERIC_SUFFIX
|
|
|
# a pre-defined type suffix.
|
|
|
```
|
|
|
|
|
|
-As can be seen in the productions, numeric literals can contain underscores for readability. Integer and floating-point literals may be given in decimal (no prefix), binary (prefix 0b), octal (prefix 0o), and hexadecimal (prefix 0x) notation.
|
|
|
+Как видно из примеров, числовые литералы могут содержать символы подчеркивания для удобства чтения. Целочисленные литералы и литералы с плавающей запятой могут быть представлены в десятичной (без префикса), двоичной (префикс `0b`), восьмеричной (префикс `0o`) и шестнадцатеричной (префикс `0x`) системах счисления.
|
|
|
|
|
|
-The fact that the unary minus - in a number literal like -1 is considered to be part of the literal is a late addition to the language. The rationale is that an expression -128'i8 should be valid and without this special case, this would be impossible — 128 is not a valid int8 value, only -128 is.
|
|
|
+Тот факт, что унарный минус `-` в числовом литерале, например `-1`, считается частью литерала, появился в языке довольно поздно. Это связано с тем, что выражение `-128'i8` должно быть допустимым, а без этого особого случая это было бы невозможно — `128` не является допустимым значением `int8`, только `-128`.
|
|
|
|
|
|
-For the unary_minus rule there are further restrictions that are not covered in the formal grammar. For - to be part of the number literal, its immediately preceding character has to be in the set {' ', '\t', '\n', '\r', ',', ';', '(', '[', '{'}.
|
|
|
+Для правила `unary_minus` существуют дополнительные ограничения, которые не отражены в формальной грамматике. Чтобы - было частью числового литерала, непосредственно предшествующий ему символ должен входить в набор {' ', '\t', '\n', '\r', ',', ';', '(', '[', '{'}.
|
|
|
|
|
|
-In the following examples, -1 is a single token:
|
|
|
+В следующих примерах `-1` — это один токен:
|
|
|
|
|
|
```nim
|
|
|
echo -1
|
|
|
@@ -336,7 +324,7 @@ echo 3,-1
|
|
|
"abc";-1
|
|
|
```
|
|
|
|
|
|
-In the following examples, -1 is parsed as two separate tokens (as - and 1):
|
|
|
+В следующих примерах `-1` разбивается на два отдельных токена (как `-` и `1`):
|
|
|
|
|
|
```nim
|
|
|
echo x-1
|
|
|
@@ -345,15 +333,14 @@ echo [a]-1
|
|
|
"abc"-1
|
|
|
```
|
|
|
|
|
|
-The suffix starting with an apostrophe (') is called a type suffix. Literals without a type suffix are of an integer type unless the literal contains a dot or E|e in which case it is of type float. This integer type is int if the literal is in the range low(int32)..high(int32), otherwise it is int64. For notational convenience, the apostrophe of a type suffix is optional if it is not ambiguous (only hexadecimal floating-point literals with a type suffix can be ambiguous).
|
|
|
+Суффикс, начинающийся с апострофа (`'`), называется _суффиксом типа_. Литералы без суффикса типа имеют целочисленный тип, за исключением случаев, когда литерал содержит точку или `E|e`, — тогда он имеет тип `float`. Этот целочисленный тип является типом `int`, если литерал находится в диапазоне `low(int32)..high(int32)`, в противном случае это тип `int64`. Для удобства записи апостроф в суффиксе типа необязателен, если он не приводит к неоднозначности (неоднозначными могут быть только шестнадцатеричные литералы с плавающей запятой и суффиксом типа).
|
|
|
|
|
|
-The pre-defined type suffixes are:
|
|
|
+Предустановленные суффиксы типов:
|
|
|
|
|
|
-Table 3. Pre-defined type suffixes
|
|
|
+**Таблица 3**. Предустановленные суффиксы типов
|
|
|
|
|
|
-| Type | Resulting type of |
|
|
|
-| ------ | ----------------- |
|
|
|
-| Suffix | literal |
|
|
|
+| Тип суффикса | Результирующий литерал|
|
|
|
+| ------------ | --------------------- |
|
|
|
|'i8 | int8 |
|
|
|
|'i16 | int16 |
|
|
|
|'i32 | int32 |
|
|
|
@@ -368,44 +355,44 @@ Table 3. Pre-defined type suffixes
|
|
|
|'f32 | float32 |
|
|
|
|'f64 | float64 |
|
|
|
|
|
|
-Literals must match the datatype, for example, 333'i8 is an invalid literal.
|
|
|
+Литералы должны соответствовать типу данных. Например, `333'i8` — недопустимый литерал.
|
|
|
|
|
|
-Non-base-10 literals are used mainly for flags and bit pattern representations, therefore the checking is done on bit width and not on value range. Hence: 0b10000000'u8 == 0x80'u8 == 128, but: 0b10000000'i8 == 0x80'i8 == -1, instead of causing an overflow error.
|
|
|
+Литералы, не основанные на десятичной системе счисления, используются в основном для флагов и представления битовых шаблонов, поэтому проверка выполняется по разрядности, а не по диапазону значений. Следовательно: `0b10000000'u8 == 0x80'u8 == 128`, но: `0b10000000'i8 == 0x80'i8 == -1`, а не вызывает ошибку переполнения.
|
|
|
|
|
|
-## 12.12.1. Custom Numeric literals
|
|
|
+## 12.12.1. Пользовательские числовые литералы
|
|
|
|
|
|
-If the suffix is not predefined, then the suffix is assumed to be a call to a proc, template, macro or other callable identifier that is passed the string containing the literal. The callable identifier needs to be declared with a special ' prefix:
|
|
|
+Если суффикс не является предопределенным, то предполагается, что он представляет собой вызов процедуры, шаблона, макроса или другого вызываемого идентификатора, которому передается строка, содержащая литерал. Вызываемый идентификатор должен быть объявлен со специальным префиксом `'`:
|
|
|
|
|
|
```nim
|
|
|
import strutils
|
|
|
|
|
|
-type u4 = distinct uint8 # a 4-bit unsigned integer aka "nibble"
|
|
|
+type u4 = distinct uint8 # 4-битное беззнаковое целое "нибл"
|
|
|
|
|
|
proc `'u4`(n: string): u4 =
|
|
|
- # The leading ' is required.
|
|
|
+ # Требуется лидирующая кавычка `'` в апострофах
|
|
|
result = (parseInt(n) and 0x0F).u4
|
|
|
var x = 5'u4
|
|
|
```
|
|
|
|
|
|
-More formally, a custom numeric literal 123'custom is transformed to r"123".'custom in the parsing step. There is no AST node kind that corresponds to this transformation. The transformation naturally handles the case that additional parameters are passed to the callee:
|
|
|
+Если говорить более формально, пользовательский числовой литерал `123'custom` на этапе синтаксического анализа преобразуется в `r"123".'custom`. Этому преобразованию не соответствует ни один тип узла **AST**. Преобразование естественным образом обрабатывает случай, когда вызываемому объекту передаются дополнительные параметры:
|
|
|
|
|
|
```nim
|
|
|
import strutils
|
|
|
|
|
|
-type u4 = distinct uint8 # a 4-bit unsigned integer aka "nibble"
|
|
|
+type u4 = distinct uint8 # 4-битное беззнаковое целое "нибл"
|
|
|
|
|
|
proc `'u4`(n: string; moreData: int): u4 =
|
|
|
result = (parseInt(n) and 0x0F).u4
|
|
|
var x = 5'u4(123)
|
|
|
```
|
|
|
|
|
|
-Custom numeric literals are covered by the grammar rule named CUSTOM_NUMERIC_LIT. A custom numeric literal is a single token.
|
|
|
+Пользовательские числовые литералы описываются грамматическим правилом `CUSTOM_NUMERIC_LIT`. Пользовательский числовой литерал представляет собой один токен.
|
|
|
|
|
|
-## 12.13. Operators
|
|
|
+## 12.13. Операторы
|
|
|
|
|
|
-Nim allows user-defined operators, in fact, Nim does not distinguish between user-defined and builtin operators. When one writes 1 + 2 it is a call to a plus operator ``(1, 2)`` which is subject to overload resolution. The `system` module is automatically imported in every Nim program and offers ``func \``(a, b: int): int so the call will be resolved to system.`+`(1, 2).
|
|
|
+В **Nim** можно использовать пользовательские операторы. На самом деле в **Nim** нет разницы между пользовательскими и встроенными операторами. Когда мы пишем `1 + 2`, это вызов оператора сложения `+(1, 2)`, который подлежит разрешению перегрузки. Модуль `system` автоматически импортируется в каждую программу на **Nim** и предлагает `func \(a, b: int): int`, поэтому вызов будет разрешен как `system.+(1, 2)`.
|
|
|
|
|
|
-An operator is any combination of the following characters:
|
|
|
+Оператор — это любая комбинация следующих символов:
|
|
|
|
|
|
```text
|
|
|
= + - * / < >
|
|
|
@@ -413,32 +400,33 @@ An operator is any combination of the following characters:
|
|
|
! ? ^ . : \
|
|
|
```
|
|
|
|
|
|
-(The grammar uses the terminal OPR to refer to operator symbols as defined here.)
|
|
|
+(В грамматике используется терминал `OPR` для обозначения символов операторов, как указано здесь.)
|
|
|
+
|
|
|
+Эти ключевые слова также являются операторами: and or not xor shl shr div mod in notin is isnot of as from.
|
|
|
|
|
|
-These keywords are also operators: and or not xor shl shr div mod in notin is isnot of as from.
|
|
|
+`.`, `=`, `:`, `::` недоступны в качестве общих операторов; они используются для других целей. `*:` в качестве особого случая рассматривается как два токена `*` и `:` (для поддержки `var v*: T`).
|
|
|
|
|
|
-., =, :, :: are not available as general operators; they are used for other notational purposes.
|
|
|
-*: is as a special case treated as the two tokens * and : (to support var v*: T). The not keyword is always a unary operator, a not b is parsed as a(not b), not as (a) not (b).
|
|
|
+Ключевое слово `not` всегда является унарным оператором, `a not b` анализируется как `a(not b)`, а не как `(a) not (b)`.
|
|
|
|
|
|
-## 12.14. Other tokens
|
|
|
+## 12.14. Другие токены
|
|
|
|
|
|
-The following strings denote other tokens:
|
|
|
+Следующие строки обозначают другие токены:
|
|
|
|
|
|
```text
|
|
|
` ( ) { } [ ] , ; [. .] {. .} (. .) [:
|
|
|
```
|
|
|
|
|
|
-The slice operator .. takes precedence over other tokens that contain a dot: {..} are the three tokens: { and .. and }, and not the two tokens: {. and .}.
|
|
|
+Оператор среза `..` имеет приоритет над другими токенами, содержащими точку: `{..}` — это три токена: `{` и `..` и `}`, а не два: `{.` и `.}`.
|
|
|
|
|
|
-## 12.15. Unicode Operators
|
|
|
+## 12.15. Операторы Юникода
|
|
|
|
|
|
-These Unicode operators are also parsed as operators:
|
|
|
+Эти операторы **Юникода** также распознаются как операторы:
|
|
|
|
|
|
```nim
|
|
|
-∙ ∘ × ★ ⊗ ⊘ ⊙ ⊛ ⊠ ⊡ ∩ ∧ # same priority as * (multiplication)
|
|
|
-± ⊕ ⊖ ⊞ ⊟ ∪ ∨ # same priority as + (addition)
|
|
|
+∙ ∘ × ★ ⊗ ⊘ ⊙ ⊛ ⊠ ⊡ ∩ ∧ # такой же приоритет, как у * (умножение)
|
|
|
+± ⊕ ⊖ ⊞ ⊟ ∪ ∨ # тот же приоритет, что и у + (сложение)
|
|
|
```
|
|
|
|
|
|
-Unicode operators can be combined with non-Unicode operator symbols. The usual precedence extensions then apply, for example, ×= is an assignment like operator just like *= is.
|
|
|
+Операторы **Юникода** можно комбинировать с символами операторов, не входящими в **Юникод**. При этом применяются обычные расширения приоритета, например `×=` — это оператор присваивания, как и `*=`.
|
|
|
|
|
|
-No Unicode normalization step is performed.
|
|
|
+Этап нормализации Unicode не выполняется.
|