Устойчивость синтаксиса

Формальное описание синтаксиса и однозначность разбора несомненно важны для автоматической обработки текста программы. Однако, не менее важно, чтобы текст программы воспринимался человеком[6]. А человеку свойственно ошибаться. Мы будем говорить, что синтаксис языка устойчив к ошибкам, если опечатки, слабо изменяющие текст программы, приводят к синтаксическим ошибкам. Иными словами:

1. Случайные ошибки и опечатки должны обнаруживаться;

2. Разные конструкции должны визуально различаться.

Поскольку данное определение неформально и весьма расплывчато, продемонстрируем понятие устойчивости на нескольких примерах. Рассмотрим следующий оператор цикла на языке C:

for (i = 0; i<N-1; i++);

A[i] = A[i+1];

Очевидно, что здесь имелось ввиду, что оператор присваивания A[i]=A[i+1]; выполнится N-1 раз. Однако, «случайная» точка с запятой в конце первой строки кардинально меняет структуру, и оператор присваивания оказывается вне цикла и, соответственно, цикл выполнит N-1 «холостую» итерацию, после чего пересылка будет выполнена лишь один раз. Заметим, что если бы оператор цикла имел завершитель, то такой ситуации не возникло, как, например, в языке Алгол 68:

.for i.from 0.to N-2.do

A[i]:= A[i+1]

.od

Ещё один пример на языке C - синтаксически корректный фрагмент:

float x;

for (float x=0.0; x<=1,2; f=+0.1)

s = + f(x);

Здесь первая проблема заключается в «случайной» запятой в условии x<=1,2, хотя, очевидно, подразумевалось x<=1.2. Синтаксис последовательного выражения языка C делает это условие эквивалентным x<=2, что приведёт к тому, что цикл будет выполнен лишних 8 раз. Вторая ошибка связана с устаревшей формой присваивания =+, означающего «увеличить на». «Случайный» пробел после равенства делает равенство обычной пересылой, а + - унарной операцией. В результате оператор стал эквивалентным s=f(x). Новая форма совмещённого присваивания += не имеет этого недостатка.

Рассмотрим пример на языке C, где присваивается переменная y, а источник присваивания достаточно длинный, чтобы разумно было записать его на двух строчках:

y = a[0]/2 + a[1]//3 + a[2]/5 + a[3]/7

+ a[4]/11 + a[5]/13 + a[6]/17 + a[7]/19;

«Случайно» удвоенный символ деления / превращается в начало комментария, заканчивающегося концом строки, но оператор остаётся синтаксически правильным и эквивалентным

y = a[0]/2 + a[1]

+ a[4]/11 + a[5]/13 + a[6]/17 + a[7]/19;

Пример на языке Фортран, где цикл DO имеет вид

DO переменная-цикла = начальное-значение [, шаг ], конечное значение

В следующем операторе «случайная» точка вместо запятой в заголовке цикла

10 DO I = 1.2,N

S = S * I

CONTINUE

приводит к тому, что шаг цикла становится равным не 2, а умолчательному, равному 1.

Последний пример – на языке Алгол 68:

for i from 10.to N.do

print(“ “)

od;

Здесь сыграли роль три решения, заложенных в синтаксисе языка. Во-первых, ключевые слова отличаются от идентификаторов точкой в начале. Во-вторых, внутри идентификаторов для лучшей читаемости можно использовать пробелы. В-третьих, в цикле.for можно опускать начальное значение, по умолчанию равное 1. В результате «случайно» забытая точка перед ключевым словом.from делает цикл эквивалентным

.for ifrom10.from 1.to N.do

print(“ “)

.od;

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


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: