Введение

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

Правило отступов описывает синтаксис языка программирования, определяющий границы блока кода с помощью отступов. Термин был придуман Питером Лэндином, возможно, как игра слов, основанная на правиле офсайда в футболе. Язык с правилом отступов противопоставляется языку со свободной формой, в котором отступы не имеют синтаксического значения и являются исключительно вопросом стиля. Язык с правилом отступов также называют языком с значимыми отступами.

Определение

Питер Лэндин в своей статье 1966 года "Следующие 700 языков программирования" определил правило отступов следующим образом: "Любой символ, не являющийся пробелом, расположенный левее первого такого символа на предыдущей строке, считается началом новой декларации".

Реализация

Правило отступа может быть реализовано на этапе лексического анализа, как в Python, где увеличение отступа приводит к тому, что лексер выдает токен INDENT, а уменьшение отступа – токен DEDENT. Эти токены соответствуют открывающей фигурной скобке { и закрывающей фигурной скобке } в языках, использующих фигурные скобки для обозначения блоков, и означают, что синтаксис не зависит от того, используются ли скобки или отступы. Для этого лексеру необходимо хранить состояние, а именно текущий уровень отступа, и, следовательно, обнаруживать изменения отступа при их возникновении. Таким образом, лексический синтаксис не является контекстно-свободным: токены INDENT и DEDENT зависят от контекстной информации о предыдущем уровне отступа.

Альтернативы

Основной альтернативой разграничению блоков с помощью отступов, получившей распространение благодаря широкому использованию и влиянию языка C, является игнорирование пробельных символов и явное обозначение блоков фигурными скобками (т. е., { и }) или другими разделителями. Это обеспечивает большую свободу форматирования – разработчик может не делать отступы для небольших фрагментов кода, таких как операторы `break` и `continue`, – однако небрежные отступы могут сбить читателя с толку, например, как в ошибке `goto fail`. Lisp и другие языки, основанные на S-выражениях, не различают операторы и выражения, и круглых скобок достаточно для управления областью видимости всех операторов в языке. Как и в языках с фигурными скобками, пробельные символы в основном игнорируются интерпретатором (т. е., функцией чтения). Пробелы используются для разделения токенов. Явная структура кода Lisp позволяет автоматически добавлять отступы, создавая визуальную подсказку для читающего. Другая альтернатива заключается в том, чтобы каждый блок начинался и заканчивался явными ключевыми словами. Например, в ALGOL 60 и его потомке Pascal блоки начинаются с ключевого слова `begin` и заканчиваются ключевым словом `end`. В некоторых языках (но не в Pascal) это означает, что переносы строк важны (в отличие от языков с фигурными скобками), а отступы – нет. В BASIC и Fortran блоки начинаются с имени блока (например, `IF`) и заканчиваются именем блока, предваряемым `END` (например, `END IF`). В Fortran каждый блок может иметь свое собственное уникальное имя блока, что добавляет дополнительный уровень явности для длинного кода. ALGOL 68 и оболочка Bourne (sh и bash) похожи, но конец блока обычно указывается именем блока, записанным в обратном порядке (например, `case` начинает оператор `switch` и продолжается до соответствующего `esac`; аналогично условные операторы `if then [elif [else ]]fi` или циклы `for do od` в ALGOL68 или `for do done` в bash). Интересный вариант этого встречается в Modula 2, языке, похожем на Pascal, который устраняет разницу между однострочными и многострочными блоками. Это позволяет опустить открывающий блок ({ или `BEGIN`) для всех блоков, кроме блоков уровня функции, требуя только токен завершения блока (} или `END`). Это также решает проблему "висячих" `else`. Обычно токен завершения помещается на том же уровне отступа, что и остальная часть блока, что обеспечивает очень читаемую структуру блока. Одним из преимуществ подхода Fortran является то, что он повышает читаемость длинного, вложенного или сложного кода. Группа отступов или закрывающих скобок сама по себе не дает контекстных подсказок о том, какие блоки закрываются, что требует возврата и более внимательного изучения при отладке. Кроме того, языки, которые позволяют добавлять суффиксы к `END`, как ключевым словам, еще больше улучшают такие подсказки, например, `continue` против `continue for x`, и маркер конца цикла, указывающий переменную индекса `NEXT I` против `NEXT`, и уникальные имена циклов `CYCLE X1` против `CYCLE`. Однако современные редакторы исходного кода часто предоставляют визуальные индикаторы, такие как подсветка синтаксиса, и функции, такие как сворачивание кода, чтобы помочь справиться с этими недостатками.

Производительность

В языке Scala ранние версии допускали использование только фигурных скобок. Scala 3 добавила возможность структурировать блоки с помощью отступов. Разработчик Мартин Одерски заявил, что это стало самым важным улучшением в Scala 3, повысившим его личную продуктивность, позволяя сократить программы более чем на 10% и поддерживая программистов в состоянии потока, и рекомендует использовать эту возможность.