DataMuseum.dk

Presents historical artifacts from the history of:

RC4000/8000/9000

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about RC4000/8000/9000

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download

⟦7c87a6d30⟧ TextFile

    Length: 73728 (0x12000)
    Types: TextFile
    Names: »tptoa«

Derivation

└─⟦00964e8f7⟧ Bits:30007478 RC8000 Dump tape fra HCØ.
    └─⟦b2ec5d50f⟧ 
        └─⟦this⟧ »tptoa« 

TextFile

begin
procedure writetest(text);
integer array text;
begin
integer i,j,k;
j:=system(3,k,text);
for i:=j,i+1 while i<=k and text(i-1) <> 0 do
  begin
  outchar(out,if text(i) = 0 then 38 else text(i));
  end;
if text(i-1) <> 0 then outchar(out,37);
end writetest;

procedure writetesti(text,j);
value j; integer j; integer array text;
begin
integer i,k;
system(3,k,text);
for i:=j,i+1 while i<=k and text(i-1) <> 0 do
  begin
  outchar(out,if text(i) <> 0 then text(i) else 38);
  end;
if text(i-1) <> 0 then outchar(out,37);
end writetesti;

procedure writetestnl(textstring);
string textstring;
begin
write(out,<:<10>:>,textstring,<:<58>:>);
end writetestnl;
procedure writetestno(number);
value number; integer number;
begin
write(out,number);
end writetestno;

procedure writetestchar(char);
value char; integer char;
begin
if char > 32 and  char < 127 then
 outchar(out,char)
 else
  write(out,false add 34,1,<<zdd>,char,false add 34,1);

end writetestchar;


integer searchtablelength,
        ntablength,
        stdlinelength,
        maxniveau;
comment all texts is assumed to be of stdlinelength,
        unless otherwise conditions assure another length
        ;
stdlinelength := 132;


comment table length initialisation;
searchtablelength := 253; 

ntablength := 6000;

comment in sequential pascal their is only 2 niveaus
        program and procedure, note no
        local procedures;
maxniveau := 1;
  


  begin
  integer array 
     ntab(0:ntablength),
     searchtable(0:searchtablelength);

integer entrynext,
        entrytype,
        entrylength,
        entrynamelength,
        entrytypeid,
        basicentrylength,
        entrytypedeckind,
        entryparameterlistlength,
        entrytypedecref;

comment entry types;
integer constantentry,
        typedecentry,
        recorddecentry,
        recordentry,
        reservedword,
        variabledecentry,
        structuredecentry,
        routineheading,
        enumerationconstantentry,
        recordfixedpartelemententry,
        recordelementfixedinwithblockentry,
        recordelementvariantentry
        recordelementvariantinwithblockentry;

comment name types;
integer notype,
        integertype,
        realtype,
        chartype,
        booleantype,
        stringtype,
        nextdeclaredtype;

comment type declaration kinds;
integer enumerationtype,
        previusdefinedtype,
        simpletype,
        subrangetype;

procedure initofntabrecord;
begin
comment this procdure inits constants which
        conserning records and entrylength 
        in the ntab;
comment identifier symbol record describtion;
entrynext := 0;
entrylength := 1;
  basicentrylength := 6;
entrynamelength := 3;
entrytype := 4;
      constantentry := 1;
      typedecentry := 2;
      recorddecentry := 3;
      recordentry := 4;
      reservedword := 5;
      variabledecentry := 7;
      structuredecentry := 8;
      routineheading := 9;
entrytypeid :=5;
comment refference to a structured type,
        if type dec kind is previus definied type;
entrytypedecref := 5;
  notype := 0;
  integertype:= 1;
  realtype := 2;
  chartype:= 3;
  booleantype := 4;
  stringtype := 5;
  nextdeclaredtype := 6;
entryparameterlistlength := 6;
entrytypedeckind := 6;
  enumerationtype := 1;
  previusdefinedtype := 2;
  subrangetype := 3;
end initofntabrecord;
comment table entry types;

comment ***************************************************
                version 1.1   jan.1981.
                lilli andersen
                carsten gyrn.
        ***************************************************
        in this version all texts and charakters
        if considered as charakters is contained in a integer
        and texts is integer array with one charakter stored    

        in every integer item.
        ***************************************************;

comment ***************************************************
                implementation dependent 
                input/output procedures
        *************************************************;

comment  
       procedure sourcechar schould read a charakter from 
                            the file where the pascal
                            source program is stored.▶16◀▶16◀▶16◀
       procedure objectchar schould write a charakter on the file 
                            where the algol object program
                            is wanted.   
                            
       procedure listchar   schould write a char on the file where 
                            the program listning, and error messages
                            is wanted.

       all these procedure schold accept or return charater 
       values, as integers in the iso alphabet
       ( close to asscii), the alphabet and conversion
       is given below.

       ( iso alphabet table );
procedure sourcechar(char);
integer char;
begin
readchar(in,char);
end sourcechar;

procedure objectchar(char);
value char; integer char;
begin
comment implementation dependent code,
        algol 8 version;
outchar(objectfile,char);
end objectchar;

procedure listchar(char);
value char; integer char;
begin
comment implementaion dependant code,
        algol 8 version;

outchar(out,char);
end listchar;
comment decleration of file in the algol 8 version;

zone objectfile(128,1,stderror);

procedure openfiles;
begin
comment make all files ready to charakter input output.
        in the algol8 version the files for input source char
        and output of list char allready is openened and
        ready, becayse the standard input and output files
        is used.
        the file to the object file is declared just prior 
        to this procedure.
open(objectfile) as bs storage:(4) name:(<:objectfile:>) error mask :(0);
end openfiles;

procedure closefiles;
begin
comment terminates all ues of files.
        see comment to procedure obenfiles;
close(objectfile,true);
end closefiles;


comment ******************************************************
                     implemantion dependant 
                     conversion procedures
        ******************************************************;

boolean procedure convertstring(textarray,textstring);
integer array textarray; string textstring;
begin
comment this procedure schould convert a string given as parameter
        to an integer array, where the charakters is 
        packed left justified in a prober way ( see comment version ).
        the items in the textarray not used for the conversion is
        zero filled (null charakter).
        the procedure returns true if the conversion is ok,
        false otherwise;

comment code for convertstring in algol 8,
        where move string converts a string to
        a real array where the charakters is packed 
        as 6 charakters in every word, and
        a charakter occupie 8 bits;

