Страницы

Синтаксис — основа языка программирования, а не что-то там

В среде не только обычных программистов, но даже и некоторых разработчиков, близких к компиляторной тематике, принято пренебрежительное отношение к синтаксису языка программирования как к второстепенной детали, которой противопоставляется семантика, которая только и имеет серьёзное значение. Считается, что в крайнем случае, всегда можно снабдить один язык программирования несколькими синтаксисами и это лишь вопрос вкуса. Но есть одно очевидное соображение, которое, очевидно, оказалось не таким уж очевидным, но которое делает такое отношение абсурдным.

Дело в том, что до тех пор, пока язык остаётся алгоритмически полным, то есть полным по Тьюрингу, в нём можно описать всю ту же семантику, что и в любом другом алгоритмически полном языке. Ключевая разница между языками заключается не в самой возможности выразить семантику, а то, как именно её можно выражать. И главное отличие языков пролегает как раз через различия в синтаксисе. Синтаксис языка задаёт не столько текстовое представление терминалов, сколько основные конструкции языка, формирующие его основные понятия, без которых и мыслить о языке не получится. Выбор синтаксиса совсем не сводится к выбору между фигурными скобками — {}, ключевыми словами begin end или значимыми отступами. Этим обычно занимается лексика языка, которую в зависимости от желаемого результата могут как отделять в отдельную дисциплину, так и рассматривать неотделимой частью синтаксиса. В любом случае лексика для синтаксиса второстепенна и не определяет его суть.

Рассмотрим для примера корневые синтаксические уравнения двух языков: Оберона и Си

  1. module = "MODULE" ident ";" 
      [ImportList] 
      [DeclarationSequence]
    ["BEGIN" StatementSequence]
    "END" ident "." .
  2. translation_unit = external_declaration {external_declaration} .

Несмотря на минимум информации эти уравнения сразу знакомят нам с совершенно разными понятиями этих языков.

  1. В случае Оберона программной единицей является именованная сущность, содержащая опциональные списки импорта, объявлений и операторов. Порядок объявления списков строго задан.
  2. В случае Си единицей трансляции является непустой безымянный список внешних объявлений, равноправных c точки зрения расположения в коде.

Хотя в примере остаётся непрояснённой суть упоминаемых в них нетерминалов и ничего не сказано о смысле уравнений, уже может быть понятно, что конструкции, задаваемые этимм синтаксами, несут в себе разный смысл и не сопоставляются друг с другом напрямую.

Если посмотреть на синтаксис типичного динамически типизированного языка, то скорее всего там не найдётся уравнений для задания и использования типов, но они почти наверняка обнаружатся в синтаксисе статически типизированного языка. Структурность потока управления в операторах Оберона-07 выражается в отсутствии синтаксиса для неструктурных операторов, наподобие break, continue, goto, throw, return[0]. Так, ключевые особенности языка находят своё отображение в его синтаксисе и напрямую от него зависят.

Когда мы говорим, что важна только семантика, понимаем ли мы до конца, что такое семантика? Кто-то скажет, что всё просто — семантика задаёт смысл синтаксических конструкций. Такое прояснение, с одной стороны, при ближайшем рассмотрении может показаться бесполезным, так как задаёт смысл термина используя слово, являющееся его синонимом. С другой стороны, оно хорошо иллюстрирует работу семантики, которая состоит в сопоставлении друг другу разных синтаксических конструкций. Это означает, что для задания семантики нового синтаксиса нужен синтаксис другого языка, семантику которого посчитали базовой, но которая тоже в конечном итоге выражается через сопоставление.

Возможно, с точки зрения мистики смысл чего-либо может иметь некоторое нематериальное духовное происхождение, но в скучном материалистическом мире смысл всегда выражается с помощью материи по некотором правилам. А эти правила неизбежно найдут своё отображение в абстракции под названием «синтаксис». Для задания семантики синтаксиса не только нужен синтаксис языка — донора семантики, но и сами правила сопоставления фрагментов синтаксисов описываются на некотором языке, который, конечно, тоже имеет некий синтаксис. Синтаксис на синтаксисе синтаксисом погоняет.

Итого:

  1. Для определения языка семантика не только не является более важным понятием, чем синтаксис, но и попросту не существует без синтаксиса, точно так же, как не существует смысла слов без самих слов.
  2. Одной из причин неправильной оценки синтаксиса является спутывание его с лексикой — его лишь второстепенной частью.
  3. Один язык не может иметь несколько существенно отличающихся синтаксисов. Относительно безболезненно можно менять лишь лиственную часть синтаксического дерева — той части, что ближе к терминалам. Это можно сравнить с заменой кодировки для передачи текста. И как смена кодировки не считается существенным изменением текста, так и смена терминальной части синтаксиса не должна считаться существенным изменением синтаксиса. Часть же синтаксиса, находящаяся ближе к корню, задаёт представление важных конструкций языка и не может быть существенно изменена без существенного изменения языка.

Понимание этого имеет важное практическое значение.


[0] В Oberon-07 есть лексические элемент RETURN, всегда заверщающий процедуру, возвращающую значение, но это не оператор, который может встречаться наравне с другими операторами, как это было в предыдущих определениях языка.

Комментариев нет:

Отправить комментарий