Алгол: правильный синтаксис приводит к проблемам при компиляции?

Вот сравнительно простой код для "Оценки числа Пи с использованием правила среднего ординаты в квадранте круга с радиусом 2 единицы".

main.alg

BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;

FOR n BY interval TO upperlimit DO
    sumy := 0.0;

    FOR p BY 2 TO n+n-1 DO 
        x := p/n;
        y := sqrt(4.0 - x**2);
        sumy := sumy + y;
    OD
    pi := sumy * (2.0 / n);
    print((n,pi))
OD
END

Я получаю следующие ошибки:

a68g: syntax error: 1: possibly a missing or erroneous separator nearby.                                                                             
sh-4.3$ a68g main.alg                                                                                                                                
13                sumy := sumy + y;                                                                                                                  
                              1                                                                                                                  
a68g: warning: 1: skipped superfluous semi-symbol.                                                                                                   
15            pi := sumy * (2.0 / n);                                                                                                                
          1                                                                                                                                      
a68g: syntax error: 1: possibly a missing or erroneous separator nearby.  

Попробуйте жить здесь.

Что я делаю неправильно? Как это исправить?


1 ответ

Решение

Краткий ответ: в следующем коде исправлена ​​ваша конкретная проблема...

Следует помнить, что ";" является "разделителем операторов"... поэтому все "составные операторы" должны иметь каждый оператор, разделенный ";".. например, рассмотреть:

statement; statement; statement # is a valid program #
statement; statement statement; # is not valid #

(statement; statement; statement) # is a valid program #
(statement; statement; statement;) # is not valid #
(statement; statement; statement); # is not valid #

Мораль это... отделить все утверждения с ";" и не ставьте ";" после последнего заявления. (например, перед END, FI, DO, ")" или ESAC)

BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;

FOR n BY interval TO upperlimit DO
    sumy := 0.0;

    FOR p BY 2 TO n+n-1 DO 
        x := p/n;
        y := sqrt(4.0 - x**2);
        sumy := sumy + y
    OD;
    pi := sumy * (2.0 / n);
    print((n,pi))
OD
END

Интересно отметить, что вы часто можете использовать "," вместо ";", это говорит компилятору, что вам все равно, в каком порядке выполняются операторы. Это называется ГОММА. (Сокращение иди и запятая)

Например, GOMMA следует использовать с осторожностью, поскольку компилятор не обязан предупреждать вас о побочных эффектах... например (теоретически)

#!/usr/bin/a68g --script #
# -*- coding: utf-8 -*- #

INT x:=0;
(x+:=1, x+:=2); # allow the compiler the choice of threading #
PAR(x+:=10, x+:=20); # force statements into different threads #
printf(($"Answer="gl$,x))

Какой ответ? ... это может быть 33, но также может быть 21 или 12 и т. д. в зависимости от вашего компилятора.

В этом случае операция +:= настолько мала и быстра, что ответ, вероятно, будет 33.

Длинный ответ: расположение разделителей операторов на языках вызывает печаль на протяжении многих лет. Например, рассмотрим следующий код FORTRAN с пропущенной запятой:

DO 999 I=1 1000
  PRINT *,I
999 CONTINUE

Эта ошибка была найдена и исправлена ​​до запуска Project Mercury. Городской миф гласит, что в программе Mariner была похожая ошибка, приводившая к сбою.

Обратите внимание, что часто полезно иметь "поддельные" операторы, это используется для выполнения требований синтаксиса / семантики. Python в качестве различных примеров, например: "None", "NoneType" и "pass". Algol68 имеет "VOID", "SKIP" и "~"

Чтобы продемонстрировать использование SKIP (или "~").

BEGIN
REAL x, y, sumy, pi;
INT n := lowerlimit, p := 1, lowerlimit := 10, upperlimit := 100, interval := 10;

FOR n BY interval TO upperlimit DO
    sumy := 0.0;

    FOR p BY 2 TO n+n-1 DO 
        x := p/n;
        y := sqrt(4.0 - x**2);
        sumy := sumy + y; SKIP # insert a "fake statement after the ";" #
    OD; # the ";" is still needed #
    pi := sumy * (2.0 / n);
    print((n,pi))
OD
END

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

statement1;
statement2;
SKIP COMMENT
statement3;
statement4 # eg. no ";" on the last statement #
END COMMENT

Без SKIP программа не будет компилироваться.

В случае с Algol68 есть странная ситуация с двусмысленностью Йонеды. С тех пор эта неоднозначность преследует многие языки программирования, включая Ada и python, и, возможно, даже C...

Чтобы узнать больше, зайдите в свою университетскую библиотеку и прочитайте: "История АЛГОЛА 68" - CH Lindsey - [Включает в себя откровенное отражение процесса разработки языка "Редакция по почте", языковая функция борется с "Изгибом" и включает / исключенные неясности (например, двусмысленность Йонеды и кровосмесительные союзы)]

В python они пытаются обойти "Разделитель", делая его необязательным и скрывая его с отступом... но неясность запятой осталась... например. определить синтаксическую / семантическую ошибку и ошибку времени выполнения в следующем...

print [i for i in ()]
print [i for i in (1)]
print [i for i in (1,2)]
print [i for i in (1,2,3)]
ab="ab etc etc etc"
print "first 2 only: %c,%c"%ab[0:2]

C также немного страдает от "куда я ставлю точку с запятой и запятую"... логика в том, что ";" никогда не нужно следовать за "}", например всегда ";}", но никогда "};"... Оказывается, иногда вам нужно ";};"

Затем C полностью добавляет гаечный ключ в произведениях для запятых, никогда не ",)" но иногда "),".

Algol68 1968 года выдает сообщение об ошибке для этого класса двусмысленностей. Мораль этой истории может быть следующей: если ваш компилятор не улавливает такую ​​двусмысленность во время компиляции, тогда (возможно) вам следует выбрать другой язык.

Кстати: вы можете найти несколько примеров программ на Algol68 здесь... А затем ваш код с удаленными острыми краями.

INT lower limit = 10, upper limit = 100, interval = 10;

PROC circle = (REAL x)REAL: sqrt(4 - x**2);

FOR n FROM lower limit BY interval TO upper limit DO
    REAL sum y := 0;

    FOR p FROM 1 BY 2 TO 2*n DO
        REAL x = p/n;
        REAL y = circle(x);
        sum y +:= y
    OD;
    REAL pi := sum y * 2 / n;
    printf(($g(0)": "g(-real width,real width-2)l$,n,pi))
OD

Сравните изменения кода, чтобы увидеть, сможете ли вы выяснить эффект и какие подсказки они предоставляют...:-)

Или... вот как стандартная числовая квадратурная программа может быть закодирована для совместного использования. Обратите внимание на использование передаваемых функций в качестве аргументов, в частности, здесь есть концепция, называемая Curry. circle(2,)... где запятая имеет значение!

INT lower limit = 10, upper limit = 100, interval = 10;

PROC circle = (REAL radius, x)REAL: sqrt(radius**2 - x**2);

PROC mid point integrate = (PROC(REAL)REAL f, REAL lwb, upb, INT num steps)REAL: (
  REAL dx := (upb - lwb ) / num steps;
  REAL x := lwb + dx/2;
  REAL sum y := 0;

  FOR p TO num steps DO
      REAL y = f(x);
      sum y +:= y;
      x +:= dx
  OD;
  sum y * dx
);

FOR num steps FROM lower limit BY interval TO upper limit DO
  REAL pi := mid point integrate(circle(2,),0,2,num steps);
  printf(($g(0)": "g(-real width,real width-2)l$,num steps,pi))
OD
Другие вопросы по тегам