real array workarray(1:stdlinelength);
integer i;
movestring(workarray,1,textstring);
for i:=1,i+1 while textarray(i-1) <> 0 do
  textarray(i) := workarray((i-1)//6+1) shift (-(48 -((i-1) mod 6+1)*8))
                  extract 8;
end convertstring;


comment *******************************************************
                  input output procedures
        *******************************************************;
boolean procedure readsourceline;      
begin
comment the procedure reads a string of a charakters
        using the procedure sourcechar, until either
         a new line, a form feed, a carrige return or a
        end medium charakter is met or the array line
        if filled up. the array line is assumed to be of standard
        line length;
integer i;
if -, endoffile then
  begin
  for i:=1,i+1 while class(sourceline(i-1)) < endoflineclass and
                     i < stdlinelength do
    sourcechar(sourceline(i));
  endofline := false;
  sourceline(i) := nullchar;
  sourcelinecounter := sourcelinecounter +1;
  gpointer := 1;
  if listsource then
    listsourceline;
  readsourceline := if class(sourceline(i-1)) < endoflineclass then
                    true else false;
  if sourceline(i-1) = emchar then endoffile := true;
  end;
end readsourceline;

procedure writeobjectline(text);
integer array text;
begin
comment write a std. text un the ogject file
        using the output procedure object char;
integer index;
for index := 1,index+1 while index <= stdlinelength 
                       and text(index-1) <> nullchar do
  begin
  objectchar(text(index));
  end;
end writeobjectline;


procedure listline(line);
integer array line;
begin
comment output a line given in the integer parameter line
        on the list file.
        the procedure stop output symbol from the line
        when a nlchareter , a formfeed, a carrige return or
        a end medium charakter is met or when the
        last charakter in the array line is met;
integer i;
for i:=1,i+1 while class(line(i-1)) < endoflineclass and
                   line(i) <> nullchar and
                   i <= stdlinelength do
  listchar(line(i));
end listline;

procedure listsourceline;            
begin
comment prints the source code with line numbers;
integer index;
integer array numbertext,
              formatnumber(1:12);
converttextinteger(numbertext,sourcelinecounter);
formatrigthtext(formatnumber,7,numbertext,1);
concattext(printline,formatnumber,sourceline);
insertnlchar(printline);
listline(printline);
end listsourceline;

comment error and recovery procedures;
 

procedure error(errorstring);
string errorstring;
begin
comment errortext will be printed out on the list fie
        if list a pointer 
        if source text is to be listed then a pointer
        is printed out before the error text line
        at positioning at current g pointer.
        line number is printed out before 
        the error line text;
integer array numbertext,
              formatnumber(1:12),
              errortext(1:stdlinelength);
integer index;
if listsource then
  begin
  for index := 1 step 1 until gpointer+7-1 do
    printline(index) := blankchar;
  printline(gpointer) := snabelachar;
  printline(gpointer+1) := nullchar;
  insertnlchar(printline);
  listline(printline);
  resettext(printline);
  end
 else
  begin
  converttextinteger(numbertext,sourcelinecounter);
  formatrigthtext(formatnumber,7,numbertext,1);
  movetext(printline,formatnumber);
  converttextinteger(numbertext,gpointer);
  formatrigthtext(formatnumber,7,numbertext,1);
  appendtext(printline,formatnumber);
  end;
convertstring(errortext,errorstring);
appendtext(printline,errortext);
insertnlchar(printline);
listline(printline);
end error;

comment recovery  conditions;
integer skipsemicolon,
        skipbegin,
        skipbeginsemicolon,
        skipreservedwordsemicolon,
        skipreservedword;

procedure initofrecoverconditions;
begin
skipsemicolon := 1;
comment skip until reserved word symbol begin or
        past semicolon;
skipbeginsemicolon := 2;
comment skip until begin;
skipbegin := 3;
comment skip  until reserved word symbol or
        past semicolon;
skipreservedwordsemicolon := 4;
comment skip until next reserved word;
skipreservedword := 5;
end initofreceverconditions;


procedure recover(condition);
value condition; integer condition;
begin
comment this procedure tryes to firn 
        the start of the next sentence, and set gpointer to
        start there;
end recover;            

comment variables used in connection with input and output 
        procedures;
boolean endofline,
        endoffile,
        listsource;
comment input and output buffers;
integer array sourceline,
              objectline,
              printline(1:stdlinelength);
integer sourcelinecounter,
        objectlinecounter;


procedure initinputoutputvariables;
begin
endofline := true;
endoffile := false;
comment allways listning;
listsource := true;
sourcelinecounter := 0;
objectlinecounter := 0;
end initinputoutputvariables;

comment objectcode printing procedures;

procedure outcodenl;
begin
comment creates a newline char on the object line
        and write it out on the objectfile;
objectlinecounter := objectlinecounter +1;
insertnlchar(objectline);
writeobjectline(objectline);
end outcodenl;

procedure outcodechar(char);
value char; integer char;
begin
comment append the char to last of the objectline;
if appendchar(objectline,char) then
  begin
  outcodenl;
  resettext(objectline);
  objectline(1) := char;
  end;
end objectchar;

procedure outcodetext(text);
integer array text;
begin
comment add the text to
     the object line. if the result of
     the adding is greateher than std line then
     the object line i writen out and
     text is firt of new object line;
if -, appendtext(objectline,text) then
  begin
  outcodenl;
  movetext(objectline,text);
  end;
end outcodetext;

procedure outcodestring(textstring);
string textstring;
begin
comment adds the textstring to the objectline.
        if the result of the adding is greather
        than stdlinelength then objectline
        is written out on objectfile and
        textstring is made first of a new
        objectline;
integer array text(1:stdlinelength);
convertstring(text,textstring);
if -, appendtext(objectline,text) then
  begin
  outcodenl;
  movetext(objectline,text);
  end;
end outcodestring;


                          

comment variable used in connection with the procedure 
        next,next0,next1,next2 which get next symbol from 
        the source file;
comment text,text0,text1,text2 contains the text of the identifier;
integer array text,text0,text1,text2(1:stdlinelength);

comment entry,entry0,entry1,entry2 contain 
        an index of the identifier;
integer entry,entry0,entry1,entry2;

comment symbol,symbol0,symbol1,symbol2 contaion the symbol class of the
        the next symbol;
integer symbol,symbol0,symbol1,symbol2;

comment aux,aux0,aux1,aux2 contaions varius values;
integer aux,aux0,aux1,aux2;
comment the procedures next,next0,next1,next2 call 
        getnextsymbol with different parameters;

integer procedure next;
begin
next := symbol := getnextsymbol(text,entry,aux);
end next;

integer procedure next0;
begin
next0 := symbol0 := getnextsymbol(text0,entry0,aux0);
end next0;

integer procedure next1;
begin
next1 := symbol1 := getnextsymbol(text1,entry1,aux1);
end next1;

integer procedure next2;
begin
next2 := symbol2 := getnextsymbol(text2,entry2,aux2);
end next2;
comment table for class values associated to each
        char;
integer array charclass(0:127);


integer procedure class(char);
value char; integer char;
comment returns a class value associated to a given char.
        in this version the class values is taken from the 
        table charclass;
begin
class := charclass(char);
end class;

integer procedure thisclass;
begin
comment delivers the class of the current spointer from
        the char in source line, only made to 
        speed things up a bit;
thisclass := charclass(sourceline(spointer));
end thisclass;

comment variables used as symbol classes;
integer illegalclass,
        letterclass,
        digetclass,
        exponentchar,
        rigthbraketchar,
        leftbraketchar,
        investchar,
        nextchar;
comment charakter constants;
integer nullchar,
        nlchar,
        emchar,
        ffchar,
        crchar,
        blankchar,
        minuschar,
        starchar,
        zerodigetchar,
        equalchar,
        greatherchar,
        lesschar,
        periodchar,
        colonchar,
        doublequotechar,
        snabelachar,
        firstsingleclass,
        lastsingleclass,
        firstdoubleclass,
        lastdoubleclass,
        firstseperatorclass,
        endoffileclass,
        endoflineclass;
comment variables used as constant delivered as results
        from getnextsymbol, directive symbol and doublequotesymbol
        is not defined in the sequential pascal rapport
        page 5.;

integer unknownsymbol,
        namesymbol,
        numbersymbol,
        greathersymbol,
        greatherequalsymbol,
        lesssymbol,
        lessequalsymbol,
        notequalsymbol,
        periodsymbol,
        rangeseperatorsymbol,
        rigtharraybraketsymbol,
        leftarraybraketsymbol,
        leftbraketsymbol,
        rigthbraketsymbol,
        assignmentsymbol,
        plussymbol,
        minussymbol,
        timessymbol,
        slashsymbol,
        pointersymbol,
        ambersandsymbol,
        equalsymbol,
        snabelasymbol,
        commasymbol,
        semicolonsymbol,
        colonsymbol,
        singlequotesymbol,
        doublequotesymbol,
        directivelsymbol;

comment variables used inconnection with get next symbol.
        gpointer points to next char in sourceline,
        rpointer points to start of previus symbol
                 used for error recovery,
        spointer used for scanning in sourceline
                 is undefined after call of next;

integer gpointer,
        spointer,
        rpointer,
        symbclass;


integer procedure getnextsymbol(text,index,aux);
integer array text; integer index,aux;
begin
if skipseperatorsymbol then
  begin
  comment init recovery pointer
          and scan pointer;
  rpointer := gpointer;
  spointer := gpointer;
  if symbclass = letterclass then
    getnextsymbol := getnextname(text,index,aux)
   else
  if symbclass = digetclass then
    getnextsymbol := getnextnumber(text,index,aux)
   else
  if symbclass >= firstsingleclass and
     symbclass <= lastsingleclass then
    getnextsymbol := getnextsinglecharsymbol(text,index,aux)
   else
    getnextsymbol := getnextdoublecharsymbol(text,index,aux);
  end
 else
  begin
  getnextsymbol := endoffileclass;
  end;
end getnextsymbol;

integer procedure getnextname(text,index,aux);
integer array text; integer index,aux;
begin
  comment letter found.
          collect text, and look up;
integer spointer;
for spointer := gpointer, spointer + 1 
  while symbclass = letterclass or
  symbclass = digetclass do
    begin
    text(spointer+1-gpointer) := sourceline(spointer);
    symbclass := class(sourceline(spointer+1));
    end;
comment set end text charakter in text;
text(spointer+1-gpointer) := nullchar;
gpointer := spointer;
comment look up text in texttable;
if lookuptext(text,index) then
  begin
  comment find name type in ntab
          and return result;
  if ntab(index+entrytype) = reservedword then
    begin
    comment because the reserved word is one of
            the most common symbols it is given a
            spcial symbol. also instead of returning
            the type in the var aux the nameid is returned,
            ( i.e. is it a begin or a while ect.).
            ;
    getnextname := reservedword;
    aux := ntab(index+entrytypeid);
    end
   else
    begin
    getnextname := namesymbol;
    aux := ntab(index+entrytype);
    end;
  end
 else
  getnextname := unknownnamesymbol; 
end getnextname;

integer procedure getnextnumber(text,index,aux);
integer array text; integer index,aux;
begin
comment number found.
read number and store as text.
aux gives as result integer or real;
aux := integertype;
for spointer:=gpointer,                 
   spointer+1 while thisclass = digetclass do
  begin
  text(spointer+1-gpointer) := sourceline(spointer);
  end;
if class(spointer) = periodsymbol then
  begin
  aux := realtype;
  comment decimalpart found;
  text(spointer+1-gpointer) := sourceline(spointer);
  for spointer:=spointer+1 while 
    thisclass=digetclass do
    begin
    text(spointer+1-gpointer) := sourceline(spointer);
    end;
    if sourceline(spointer) = exponentchar then
      begin
      comment exponent part found;
      text(spointer+1-gpointer) := sourceline(spointer);
    for spointer := spointer+1 while
      thisclass = digetclass do
       begin
       text(spointer+1-gpointer) := sourceline(spointer);
        end;
      end exponent part;
    end decimalpart;
comment set end text charakter;
text(spointer+1-gpointer) := 0; 
gpointer := spointer;
getnextnumber := numbersymbol;
end getnextnumber;

integer procedure getnextsinglecharsymbol(text,index,aux);
integer array text; integer index,aux;
begin
comment single charakter symbol is met,
        the class of the symbol is used as result,
        aux is set to the charakter value,
        text and index is unassigned;
aux := sourceline(gpointer);
getnextsinglecharsymbol := symbclass;
gpointer := gpointer+1;
end  getnextsinglesymbol;

integer procedure getnextdoublecharsymbol(text,index,aux);
integer array text; integer index,aux;
begin
investchar := sourceline(gpointer);
nextchar   := sourceline(gpointer+1);
if investchar = colonchar and nextchar = equalchar then
  begin
  getnextdoublecharsymbol:= assignmentsymbol;
  gpointer := gpointer + 2;
  end
 else
if investchar = leftbraketchar and nextchar = periodchar then
  begin
  getnextdoublecharsymbol:= leftarraybraketsymbol;
  gpointer := gpointer + 2;
  end
 else
if investchar = periodchar then
  begin
 if nextchar = rigthbraketchar then
    begin
    getnextdoublecharsymbol:= rigtharraybraketsymbol;
    gpointer := gpointer + 2;
    end
   else
  if nextchar = periodchar then
    begin
    getnextdoublecharsymbol:= rangeseperatorsymbol;
    gpointer := gpointer + 2;
    end
   else
    begin
    getnextdoublecharsymbol:= periodsymbol;
    gpointer := gpointer +1;
    end;
  end
 else
if investchar = lesschar then
  begin
  if nextchar = greatherchar then
    begin
    getnextdoublecharsymbol:= notequalsymbol;
    gpointer := gpointer +2;
    end
   else
  if nextchar = equalchar then
    begin
    getnextdoublecharsymbol:= lessequalsymbol;
    gpointer := gpointer+2;
    end
   else
    begin
    getnextdoublecharsymbol:= lesssymbol;
    gpointer := gpointer +1;
    end;
  end
 else
if investchar = greatherchar then
  begin
  if nextchar = equalchar then
    begin
    getnextdoublecharsymbol:= greatherequalsymbol;
    gpointer := gpointer +2;
    end
   else
    begin
    getnextdoublecharsymbol:= greathersymbol;
    gpointer := gpointer +1;
    end;
  end
  else
  begin
  getnextdoublecharsymbol := unknownsymbol;
  gpointer := gpointer +1;
  end;
aux := investchar;
index := nextchar;
end  getnextdoublesymbol;


boolean procedure skipseperatorsymbol;
begin
comment this procedure skips all seperator symbols
        i.e blank, newline, carriege return and form feed
        charakters and comments.
        the skipping starts with the charakter pointerd out
        by gpointer, at return gpointer points to
        the first charakter not part of a seperator and 
        symbclass contains the class of the first char 
        not part of a seperator.
        the result of skipseperator is false if
        endoffile is met otherwise true;
if -, endoffile then
  begin
  if endofline then readsourceline;

  for symbclass := class(sourceline(gpointer))
      while symbclass >= firstseperatorclass and
            -, endoffile do
    begin
    if symbclass = endoflineclass then
      readsourceline
     else
    if symbclass = doublequotesymbol then
      skipcomment          
     else
      gpointer := gpointer +1;
    end;
  end;
skipseperatorsymbol := if endoffile then false else true;
end skipblank;

procedure skipcomment;
begin
comment skips from a begining of a comment
        until and past its end.
        gpointer points on the first duoblequote
        at entry. ;
for gpointer := gpointer +1
      while sourceline(gpointer) <> doublequotechar and
            -, endoffile do
    begin
    if class(sourceline(gpointer)) = endoflineclass then
      begin
      readsourceline;
      gpointer := 0;
      end;
    end;
end skipcomment;

procedure initofsearchtable;
begin
comment initialize every entry in the searchtable
        with the initial value nil;
integer index;
for index := 0 step 1 until searchtablelength do
  searchtable(index) := nil;
end initofsearchtable;


boolean procedure insertname(tabindex,name,recordtype,recordidno);       
value recordtype,recordidno;       
integer tabindex,recordtype,recordidno;       
integer array name;
begin
integer nameindex,recordindex;
comment insert name in identifier table.
        if the name is allready in the idnametable then
        it is not inserted but the same name in the 
        idnametable is used. if the same name exists in the
        idname table then it must be on same or a lower 
        niveau;
lookupname(name,nameindex);
nameindex := allocate(length0(name));
movename4(ntab,nameindex,name);
comment record information insert in ntable;
recordindex := allocate(basicentrylength);
ntab(recordindex+entrylength) := basicentrylength;
ntab(recordindex+entrynext) := searchtable(tabindex);
searchtable(tabindex) := recordindex;
ntab(recordindex+entryrecordtype) := recordtype;
ntab(recordindex+entryrecordtypeid) := recordidno;
ntab(recordindex+entrynamelength) := length0(name);
tabindex := recordindex;
end insertname;

boolean procedure lookuptext(text,textindex);
integer array text; integer textindex;
begin
comment lookup a text in the ntab indexed through the
        search table.
        the result is true if the text is found othervise false.
        if the text is found then the textindex points to the symbol 
        in the ntab.
        if the text is not found then textindex is the               
        index in the search table;
integer hashkey,searchkey,textlength;
boolean textfound;
textfound := false;
textlength := length0(text);
hashkey := calculatehashkey(text);
searchkey := searchtable(hashkey);
textindex := hashkey;
for dummy := dummy while
  -, textfound and searchkey <> nil do
  begin
  if textlength = ntab(searchkey+entrynamelength) then
    begin
    if comparetext(text,1,ntab,
         ntab(searchkey-ntab(searchkey+entrynamelength))) then
     begin
     textindex := searchkey;
     textfound := true;
     end
   end;
  searchkey := ntab(searchkey+entrynext);
  end;
lookuptext := textfound;
end lookuptext;

integer procedure calculatehashkey(text);
integer array text;
begin
comment calculates a search key to be used 
        for searching in the symbolable.
        the key is calculated using all charakters
        in the text.
        if no text is aplied to the procedure 
        the hash key as result i zero.;
integer hashkey,index;
hashkey := 0;
index := 0;
for index := index+1 while text(index) <> 0 do
  hashkey := hashkey + index*text(index);
calculatehashkey := hashkey mod searchtablelength
                    + ( if hashkey <> 0 then 1 else 0);
end calculatehashkey;
procedure resettext(text);
integer array text;
begin
comment insert a null char in the frirst position
        in the text, and by doing so making it a standard
        left justified empty text;
text(1) := nullchar;
end resettext;

boolean procedure comparetext(text1,pointer1,text2,pointer2);
integer array text1,text2;
integer pointer1,pointer2;
begin
comment compares a text in array text1 with a text in array text2.
        the texts starts in the arrays at pointer1 or pointer2
        respectively.
        result true if the texts are equal othervise false.
        it is asumed the the texts ends correct whit a zero
        charakter;

integer index;
boolean finiscompare;
finiscompare := false;
comparetext := true;

for index := 0, index+1 while -,finiscompare do
  begin
  if text1(pointer1+index) <> text2(pointer2+index) then
    begin
    comparetext := false;
    finiscompare := true;
    end;
  if text1(pointer1+index) = 0 then finiscompare := true;
  end;
end comparetext;

boolean procedure concattext(resulttext,text1,text2);
integer array resulttext,text1,text2;
begin
comment concatenate 2 left justified texts text1 and text2
        to result text.
        ;
integer indexfrom,indexto;

indexto := 1;
indexfrom:= 0;
for indexfrom := indexfrom+1 while text1(indexfrom) <> 0 
                                   and indexto < stdlinelength do
  begin
  resulttext(indexto) := text1(indexfrom);
  indexto := indexto + 1;
  end;
indexfrom := 0;
for indexfrom := indexfrom + 1 while text2(indexfrom) <> 0 
                               and indexto < stdlinelength do
  begin
  resulttext(indexto) := text2(indexfrom);
  indexto := indexto + 1;
  end;
concattext := if indexto > 131 then false else true;
resulttext(indexto) := 0;
end concattext;

boolean procedure appendtext(text1,text2);
integer array text1,text2;
begin
comment adds text2 into text1 after the zero ending char
        in text1.
        if the result of the appending is longer than
        stdlinelength then text1 is left unchanged.
        the result of append is true if the appending
        is performed othervise false;
integer text1length,index2;
for text1length := 0,
    text1length+1 while text1(text1length) <> nullchar
    and text1length <= stdlinelength do;
for index2:=0,index2+1 while text1length+index2 < stdlinelength
    and text2(index2) <> nullchar do
  text1(text1length+index2) := text2(index2+1);
if index2+text1length <= stdlinelength then
  appendtext := true
 else
  begin
  appendtext := false;
  text1(text1length) := nullchar;
  end;
end appendtext;

boolean procedure appendchar(text,char);
value char; integer char;
integer array text;
begin
comment appends the char to the last of the text;
integer index;
for index:=1,index+1 while index<=stdlinelength
                     and text(index-1) <> nullchar do;
if index+1 < stdlinelength then
  begin
  appendchar := true;
  text(index-1) := char;
  text(index) := nullchar;
  end
 else
  appendchar := true;
end appendchar;



boolean procedure movetext(resulttext,sourcetext);
integer array resulttext,sourcetext;
begin
comment moves the contents of sourcetext to result text.
        both text is left justified.
        the result schold obius allways be true, but
        if source text not end with a zero charakter then
        the result is false;
integer index;
for index := 1,index+1 while index < stdlinelength do
  resulttext(index) := sourcetext(index);
movetext := if index < stdlinelength then true else false;
end movetext;


boolean procedure movetext1(resulttext,text1,indexlow,indexhigh);
value indexlow,indexhigh; integer indexlow,indexhigh;
integer array resulttext,text1;
begin
comment moves a text from array text1 indexed 
        from indexlow to index high to the array
        resulttext left justified.
        if a zero charakter in text1 is met before
        index high then the procedure is terminated.
        the result of the procedure is false if more
        than stdlinelength charakters is tryed to be moved
        othervise true;
integer indexto;
indexto := 0;
for indexto:=indexto+1 while indexto < stdlinelength 
                             and indexlow <= indexhigh do
  begin
  resulttext(indexto) := text1(indexlow);
  if resulttext(indexto) = 0 then 
    indexlow := indexhigh + 1
   else
    indexlow := indexlow + 1;
  end;
movetext1 := if indexto < stdlinelength then true else false;
end movetext1;

boolean procedure movetext2(resulttext,indexhigh,indexlow,sourcetext);
integer array resulttext,sourcetext; integer indexhigh,indexlow;
begin
comment
       moves the left justifieded sourcetext ending on a zero 
       charakter to resulttext starting at index indexlow.
       indexhigh is the last position in resulttext where
       sourcetext is mowed to.
       the zero ending charakter ending sourcetext is not 
       mowed.
       the result of the procedure is true if the move was 
       succesfull otherwise false (i.e. result text was
       mot long enogh to take the whole of sourcetext);
integer index;
index:=0;
for index:=index+1 while sourcetext(index) <> 0 and
                         indexlow+index < stdlinelength do
  begin
  resulttext(indexlow+index-1) := sourcetext(index);
  end;
movetext2 := if indexlow+index < stdlinelength then true else false;
end movetext2;


boolean procedure movetext3(resulttext,indexrlow,indexrhigh,
                            sourcetext,indexslow,indexshigh);
value indexrlow,indexslow,indexshigh;
integer array resulttext,sourcetext;
integer indexrlow,indexrhigh,indexslow,indexshigh;
begin
comment move sourcetext from lindexslow to indexshigh
        to resulttext from indexrlow to indexrhigh.
        indexrhigh is a result parameter.
        the result of the procedure is true
        if the move was successfully otherwise false;
integer index;
index :=-1;
for index := index+1 while indexslow+index <= indexrhigh and
                           indexslow+index < stdlinelength  and
                           indexrlow+index < stdlinelength do
 begin
 resulttext(indexrlow+index) := sourcetext(indexslow+index);
 end;
movetext3 := if indexrlow+index >= stdlinelength then false
               else
              if indexslow+index >= stdlinelength then false 
               else true;
end movetext3;
boolean procedure movetext4(resulttext,indexlow,sourcetext);
value indexlow; integer indexlow;
integer array resulttext,sourcetext;
begin
comment moves a left justified text from source text to
        result text starting at positon indexlow in resulttext;
integer index;
for index:=1,index+1 while sourcetext(index-1) <> 0 do
  begin
  resulttext(indexlow-1+index) := sourcetext(index);
  end;
movetext4 := if sourcetext(index) <> 0 then false else true;
end movetext4;

boolean procedure movetext5(tabtext,tabindex,text);
value tabindex;

integer array tabtext,text;
integer tabindex;
begin
comment moves a left justified text from
        text to a 2 dimentional  array tabtext
        where the first index is tabindex and the 
        the second index is the text;
integer charindex;
charindex := 0;
for charindex:=charindex+1 while text(charindex) <> 0 and
                                 charindex < stdlinelength do
   begin
   tabtext(tabindex,charindex) := text(charindex);
   end;
tabtext(tabindex,charindex) := 0;
movetext5 := if text(charindex) <> 0 then false else true;
end movetext5;


boolean procedure movetext6(text,tabtext,tabindex);
value tabindex;
integer array text,tabtext;
integer tabindex;
begin
comment movex a left justified text in the table
        texttable indexed with the tabindex to the 
        text;
integer charindex;
charindex := 0;
for charindex := charindex +1 while charindex < stdlinelength and
                                     tabtext(tabindex,charindex) <> 0 do
  begin
  text(charindex) := tabtext(tabindex,charindex);
  end;
text(charindex) := 0;
movetext6 := if tabtext(tabindex,charindex) = 0 then true else false;
end movetext6;

procedure converttextinteger(text,number);
value number; integer number; integer array text;
begin
comment converts an integer number to a text with 
        std format left justified;
integer index,turnindex,help;
if number < 0 then
  begin
  text(index):=minuschar;
  turnindex := 2;
  index:=2;
  number := -1* number;
  end
 else
  begin
  index := 1;
  turnindex := 1;
  end;
for index := index ,index+1 while number > 0 do
  begin
  text(index) := ( number mod 10) + zerodigetchar;
  number := number // 10;
  end;
text(index) := 0;
comment turn number;
for index := index -1 while index <> turnindex do
  begin
  help := text(index);
  text(index) := text(turnindex);
  turnindex := turnindex+1;
  end;
end converttextinteger;

boolean procedure convertintegertext(result,text);
integer result; integer array text;
begin
comment converts a left justified text  which contains
        diget charakters into a integer.
        result is zero if no diget charakters is met,
        the conversion stops when the first non diget charakter 
        is met,
        convertintegertext is false if no diget is met 
        otherwise false;
integer index,number;
number := 0;
index := 0;
for index := index+1 while class(text(index)) = digetclass do
  begin
  number := number*10 + text(index)-zerodigetchar;
  end;
convertintegertext := if index > 1 then true else false;
result := number;
end convertintegertext;


procedure formattext(resulttext,resultlength,position,sourcetext);
value position,resultlength; integer resultlength,position;
integer array resulttext,sourcetext;
begin
comment formats sourcetext into resulttext so
        it will be resultlength charakters long and 
        start in position. not used position veill
        be filled with blanks;
integer index;

for index := 1 step 1 until position-1 do
  resulttext(index) := blankchar;
for index := index+1 while sourcetext(index) <> 0 
                     and index <= resultlength do
  resulttext(index) := sourcetext(index+1-position);
for index := index step 1 until resultlength do
  resulttext(index) := blankchar;
end formattext;

procedure formatrigthtext(resulttext,resultlength,sourcetext,endspace);
value resultlength,endspace; integer resultlength,endspace;
integer array resulttext,sourcetext;
begin
comment positions sourcetext rigth in 
        resulttext which is resulttext ling so 
        after sourcetext their is endpace blankchars.
        if source text can not be in resulttext plus endspace
        then sourcetext is filed up with starchar;
integer index,leadingblanks;
if length(sourcetext) + endspace > resultlength then
  begin
  for index := 1 step 1 until resultlength do
    resulttext(index) := starchar;
  resulttext(index+1) := nullchar;
  end
 else
  begin
  leadingblanks := resultlength -(endspace+length(sourcetext));
  for index := 1 step 1 until leadingblanks do
    resulttext(index) := blankchar;
  index := 0;
  for index := index +1 while sourcetext(index) <> 0 and
                               index < stdlinelength do
    resulttext(index+leadingblanks) := sourcetext(index);
  for index := 1 step 1 until endspace do
    resulttext(resultlength+1-1) := blankchar;
  resulttext(resultlength+1) := nullchar;
  end;
end formatrigthtext;


integer procedure length0(text);
integer array text;
begin
comment calcualtes the length of text
        which is left justified and ending on
        zero charakter.
        if the last char is not a zero char then 
        zero char is inserted.
        if length is negative then text was
        not ending on a zero charakter.
        the zero char is included in the length
        calculation;
integer index;
for index :=0, index+1 while index < stdlinelength and
                           text(index) <> 0 do;
length0 := if text(index) = 0 then index else -index;
if index= stdlinelength then text(index) := 0;
end length0;

integer procedure length(text);
integer array text;
begin
comment catculates the length of a left justified std format 
        text. if the last char is not a null char then 
        a nnull char is inserted an the length is given 
        as negative. the zero char is not included in the
        length calculation, see proccedure length0;
integer index;
for index := 0 , index +1 while index<= stdlinelength and
        text(index) <> 0 do;
length := if text(index) = 0 then index-1 else -index-1;
if index=stdlinelength then text(index) := 0;
end length;

boolean procedure insertnlchar(line);
integer array line;
begin
comment inserts a nl char if 
        before the zero char ending the text line
        if no nl char is present before.
        if the line fills the whole array the
        nl char is inserted instead of
        the zero char.
        if the zero char is substitueted then
        insertnlchar is false else true;
integer index;
for index :=1,index+1 while index <= stdlinelength and
                              line(index-1) <> nlchar do
  begin
  if line(index) = 0 then
    begin
    line(index) := nlchar;
    if index+1 <= stdlinelength then line(index+1) := nullchar;
    end;
   end;
insertnlchar := if index > stdlinelength then false else true;
end procedure insertnlchar;


comment reservedword symbols;

comment reservedword symbols constant;
integer resarray,
        resbegin,
        resconst,
        rescase,
        resdiv,
        resdo,
        resdownto,
        reselse,
        resend,
        resfor,
        resforward,
        resfunction,
        resif,
        resin,
        resmod,
        resnot,
        resof,
        resor,
        resprocedure,
        resprogram,
        resrecord,
        resrepeat,
        resset,
        resthen,
        resto,
        restype,
        resuniv,
        resvar,
        reswhile,
        reswith;

procedure initofreservedwordsymbol;
begin
comment initialization of reservedword constants;
resarray := 1; resbegin := 2; resconst := 3;
rescase := 4; resdiv := 5; resdo := 6; 
resdownto := 7; reselse := 8; resend := 9;
resfor := 10; resforward := 11; resfunction := 12;
resif := 13; resin := 14; resmod := 15;
resnot := 16; resof := 17; resor := 18;
resprocedure := 19; resprogram := 20; resrecord := 21;
resrepeat := 22; resset := 23; resthen := 24;
resto := 25; restype := 26; resuniv := 27;
resvar := 28; reswhile := 29; reswith := 30;
end initofreservedwordsymbol;

comment symbolconstants;
integer lastreservedword,
        unknownnamesymbol
        firstidentifier,
        idboolean,
        idchar,
        idinteger,
        idreal,
        idfalse,
        idtrue,
        predefinedidentifier;

procedure initofsymbolconstants;
begin
lastreservedword:=30;

firstidentifier := 32;
comment predeclared identifiers;
comment 4 types is predeclared;
idboolean := 32;
idchar := 33;
idinteger := 34;
idreal := 35;
comment the two resrved enumeration values
        true and false;
idfalse := 36;
idtrue := 37;
end initofsymbolconstants;

procedure initofnametable;
begin
comment this procedure initialize the name table
        with the reservedword symbol and predefined 
        identifiers (ex. false and true);
integer array texttable(1:30,1:12);
integer array text(1:12);
integer index,searchindex;
comment initialize the tet table with the reservedword;
convertstring(text,<:array:>);
movetext5(texttable,1,text);
convertstring(text,<:begin:>);
movetext5(texttable,2,text);
convertstring(text,<:case:>);
movetext5(texttable,3,text);
convertstring(text,<:const:>);
movetext5(texttable,4,text);
convertstring(text,<:div:>);
movetext5(texttable,5,text);
convertstring(text,<:do:>);
movetext5(texttable,6,text);
convertstring(text,<:downto:>);
movetext5(texttable,7,text);
convertstring(text,<:else:>);
movetext5(texttable,8,text);
convertstring(text,<:end:>);
movetext5(texttable,9,text);
convertstring(text,<:for:>);
movetext5(texttable,10,text);
convertstring(text,<:forward:>);
movetext5(texttable,11,text);
convertstring(text,<:function:>);
movetext5(texttable,12,text);
convertstring(text,<:if:>);
movetext5(texttable,13,text);
convertstring(text,<:in:>);
movetext5(texttable,14,text);
convertstring(text,<:mod:>);
movetext5(texttable,15,text);
convertstring(text,<:not:>);
movetext5(texttable,16,text);
convertstring(text,<:of:>);
movetext5(texttable,17,text);
convertstring(text,<:or:>);
movetext5(texttable,18,text);
convertstring(text,<:procedure:>);
movetext5(texttable,19,text);
convertstring(text,<:program:>);
movetext5(texttable,20,text);
convertstring(text,<:record:>);
movetext5(texttable,21,text);
convertstring(text,<:repeat:>);
movetext5(texttable,22,text);
convertstring(text,<:set:>);
movetext5(texttable,23,text);
convertstring(text,<:then:>);
movetext5(texttable,24,text);
convertstring(text,<:to:>);
movetext5(texttable,25,text);
convertstring(text,<:type:>);
movetext5(texttable,26,text);
convertstring(text,<:univ:>);
movetext5(texttable,27,text);
convertstring(text,<:var:>);
movetext5(texttable,28,text);
convertstring(text,<:while:>);
movetext5(texttable,29,text);
convertstring(text,<:with:>);
movetext5(texttable,30,text);
comment insert reservedwords symbols
        in  name table;
for index := 1 step 1 until 30 do
  begin
  movetext6(text,texttable,index);
  lookuptext(text,searchindex);
  insertname(searchindex,text,reservedword,index);
  end;
comment insert predefined identifiers in
        name table;
convertstring(text,<:boolean:>);
movetext5(texttable,1,text);
convertstring(text,<:char:>);
movetext5(texttable,2,text);
convertstring(text,<:integer:>);
movetext5(texttable,3,text);
convertstring(text,<:real:>);
movetext5(texttable,4,text);
convertstring(text,<:false:>);
movetext5(texttable,5,text);
convertstring(text,<:true:>);
movetext5(texttable,6,text);
for index := 1 step 1 until 6 do
  begin
  movetext6(text,texttable,index);
  lookuptext(text,searchindex);
  insertname(searchindex,text,predefinedidentifier,index+31);
  end;
end initofnametable;

procedure initclasscharsymbol;
begin
integer i;
comment init all illegal charakters;
unknownsymbol := 1;
illegalclass := 1;
for i:= 0 step 1 until 127 do
  charclass(i) := 1;
comment charakters which is skipped in input;
charclass(0) := 0;
comment charakter null is internaly
       used for ending texts;
nullchar := 0;
comment diget is class 10;
numbersymbol := 10;
digetclass := 10;
zerodigetchar := 48;
for i:=48 step 1 until 58 do
  charclass(i) := 10;
comment letters is class 12;
comment unknown name is when the identifier is
        not found in the name table;
unknownnamesymbol := 11;
comment name symbol is when the identifier is 
        found in the name table;
namesymbol := 12;
comment reservedword is when the entrytype found
        in the name table is of reservedword type.
        this value is initialised and defined
        in section name table record;
comment initialised to 5, therefor symbol class 5
        is reserved;
reservedword := reservedword;
letterclass := 12;
for i:= 65 step 1 until 90 do
  charclass(i) := 12;
for i:= 97 step 1 until 122 do
  charclass(i) := letterclass;
comment single class;
firstsingleclass := 14;
comment plus char;
plussymbol := 14;
charclass(43) := 14;
comment minus char;
minussymbol := 15;
minuschar := 45;
charclass(45) := 15;
comment times char or star char;
starchar := 42;
timessymbol := 16;
charclass(42) := 16;
comment slash char;
slashsymbol := 17;
charclass(47) := 17;
comment and char;
ambersandsymbol := 18;
charclass(38) := 18;
comment equal char ;
equalsymbol := 19;
charclass(61) := 19;
comment snabela char;
pointersymbol := 20;
snabelasymbol := 20;
snabelachar := 64;
charclass(64) := 20;
comment rigth braket;
rigthbraketsymbol := 21;
charclass(41) := 21;
comment comma char;
commasymbol := 22;
charclass(44) := 22;
comment semicolon char;
semicolonsymbol := 23;
charclass(59) := 23;
comment quote char;
singlequotesymbol := 24;
charclass(60) := 24;
lastsingleclass := 24;
comment class 25 not used;

comment symbols which is migth single if not double;
comment colon class;
charclass(58) := 26;
colonsymbol := 26;
comment period char;
charclass(46) := 27;
periodsymbol := 27;
comment comment less char;
charclass(60) := 28;
lesssymbol := 28;
comment greather char;
charclass(62) := 29;
greathersymbol := 29;
comment init of double charakters symbol;
comment colon char and equal char is assignment;
colonchar := 58; equalchar := 61;
assignmentsymbol := 30;
firstdoubleclass := 30;
comment left braket and period is left array braket;
leftbraketchar := 40; periodchar := 46;
leftarraybraketsymbol := 34;
comment period char and rigth braket is rigth array braket;
rigthbraketchar := 41;
rigtharraybraketsymbol := 36;
comment period char and period char is range symbol;
rangeseperatorsymbol := 38;
comment lesschar end greather char is notequal symbol;
lesschar := 60; greatherchar := 62;
notequalsymbol := 38;
comment lesschar and equal char is lessequalsymbol;
lessequalsymbol := 40;
comment greather char and equal char is greatherequalsymbol;
greatherequalsymbol := 42;
lastdoubleclass := 42;
comment double quote char class;
charclass(34) := 59;
doublequotechar := 34;
doublequotesymbol := 59;
firstseperatorclass := 59;
comment space char class;
charclass(32) := 60;
blankchar := 32;
comment new line , form feed and carrige return is class 20;
endoflineclass := 62;
nlchar := 10;
charclass(10) := 62;
ffchar := 12;
charclass(12) := 62;
crchar := 13;
charclass(13) := 62;
comment end medium class, the higest class number;
endoffileclass := 64;
emchar := 25;
charclass(25) := 64;
end initclasscharsymbol;

comment the table contaion information about the name table
        when a niveau change occur;
integer array niveautable(1:maxniveau,1:2);




boolean procedure newniveau;
begin
comment the value of the first free in the niveau table
        entry in the name table 
        is saved in the niveau table;
if thisniveauno > maxniveau then
  newniveau := false
 else
  begin
  niveautable(thisniveauno,1) := ntabfree;
  thisniveau := ntabfree;
  thisniveauno := thisniveauno+1;
  end;
end newniveau;

boolean procedure removeniveau;        
begin
comment removes all entry in the ntab and
        identifier texts connected to them 
        until next niveau.
        ;
integer searchindex,chain,index;
comment find previus niveau;
if thisniveauno -1 < 1 then
 removeniveau := false
 else
  begin
  thisniveauno := thisniveauno - 1;
  comment free all entreis ntab 
          connected to thisniveauno;
  ntabfree := niveautable(thisniveauno,1);
  thisniveau := niveautable(thisniveau-1,1);
  for index :=1 step 1 until searchtablelength do
    begin
    chain := searchtable(index);
    for chain := chain while chain > ntabfree do
      chain := ntab(chain+entrynext);
    searchtable(index) := chain;
    end;
  end;
end removeniveau;

integer procedure allocate(elements);
value elements; integer elements;
begin
comment allocate elementss in the ntab.
        result is index of first symbol
        ellocated;
allocate := ntabfree;
ntabfree := ntabfree + elements;
if ntabfree > ntablength then 
  fatalerror(<:ntab limit:>);
end allocate;

procedure disallocate(elements);
value elements; integer elements;
begin
comment frees elementss in ntab;
ntabfree := ntabfree - elements;
if ntabfree < 1 then
  fatalerror(<:ntab limit zero:>);
end disallocate;

procedure includestackinentry(entry);
value entry; integer entry;
begin
comment the entry is considered to be the latest 
        inserted in ntab, a possible use of the 
        the rest of ntab as stack is included in the
        ntab record, i.e the ntab records length
        is changed so the record length is j
        from entry to justbefore ntabfree;
ntab(entry) := ntabfree - entry;
end includestackinentry;

procedure disallocatetoentry(entry);
value entry; integer entry;
begin
comment this entry is  considdered the last inserted,
        a possible stack use after this record
        is removed;
ntabfree := entry + ntab(entry+entrylength);
end disallocatetoentry;




procedure changeentrylength(entry,change);
value entry,change; integer entry,change;
begin
comment the latest created entry in name table
        is changed to the new length;
if change > 0 then
  allocate(change);
ntab(entry+entrylength) := ntab(entry+entrylength) + change;
end changeentrylength;


boolean procedure controldeclaration(symbol,entry);
value                                symbol,entry;
integer                              symbol,entry;
comment control of a new identifier can be declared
        as a variable or a type, in the present
        niveau and care taken for parameters
        and record contents.
        ;
begin
if symbol = unknownname or
   ( symbol = namesymbol and entry < thisniveau ) or
   ( symbol = namesymbol and
      ( ntab(entry+entrytype) = recorcelementfixedentry or
        ntab(entry+entrytype) = reccordelementvariantentry))
  then
  controldecleration := true
 else
  controldecleration := false;
end controldeclaration;

comment test procedures and texst facilityis;
boolean array testb(1:20);
integer testall,
        testgetsymb,
        testnametab;

procedure initoftest;
begin
integer index;
for index := 1 step 1 until 20 do
 testb(index) := false;
testall := 1;
testgetsymb := 2;
testnametab := 3;
end initoftest;

boolean procedure test(index);
value index; integer index;
begin
test :=  testb(testall) or testb(index);
end test;

comment error handling procedures;

procedure fatalerror(errorstring);
string errorstring;
begin
comment called after unrecorverable error,
        normaly table length violation.
        the only goto statement in the program;
integer array errorline(1:stdlinelength);
convertstring(errorline,errorstring);
insertnlchar(errorline);
listline(errorline);
goto endprogram;
end fatalerror;

comment varius constants;
integer nil;


procedure initvariusconstants;
begin
comment varius generel constants is initialised in this procedure;
comment nil is the terminal symbol.              
        also used to assign variables indicate
        undifined condition,
        it schould be initialized to the max negative
        integer or another appropriate number.
        in a 24 bit 1 complement machine it is
        -8388607, in 2 complement -8288608;
nil := -8388708;
comment dummy is used for varius purposes and
       can not be expected thave any predefined
       value, specialy used in for sentences;
dummy := 1234567;
end initvariusconstants;

comment varius variables;
integer ntabfree,
        thisniveau,
        thisniveauno,
        dummy;

procedure initvariusvariables;
begin
comment initialise varius variable;

comment free pointer in name table and
        identifier table.
        the first symbol indexed by zero is not used;
ntabfree := 1;
comment the outmost niveau in a pascal program
       contain all predeclared identifiers,
       and is niveau 0, prefix niveau 1,
       program niveau 2, and procedures niveau 3.;
thisniveauno := 0;
comment points to thefirst entry in the name table
     containg entryes under thisniveauno;
thisniveau := ntabfree;
end initvariusvariables;

comment global variables used in connection with
        code generation;
integer whilelabno,
        replabno;

procedure initofcodevariables;
begin
comment initializing of variables used in connection with
        code generation;

comment label numbers used to destinguish labes
        generated from while and repeat statement;
whilelabno := 0;
replabno := 0;
end initofcodevariables;


procedure initofcodeconstants;
begin
comment initialising of constants used in conection with
        with code generation;
end initofcodegeneration;



procedure initgenerel;
begin
comment call of all init procedures.
        the order is critical
        betwen every group;

comment first group;
initvariusconstants;
initclasscharsymbol;
initvariusvariables;
initofntabrecord;
comment second group;
initofsearchtable;
initofsymbolconstants;
comment third group;
initofnametable;
initofreservedwordsymbol;
initofcodeconstants;
comment fourth group;
initofcodevariables;
initoftest;
initinputoutputvariables;
end initgenerel;
procedure scantest;
begin
integer i;
next1;
write(out,<:<10>NEXT:>,<<-dddd>,symbol1,
           <: INDEX::>,entry1,<: AUX::>,aux1,

         <: TEXT1: :>);

i:=0;
for i:= i+1 while i<= stdlinelength and
                  text1(i) <> 0 do
 outchar(out,text1(i));
if text1(i) = 0 then outchar(out,38);
end scantest;




comment transformation procedures;

comment
        the syntax graphs in the comment is in the
        following form.

        symbols is represented with their names or
        special charakters, fx :
        while + ; := <= const

        constructs definied by other graphs is 
        represented as the name of teh construct
        enclosed in lessbraket and equalbraket, fx:
        <identifier> <prefix> <statement>

        arraows is represented with minuschars
        directly folowed by less braket or
        equal braket, fx:
        ---> ---->-----   <---- ----<-----

        for shifting from one arrow line to another
        the charakter exclaration mark (!) is used.
        no direction is suplied.

        for syntaxgraps spreading over more lines
        a number enclosed in greather and lessbraket is used.
        fx :
         -----> <3> 
         <3> ---->---
        ;

procedure program;
begin
comment 
  sequential program is
  -> <prefix> -> <block> -> . ->
  ;
  prefix;
  block;
end program;




procedure prefix;
begin
comment
  prefix is

      --- <const definition> <--
      !                        !
  -------------------------------> <1> 
      !                        !
      --- <type definition>  <--

  <1> --> <prefix routines> --> <programheading> -->

  ;
for dummy := next while symbol = namesymbol and
                         ( aux = resconst or aux = restype ) do
  begin
  if aux = resconst then
    constdefinition
   else
    typedefinition;
  end;
prefixroutines;
programheading;
end prefix;

procedure constdefinition;
begin
comment 
  constant definition is:
  --> const  --> <identifier> --> = -->  <constant>  --> ; -->
              !                                     !
              ---------------------------------------
  where the namesymbol const 
  allready is detected.
  
  ;
integer thisentry;
for dummy := next while symbol <> reservedword do
  begin
  if controldeclaration(symbol,entry) then
    begin
    insertname(entry,text,constantentry,nil);
    if next0 = equalsymbol then
      begin
      constant;
      end
     else
      begin
      error(<:equalsign expected:>,skipreservedword);
      end;
    end
   else
    begin
    if symbol = namesymbol  and ntab(entry+entrytype) <> reservedword then
      begin
      error(<: allready decleared identifier:>,skipreservedword);
      end
     else
      begin
      error(<:identifier expected:>,skipreservedword);
      end;
    end;
  end;
end constdefinition;

procedure constant;
begin
comment <constant> is :
 <constant> is:
  ----> <identifier> ---------------->
    !                              !
    !--> <enumeration constant> -->!
    !                              !
    !--> <real constant> --------->!
    !                              !
    ---> <string constant> ------->!
  ;
integer index;
next0;
if symbol0= numbersymbol then
  begin
  indec := changeentrylength(entry,length0(text0));                
  movetext4(ntab,index,text0);
  comment type of the number is given in aux
          either real or integer type;
  ntab(entry+entrytypeid) := aux;
  end
 else
if symbol0 = stringsymbol then
  begin
  ntab(entry+entrytypeid) := stringtype;
  index := changeentrylength(entry,length0(text0));
  movetext4(ntab,index,text0);
  end
 else
if symbol0 = charsymbol then
  begin
  ntab(entry+entrytypeid) := chartype;
  index := changeentrylength(entry,1);
  ntab(entry+index) := aux0;
  end
 else
if symbol0 = namesymbol and aux0 = constantentry then
  begin
  ntab(entry+entrytypeid) := ntab(entry0+entrytypeid);
  end
 else
  begin
  error(<:illegal constant:>,skipreservedword);
  end;
end constant;



procedure typedefinition;
begin
comment
  type definitions is:
  -->type--><identifier>-->=--><type>--> ; --> 
         !                                  !           
         ------------------------------------           
  where the reserved word type allready is met.
  ;
integer thisentry;
for dummy := next while symbol <> reservedword do
  begin
  if controldeclaration(symbol,entry) then
    begin
    insertname(entry,text,typedecentry,nil);
    if next0 = equalsymbol then
      begin
      comment typedeclaration;
      typedec(entry+typeidentry);
      end
     else
      begin
      error(<:equalsign exepcted:>,skipreservedword);
      end;
    end
   else
    if symbol = namesymbol then
      begin
      error(<:allready declared identifier:>,reservedword);
      end
     else
      begin
      error(<:identifier expected:>,reservedword);
      end;
  end;
end typedefinition;
procedure typedec;             
begin
comment typedec is named type in the syntax graphs.
  typedec is :

  ----><identifier>--------------->--
    !--><enumeration type>-->--!
    !--><real type>--------->--!
    !--><array type>-------->--!
    !--><record type>------->--!
    !--><set type>---------->--!
    !--><pointer type>------>--!
  

  ;
next0;
if symbol0 = reservedwordsymbol then
  begin
  if aux0 = resarray then
    begin
    arraytype;             
    end
   else
  if aux0 = resrecord then
    begin
    recordtype;
    ntab(entry+entrytypeid) := recorddecentry;
    end
   else
  if aux0 = resset then
    begin
    settype;
    ntab(entry+entrytypeid) := setdecentry;
    end
   else
    begin
    error(<:illegal reserved word:>,skipsemicolon);
    end;
  end
 else
if symbol0 = pointersymbol then
  begin
  pointertype;
  end
 else
if symbol0 = namesymbol then 
  begin
    if entry = typedecentry then
      begin
      comment previus defined entry;
      index := allocate(2);
      ntab(index) := previusdefinedtype;
      ntab(index+1) := entry;
      end
     else
      begin
      error(<:XXXXXX:>,skipsemicolon);
      end;
  end
 else
if symbol0= namesymbol and aux0 = enumerationconstantentry then
  begin
  comment a subrangerefference type;
  index := allocate(3);
  ntab(index) := reffferencesubrance;
  comment insert low range refferange;
  ntab(index+1) := entry0;
  if next <> subrangesymbol then
    begin
    error(<:subrangesymbol expected:>,semicolonsymbol);
    end
   else
    begin
    next0;
    if sumbol0 <> namesymbol and aux0 = enumerationconstant then
      begin
      ntab(index+2) := entry0;
      comment control types;
      if ntab(ntab(index+1)+6) <> ntab(ntab(index+2)+6) then
        begin
        error(<:incompatibel subrange types:>,skipsemicolon);
        end
       else
        begin
        comment controlmin max value;
        movetext5(text,ntab,ntab(index+1)+7);
        convertintegertext(lowrange,text);
        movetext5(text,ntab,ntab(index+2)+7);
        convertintegertext(highrange,text);
        if lowrange > highrange then
          begin
          error(<:subrange value error:>,skipsemicolon);
          end;
        end;
      end;
  end
 else
if symbol0 = numbersymbol then
  begin
  comment a subrange integer type;
  index :=allocate(3);
  ntab(index) := subrangenumbertype;
  convertintegertext(lowrange,text0);
  ntab(index+1) := lowrange;
  if next0 <> subrangesymbol then
    begin
    error(<:subrange expected:>,semicolonsymbol);
    end
   else
    begin
    next0;
    if symbol0 <> numbersymbol then
      begin
      error(<:subrange type error:>,semicolonsymbol);
      end
     else
      begin
      convertintegertext(highrange,text0);
      ntab(index+1) := highrange;
      comment control min max value;
      if lowrange > highrange then
        begin
        error(<:subrange value error:>,skipsemicolon);
        end;
      end;
    end;
  end
 else
if symbol0=leftbraketsymbol then
  begin
  comment non standard enumeration type.
          var or type dec. set to next dec type.
         ;
  comment call scan identifier list,
          including rigth braket;
  identifierlist;
  end
 else
  begin
  error(<: type declaration expected:>,skipsemicolon);
  end;
end typedec;

procedure arraytype;
begin
integer index;
index := allocate(1);
ntab(index) := arraytypedecblock;
next0;
if symbol0 <> leftarraybrakket then
  begin
  error(<:left array braket expected:>,semicolonsymbol);
  end
 else
  begin
  arraydimensions;
  typedec;
  end;
end arraytype;


procedure identifierlist;
begin
comment
  identifierlist is:
  -->(--><identifier>-->)-->
      !            !
      ---<--,<-----
  and is transformed to:
    enumeration type and a subrange record
    is placed into the stack.
  all identifiers is inserted inthe name table
  as constants and typeid as next declared type.
  their value is value of nextvalue, which is inserted
  as normal for constants.
  ;
integer nextconstvalue;
integer index;
nextconstvalue := 0;
index := allocate(3);
ntab(index) := enumerationdeclaration;
previus := index+1;
for dummy := next1 while symbol = unknownnamesymbol do
  begin
  comment as type is inserted refference to next,
          which is either the variable or typedecleration;
  if controldecleration(symbol,entry) then
  insert(text1,entry1,enumerationstantentry,nil);
  ntab(previuslink) := entry1;
  previuslink := entry1 +5;
  comment insert entry to enumeration declaration;
  ntab(allocate(1)) := index;                  
  nextconstvalue := nextconstvalue+1;
  converttextinteger(constanttext,nextconstantvalue);
  index := allocate(length0(constanttext));
  movetext4(ntab,index,constanttext);
  includestackinentry(entry1);
  end;
ntab(index+2) := nextconstvalue;
if symbol1 <> rigthparsymbol then
  begin
   if symbbol1 = namesymbol then
      error(<:identifier allready declared:>);
     else
      error(<:identifier expected:>,skipsemicolon);
     end;
end identifierlist;

procedure vardecleration;
begin
comment the reserved word 'var' is met;
integer previusdeclaredtype;
comment contain information abaut the previus delclered
        type;
previusdeclaredtype := nil;
next;
if controldecleration(sy,bol,entry) then
  begin
  insert(entry,text,variabledec,nil);
  if next0 <> colonsymbol then
    begin
    error(<:colon expected:>,semicolonsymbol);
    end
   else
    begin
    typedec;
    includestackinentry(entry);
    if ntab(entry+5) = previusdefinedentry then
      definitionentry := ntab(entry+6) 
     else
      definitionindex := entry+5;
    
    definitiontype := ntab(definitionindex);
    if definitiontype = pointertype then
      begin
      declareinteger(<:po:>,entry);
      end
    if definitiontype = subrangerefferencetype then
      begin
      declareinteger(<:uf:>,entry);
      end
     else
    if difinitiontype = subrangenumbertype then
      begin
      declareinteger(<:un:>,entry);
      end
     else
    if definitiontype = enumerationtype then
      begin
      delareinteger(<:en:>,entry);
      end
    end;
  end;
if previusdeclaredtype <> nil then
  begin
  outcodechar(semicolon);
  outcodenl;

  end;
end vardecleration;
procedure declare(type,prefix,entry);
value dectype,entry;
string prefix;
begin
if type = previusdecleredtype then
  begin
  outcodechar(commachar);
  outcodenl;
  movetext6(text,ntab,entry-namelength);
  converttexttostring(text1,prefix);
  concat(text1,text);
end declare;


procedure prefixroutines;
begin
comment
  prefix routines is:

      <--<procedure heading><--
      !                        !
  -->------------------------------->
      !                       !
      <--<function heading><--
  ;
if symbol = reservedword
for dummy := dummy while (symbol = reservedword and
                            (aux = resfunction or aux = resprocedure) do
  begin
  if aux = resfunction then
    functionheading
   else
  if aux = resprocedure then
    procedureheading;
  end;
end prefixroutines;

procedure compoundstatement;
begin
comment
  compound statement is:
  where the reserved word begin allready is met.
  ;
end compoundstatement;

procedure statement;
begin
comment statement is:
      ;
next;
is symbol = reservedverd then
  begin
  if aux = resbegin then
    begin
    comment compoundstatement;
    compoundstatement;
    end
   else
  if aux = resif then
    begin
    istatement;
    end
   else
  if aux = resfor then
    begin
    forstatement;
    end
   else
  if aux = reswhile then
    begin
    whilestatement;
    end
   else
  if aux = resrepeat then
    begin
    repeatstatement;
    end
   else
  if aux = reswith then 
    begin
    withstatement;
    end
   else
    begin
    error(<:illegal reserved word, statement expected:>,skipsemicolon);
  end
 else
  if symbol = namesymbol or symbol=unknownname then
    begin
    if symbol = unknownname then
      begin
      error(<:undeclared:>);
      insert(entry,text,notype,nil);
      end;
    comment after meeting a name it can be either a assignment
            statement or a routinecall.
            A routine call can be a call of a function as
            the call of a type procedure in algol.
            if the next symbol is an assignment symbol then
            it is assumed to be a assignment statement else
            a routinecall.
            next and next0 have the 2 first symbols 
            in the statement.
            ;

    if next0 = assignmentsymbol then
      assignmentstatement
     else
      routinecallstatement;
    end
   else
    begin
    error(<:statement expected:>,skipsemicolon);
    end;
end statement;

procedure assignmentstatement;
begin
comment
  assignmentstatement used for assignment.
  assignment is:
  
  --><variable>-->:=--><expr>-->
  An assignment defines the assignment of an expression 
  value to a variable. The varable and the expression
  must be compatible. The variable must not be a constant
  parameter.
  transformed to algol as:
  --><varaible>-->:=--><expr>-->
  
  the variable name is in next, the assignmentsymbol
  is in next0.
  ;
integer assignmenttype;
end assignmentstatement;


procedure ifstatement;
begin
comment if statement is:
    -----
  where If allready is met.
  ;
outcodestring(<:if :>);
if expr <> booleantype then
  begin
  error(<:boolean expresion expected:>,skipsemicolon);
  end;
comment after expr the reserved word then
        schould be in next;
if symbol <> resthen then
  begin
  error(<:then expected:>,skipreservedwordsemicolon);
  end
 else
  begin
  outcodestring(<: then:>);
  outcodenl;
  end;
statement;
if symbol = reselse then
  begin
  outcode(<: else :>);
  outcodenl;
  statement;
  end;
end ifstatement;

procedure forstatement;
begin
comment the for statement is:
  where the reserved word for allready is met;
integer controlvariabletype;
outcodestring(<:for :>);
next;
if symbol = nametype then 
  begin
  outcodestring(<:si:>);
  movetext5(text,ntab,ntab(entry+entryrefname));
  outcodetext(text);
  if next <> assignmentsymbol then
    begin
    error(<:assignment expected:>,skipsemicolon);
    end
   else
    begin
    outcodestring(<::=:>);
    if expr <> controlvariabletype then
      begin
      error(<:expresion type error:>,skipsemicolon);
      end 
     else
      begin
      comment after expresion the reserved word
              to or downto is met from call of  next;
      if symbol <> resto and symbol <> resdownto then
        begin
        error(<:to or downto expected:>,skipsemicolon);
        end
       else
        begin
        if symbol = resto then
          outcodestring(<: step 1 until :>
         else
          outcodestring(<: step -1 until :>);
        if expr <> controlvariabletype then
          begin
          error(<:expresion type error:>,skipsemicolon);
          end
         else
          begin
          comment the reserved word do is met in expresion
          comment after expresion the reserved word 
                  do is met from call of next;
          if symbol <> resdo then
            begin
            error(<:do expected:>,noskip);
            end;
          outcodestring(<: do:>);
          outcodenl;
          statement;
          end;
        end;
      end;
    end;
  end 
 else
  begin
  error(<:enumeration type variable expected:>,skipsemicolon);
  end;
end forstatement;




procedure whilestatement;
begin
comment
  while statement is:
  -->'while'-->expr-->'do'-->statement-->
  where the namesymbol 'while' allready is met.
  transformed to algol as:
  -->'whilelab<no>:'-->                         

  -->'if -,('<expr>') then goto whilelab<no+1>'-->
  --> <statement><semicolon> -->
   !                          !
   ----------------------------
  --'goto whilelab<no>'<semicolon> -->
  -->whilelab<no+1><semicolon>-->
  ;
integer thiswhilelabelno;
integer array whilenotext,whileno1text(1:12);
thiswhilalabelno := whilelabno;
whilelabno := whilelabno +1;
thiswhilelabelno1 := whilelabno;
whilelabno := whilelabno +1;
outcodestring(<:whilelabel:>);
converttextinteger(whilenotext,thiswhilelabno);
outcodetext(whilenotext);
outcodechar(colonchar);
outcodechar(semicolonchar);
outcodenl;
outcodestring(<:if -,(:>);
expr;
if symbol <> name and aux <> resdo then
  begin
  error(<: do expected:>,skipsemicolon);
  end;
outcodestring(<:) then goto whilelab:>);
outcodetext(whileno1text);
outcodechar(semicolonchar);
statement;
outcodestring(<:goto whilelab:>);
outcodetext(whilenotext);
outcodechar(semicolonchar);
outcodenl;
outcodestring(<:whilelab:>);
outcodetext(whileno1text);
outcodechar(colonchar);
end whilestatement;

procedure repeatstatement;
begin
comment
  repeat statement is:
  -->'repeat'-->statement-->'until'-->expr-->
              !            !
              ------<semicolon><------
  where the name 'repest' is met.
  translated to algol as:
  -->'replab<no>:'-->statement<semicolon>--> 
                   !           !
                   -------------
  -->'if -,('expr') then goto replab<no>'-->
  ;
integer thisreplabno;
integer array repnotext(1:12);
thisreplabno := replabno;
replabno := replabno+1;
converttextinteger(repnotext,thisreplabno);
outcodetext(repnotext);
outcodenl;
outcodestringstring(<:::>);
statement;
if symbol = name and aux = resuntil then
  begin
  outcodenl;
  outcodestring(<:if -,(:>);
  expr;
  outcodestring(<:) then goto replab:>);
  outcodetext(repnotext);
  outcodechar(semicolonchar);
  end
 else
  begin
  error(<:until expected:>,skipsemicolon);
  end
end repeatstatement;



comment start program;
initgenerel;
program;
  
  end table dec. block;
comment label called from procedure fatalerror;
endprogram:
end outhermost block;
▶EOF◀