Введение

Слово в языке программирования, которое нельзя использовать в качестве идентификатора. В компьютерном языке зарезервированное слово (также известное как зарезервированный идентификатор) — это слово, которое нельзя использовать в качестве идентификатора, например, имени переменной, функции или метки, — оно "зарезервировано для использования". Это синтаксическое определение, и зарезервированное слово может не иметь значения, определяемого пользователем. Тесно связанным и часто смешиваемым понятием является ключевое слово, которое представляет собой слово, имеющее специальное значение в определенном контексте. Это семантическое определение. Имена в стандартной библиотеке, но не встроенные в язык, не считаются зарезервированными словами или ключевыми словами. Термины "зарезервированное слово" и "ключевое слово" часто используются как взаимозаменяемые — можно сказать, что зарезервированное слово "зарезервировано для использования в качестве ключевого слова", и их формальное использование варьируется от языка к языку. Для данной статьи мы придерживаемся вышеуказанного различия. В общем случае зарезервированные слова и ключевые слова не обязаны совпадать, но в большинстве современных языков ключевые слова являются подмножеством зарезервированных слов, поскольку это упрощает разбор, так как ключевые слова нельзя спутать с идентификаторами. В некоторых языках, таких как C или Python, зарезервированные слова и ключевые слова совпадают, в то время как в других языках, таких как Java, все ключевые слова являются зарезервированными словами, но некоторые зарезервированные слова не являются ключевыми словами, поскольку они зарезервированы для будущего использования. В других языках, таких как более старые языки ALGOL, FORTRAN и PL/I, есть ключевые слова, но нет зарезервированных слов, при этом ключевые слова отличаются от идентификаторов другими способами.

Синтаксис

Зарезервированное слово – это слово, которое "выглядит как" обычное слово, но не допускается к использованию в качестве такового. Формально это означает, что оно удовлетворяет обычному лексическому синтаксису (синтаксису слов) идентификаторов – например, являясь последовательностью букв – но не может быть использовано там, где используются идентификаторы. Например, слово `if` обычно является зарезервированным словом, в то время как `x` обычно не является, поэтому `x = 1` является допустимым присваиванием, а `if = 1` – нет. Ключевые слова имеют различное применение, но в основном относятся к нескольким классам: часть грамматики синтаксических конструкций (в частности, правило вывода с нетерминальными символами), с различными значениями, часто используемыми для управления потоком выполнения, например, слово `if` в большинстве процедурных языков, которое указывает на условный оператор и принимает блоки (нетерминальные символы); имена примитивных типов в языке, поддерживающем систему типов, например, `int`; примитивные литеральные значения, такие как `true` для логического значения "истина"; или иногда специальные команды, такие как `exit`. Другие применения ключевых слов в синтаксических конструкциях – ввод/вывод, например, `print`. Четкость различных определений проявляется при анализе языка комбинацией лексера и парсера, когда синтаксис языка генерируется лексической грамматикой для слов и контекстно-свободной грамматикой правил вывода для синтаксических конструкций. Это распространено при анализе современных языков, и в этом случае ключевые слова являются подмножеством зарезервированных слов, поскольку их необходимо отличать от идентификаторов на уровне слов (отсюда и зарезервированные слова), чтобы синтаксически анализировать их по-разному на уровне синтаксических конструкций (как ключевые слова). В этом случае зарезервированные слова определяются как часть лексической грамматики и токенизируются как отдельные типы, отличные от идентификаторов. В общепринятой нотации зарезервированные слова `if` и `then`, например, токенизируются как типы `IF` и `THEN` соответственно, в то время как `x` и `y` токенизируются как тип `Identifier`. Ключевые слова, напротив, синтаксически появляются в грамматике синтаксических конструкций как терминальные символы. Например, правило вывода для условного выражения может быть `IF Expression THEN Expression`. В этом случае `IF` и `THEN` являются терминальными символами, означающими "токен типа `IF` или `THEN` соответственно", и благодаря лексической грамматике это означает строку `if` или `then` в исходном коде. В качестве примера примитивного константного значения, `true` может быть ключевым словом, представляющим логическое значение "истина", в этом случае оно должно появляться в грамматике как возможное расширение правила вывода `BinaryExpression`, например.

Запрещенные диапазоны

