Search code examples
syntaxcompiler-errorsalgol68

Algol: correct syntax leads to problems in compilation?


Here is a relatively simple code for "Evaluation of pi using the Mid-ordinate Rule on a quadrant of circle with radius 2 units."

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

I'm getting the following errors:

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.  

Try it live here.

What am I doing wrong? How to correct it?



Solution

  • The short answer: The following code has your specific problem fixed...

    The thing to remember is that a ";" is a "statement separator"... so all "compound statement" should have each statement separated by a ";".. eg consider:

    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 #
    

    The moral is... separate all statements with a ";" and dont put a ";" after the last statement. (eg before an END, FI, DO, ")" or 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
    

    It is interesting to note that you can often use a "," instead of a ";", this tells the compiler you dont care what order the statements are run. It is called a GOMMA. (A contraction of go on and comma)

    e.g. The GOMMA should be used sparingly as the compiler is not required to warn you about side effects... for example (in theory)

    #!/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))
    

    What is the Answer? ... it could be 33, but it might also be 21 or 12 etc. depending on your compiler.

    In this case the +:= operation is so small and fast that the answer will probably be 33.

    The long answer: The location of the statement separators in languages cause caused grief through the years. For example consider the following FORTRAN code with a missing comma:

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

    This bug was found and corrected before the launch of Project Mercury. Urban myth has it that the Mariner Program had a similar bug causing it to crash.

    Note that it is often useful to have "Fake" statements, this is used to fulfill syntax/semantic requirements. Python as various examples, eg: "None", "NoneType" and "pass". Algol68 has "VOID", "SKIP" and "~"

    To demonstrate the usage of SKIP (or "~").

    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 is often used to permit code to be cleanly commented out:

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

    Without the SKIP the program would not compile.

    In the case of Algol68, there is a weird case Yoneda's ambiguity. This ambiguity has haunted numerous programming languages ever since, including Ada and python, and maybe even C...

    To find out more go to your university library and read: "A History of ALGOL 68" - by C. H. Lindsey - [Includes a candid reflection of the language design process "Revision by mail", language feature struggles "The Bend" and included/excluded ambiguities (eg Yoneda's ambiguity and incestuous unions)]

    In python they tries to side step the "Separator" by making it optional and hiding it with indentation... but the comma ambiguity remained.. eg. spot the syntax/semantic error, and run time error in the following...

    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 also suffers a little from "where do I put a semicolon and comma"... the logic is that the ";" need never follow a "}", eg always ";}" but never "};"... It turns out that sometimes you do need ";};"

    Then C completely throws a spanner in the works for commas with never ",)" but sometimes "),".

    1968's Algol68 does produce an error message for this class of ambiguities. The moral to the story might be: if your compiler does not pick up this kind of ambiguity at compile time, then (just maybe) you should pick another language.

    BTW: You can find some sample Algol68 Programs here... And next is your code with the sharp edges removed.

    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
    

    Compare the code changes to see if you can figure out the effect and what hints they provide... :-)

    Or... here is how a standard numerical quadrature program might be coded for sharing. Note the use of passing functions as arguments, in particular there is a concept called Currying here circle(2,) ... where the comma is significant!

    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