Краткое описание семантики языка
Оператор присваивания имеет нетрадиционную форму и, в общем случае, обеспечивает одновременное присваивание нескольким переменным, расположенным слева от знака «:=» значений предварительно вычисленных выражений, расположенных в правой части. Каждой переменной соответствует свое выражение. Присваивания начинаются только после вычисления всех выражений, результаты которых временно сохраняются. Это позволяет произвести обмен значений переменных с использованием только одного оператора присваивания:
x, y := y, x
В обычных языках программирования необходимо написать три отдельных оператора:
t := x; x := y; y := t
Выражения задаются в традиционной инфиксной форме. Порядок выполнения операций определяется их приоритетом и скобками. В начале выполняются выражения в скобках. Наивысший приоритет имеет унарный минус «-», далее следуют мультипликативные операции «*», «/», «%» (вычисление остатка), затем аддитивные «+», «-» и, наконец операции отношения «<», «=», «>», «<=», «>=», «!=».
Для представления пустого оператора Дейкстра намеренно использовал специальное ключевое слово skip (что мотивировал соответствующим текстом), хотя в большинстве языков программирования пустой оператор - это пустое место:
$ пустой = .
Для того чтобы продемонстрировать решения проблемы неоднозначности синтаксиса языка, возникающие из-за наличия «традиционного» пустого оператора, в язык DPL введены оба варианта написания.
Для экстренного выхода из любой точки программы в языке используется оператор прерывания abort. Необязательная строка символов предназначена для пояснения причины выхода из программы.
В соответствии с концепциями безошибочного программирования, разработанными Дейкстрой, определены условный оператор и оператор цикла. Их тела содержат наборы операторов, выполнение которых возможно только при истинности условий, задаваемых предваряющими их охраняющими выражениями. Выражения отделяются от охраняемых ими операторов стрелками «->» и, начиная с первого, последовательно анализируются до тех пор, пока не встретится «истинное». Истинным считается ненулевое значение выражения. Предполагается, что в рассматриваемой версии языка операции отношения возвращают в качестве результата целое число, равное 1, при выполнении условия и, равное 0, если условие не выполняется. Если в условном операторе все охраняющие выражения дают ложь, то он выполняется как оператор ошибки (abort). Оператор цикла в данной ситуации эквивалентен пустому оператору (skip). Возникновение такой ситуации обеспечивает выход из цикла. При наличии истинного охраняющего выражения происходит выполнение охраняемых операторов и повторное выполнение оператора цикла. Оператор abort также эквивалентен конструкции case end (пустое тело в условном операторе), а оператор skip - оператору loop end.
Спецификаторы space, tabи skipиспользуются в операторе вывода для форматирования выходного потока данных и означают пробел, табуляцию и перевод строки. Выражение, следующее за спецификатором, определяет количество его повторений. Строка символов используется для вывода пояснительного текста.
Примеры программ на DPL
Ниже приведены примеры программ, раскрывающие особенности использования языка.
Алгоритм Евклида (нахождение наибольшего общего делителя)
begin
var x, y: int; /* описание переменных */
read x, y; /* ввод операндов */
/* выполнять до равенства аргументов */
loop x != y ->
case
x > y -> x := x - y
or
y > x -> y := y - x
end
end;
write x /* полученный НОД */
end
Одновременное нахождение наибольшего общего делителя (НОД) и наименьшего общего кратного (НОК)
begin
var x, y, u, v: int; /* описание переменных */
read x, y; /* ввод операндов */
u, v := y, x;
/* выполнять до равенства аргументов */
loop
x > y -> x, v := x - y, v + u
or
y > x -> y, u := y - x, u + v
end;
write "НОД = ", x; /* НОД */
write skip, "НОК = ", (u + v) / 2 /* НОК */
end