Помимо резервирования конкретных списков слов, некоторые языки резервируют целые диапазоны слов для использования в качестве приватных пространств для будущих версий языка, различных диалектов, расширений, специфичных для поставщиков компиляторов, или для внутреннего использования компилятором, в частности, при искажении имен. Чаще всего это делается с помощью префикса, как правило, одного или нескольких символов подчеркивания. Языки C и C++ примечательны в этом отношении: C99 резервирует идентификаторы, начинающиеся с двух символов подчеркивания или символа подчеркивания, за которым следует заглавная буква, а также дополнительно резервирует идентификаторы, начинающиеся с одного символа подчеркивания (в обычных и теговых пространствах) для использования в области видимости файла; C++03 дополнительно резервирует идентификаторы, содержащие двойное подчеркивание в любом месте – это позволяет использовать двойное подчеркивание в качестве разделителя (для соединения пользовательских идентификаторов), например. Частое использование двойного подчеркивания во внутренних идентификаторах в Python привело к появлению аббревиатуры "dunder", которая была придумана Марком Джексоном и независимо Тимом Хохбергом практически одновременно, отвечая на один и тот же вопрос в 2002 году.

Спецификация

Список зарезервированных слов и ключевых слов в языке определяется в процессе его разработки и оба они являются частью формальной спецификации языка. Как правило, стремятся минимизировать количество зарезервированных слов, чтобы не ограничивать допустимые имена идентификаторов. Более того, введение новых зарезервированных слов нарушает работу существующих программ, использующих это слово (что является нарушением обратной совместимости), поэтому этого стараются избегать. Чтобы предотвратить это и обеспечить прямую совместимость, иногда слова резервируются без текущего использования (зарезервированное слово, которое не является ключевым словом), что позволяет использовать это слово в будущем, не нарушая работу существующих программ. В качестве альтернативы, новые языковые конструкции могут быть реализованы как предопределенные элементы, которые можно переопределить, тем самым не нарушая работу существующих программ. Причины такой гибкости включают возможность для разработчиков компиляторов расширять спецификацию, добавляя нестандартные функции, возможность для различных стандартных диалектов языка расширять его, или возможность для будущих версий языка включать дополнительные функции. Например, процедурный язык может предусмотреть добавление объектно-ориентированных возможностей в будущей версии или в каком-либо диалекте, в этом случае можно добавить ключевые слова, такие как `class` или `object`. Чтобы учесть такую возможность, текущая спецификация может зарезервировать эти слова, даже если они в настоящее время не используются. Ярким примером является Java, где `const` и `goto` являются зарезервированными словами — они не имеют значения в Java, но также не могут использоваться в качестве идентификаторов. Зарезервировав эти термины, их можно будет реализовать в будущих версиях Java, если потребуется, без нарушения работы старого исходного кода Java. Например, в 1999 году было предложено добавить в язык конструкцию `const` в стиле C++, что было возможно благодаря зарезервированному слову `const`, хотя оно в то время не использовалось; однако это предложение было отклонено, в частности, потому что, хотя добавление этой конструкции не нарушило бы работу существующих программ, использование её в стандартной библиотеке (особенно в коллекциях) нарушило бы совместимость. JavaScript также содержит ряд зарезервированных слов без специальной функциональности; точный список варьируется в зависимости от версии и режима. Языки существенно различаются по частоте введения новых зарезервированных слов или ключевых слов и по способам их наименования: некоторые языки очень консервативны и редко или никогда не вводят новые ключевые слова, чтобы избежать нарушения работы существующих программ, в то время как другие языки вводят новые ключевые слова более свободно, требуя от существующих программ изменить идентификаторы, которые конфликтуют. Примером может служить сравнение новых ключевых слов в C11 и C++11, оба стандарта были выпущены в 2011 году — напомним, что в C и C++ идентификаторы, начинающиеся с символа подчеркивания, за которым следует заглавная буква, являются зарезервированными:

Таким образом, C11 ввел ключевое слово `Thread local` в существующий набор зарезервированных слов (с определенным префиксом), а затем использовал отдельный механизм (макросы) для обеспечения его использования как нового ключевого слова без какого-либо префикса, в то время как C++11 ввел ключевое слово `thread local`, несмотря на то, что это не было существующим зарезервированным словом, что привело к нарушению работы любых программ, использующих это слово, но без необходимости использования макросов.

Предварительно определенные имена

Связанным понятием к зарезервированным словам являются предопределенные функции, методы, подпрограммы, типы или переменные, в особенности библиотечные процедуры из стандартной библиотеки. Они схожи с зарезервированными словами тем, что являются частью базового языка и могут использоваться для аналогичных целей. Однако они отличаются тем, что имя одной из этих сущностей обычно классифицируется как идентификатор, а не зарезервированное слово, и не обрабатывается особым образом при синтаксическом анализе. Более того, зарезервированные слова не могут быть переопределены программистом, в то время как предопределенные часто могут быть переопределены в пределах определенной области видимости. Языки программирования различаются в том, что предоставляется в качестве ключевого слова, а что как предопределенный элемент. Например, в некоторых языках для операций ввода/вывода используются ключевые слова, а в других – библиотечные процедуры. В Python (версиях до 3.0) и многих диалектах BASIC, `print` является ключевым словом. В отличие от этого, эквиваленты в C, Lisp и Python 3.0 – `printf`, `format` и `print` – являются функциями стандартной библиотеки. Аналогично, в Python до версии 3.0, `None`, `True` и `False` были предопределенными переменными, но не зарезервированными словами, однако в Python 3.0 они стали зарезервированными словами.

Определение

Некоторые используют термины "ключевое слово" и "зарезервированное слово" как взаимозаменяемые, в то время как другие различают их употребление, например, используя "ключевое слово" для обозначения слова, которое является специальным только в определенных контекстах, а "зарезервированное слово" – для обозначения специального слова, которое нельзя использовать в качестве имени, заданного пользователем. Значение ключевых слов и само понятие "ключевое слово" сильно различаются от языка к языку. В ALGOL 68 ключевые слова заключаются в специальные знаки (в строгом языке они выделены жирным шрифтом) и не являются зарезервированными словами – слово без этих знаков можно использовать как обычный идентификатор. В "Спецификации языка Java" используется термин "ключевое слово". В стандарте ISO 9899 для языка C также используется термин "ключевое слово". Во многих языках, таких как C и подобных средах, как C++, ключевое слово является зарезервированным словом, которое определяет синтаксическую конструкцию. Слова, используемые в конструкциях управления потоком, такие как if, then и else, являются ключевыми словами. В этих языках ключевые слова нельзя использовать в качестве имен переменных или функций. В некоторых языках, таких как ALGOL и ALGOL 68, ключевые слова нельзя записывать дословно, а необходимо использовать специальные знаки. Это означает, что ключевые слова должны быть каким-то образом выделены, например, заключением в кавычки или добавлением специального префикса. Как следствие, ключевые слова не являются зарезервированными словами, и, следовательно, одно и то же слово может использоваться как обычный идентификатор. Однако одним из способов выделения ключевых слов было не использовать специальные знаки, а просто считать их зарезервированными словами. Некоторые языки, такие как PostScript, очень либеральны в этом отношении, позволяя переопределять основные ключевые слова для конкретных целей. В Common Lisp термин "ключевое слово" (или "символ ключевого слова") используется для обозначения особого типа символа или идентификатора. В отличие от других символов, которые обычно обозначают переменные или функции, ключевые слова являются самоцитируемыми и самооценивающимися:98 и хранятся в пакете KEYWORD. Ключевые слова обычно используются для обозначения именованных аргументов функций и для представления символических значений. Символы, которые обозначают функции, переменные, специальные формы и макросы в пакете COMMON LISP, по сути, являются зарезервированными словами. Эффект их переопределения не определен в ANSI Common Lisp, но их можно привязать. Например, выражение (if if case or) допустимо, если if является локальной переменной. Левый if относится к оператору if, а остальные символы интерпретируются как имена переменных. Поскольку существует отдельное пространство имен для функций и переменных, if может быть локальной переменной. Однако в Common Lisp есть два специальных символа, которые не входят в пакет ключевых слов: символы t и nil. При вычислении как выражений они возвращают сами себя. Их нельзя использовать в качестве имен функций или переменных, поэтому они фактически являются зарезервированными. (let ((t 42))) – это корректное выражение, но оператор let не позволит его использовать. Обычно, когда программист пытается использовать ключевое слово в качестве имени переменной или функции, возникает ошибка компиляции. В большинстве современных редакторов ключевые слова автоматически выделяются определенным цветом текста, чтобы напомнить или сообщить программистам, что это ключевые слова. В языках с макросами или ленивыми вычислениями конструкции управления потоком, такие как if, могут быть реализованы как макросы или функции. В языках, не имеющих этих возможностей, они обычно являются ключевыми словами.

Сравнение по языкам

Различные языки программирования часто имеют сильно различающееся количество зарезервированных слов. Например, в COBOL их около 400. В Java и других языках, произошедших от C, этот набор довольно небольшой – около 50. В чистом Prolog и PL/I зарезервированных слов нет.

Недостатки

Определение зарезервированных слов в языке порождает сложности. Язык может быть сложен для освоения новыми пользователями из-за длинного списка зарезервированных слов, которые необходимо запомнить и которые нельзя использовать в качестве идентификаторов. Расширение языка также может быть затруднено, поскольку добавление зарезервированных слов для новых возможностей может привести к неработоспособности существующих программ, или, наоборот, "перегрузка" существующих зарезервированных слов новыми значениями может быть дезориентирующей. Перенос программ может быть проблематичным, так как слово, не являющееся зарезервированным в одной системе или компиляторе, может быть зарезервированным в другой. Поскольку зарезервированные слова нельзя использовать в качестве идентификаторов, пользователи могут намеренно допускать опечатки в зарезервированных словах, используя их в качестве идентификаторов, например, для Java-переменных типа .