|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 66048 (0x10200) Types: TextFile Names: »platon1pas«
└─⟦2c55ea56f⟧ Bits:30001844 SW-save af projekt 1000, Alarm-system └─⟦6b41451d2⟧ └─⟦this⟧ »platon1pas«
program platonpass1(input,output,spixtable='spixtoname', codefile='pass1code',symbfile='pass1labels'); label 10; (*exit label*) const (* bobs-constants*) stackmax=100; (*size of attstack and parsestack *) stringmax=100; (* size of attribute string *) chbufmax=200; (* size of array chbuf *) minch=' '; maxch='ü'; (*first/last character in type char*) linemax=150; (*max. length of lines*) testoutput=false; (* do not output the steps in the parse *) (*global constants used in code*) higherror = 105; (* highest error number from code *) version = 'pascal80 version 1980.09.24'; nill = -1; (* end of chain *) alfalength=12; (*length of alfa variable*) blank=' '; (*to clear a variable of type alfa*) maxnamelength = 255; (* maximum length of a name *) maxnamenodeindex = 1500; (* maximum number of name chunks *) maxnameheads = 1000; (* maximum number of different names *) maxspix = 65000; (* maximum number of different spix'es *) typebuffersize= 500; (* maximum number of buffered codes *) hashtablesize = 41; maxinclude = 5; (* maximum number of unsatisfied include names *) stop3 = 3; (* option value to pass3 for stop.3 *) stop4 = 5; (* option value to pass4 for stop.4 *) stop5 = 5; (* option value to pass5 for stop.5 *) type (* bobs-types*) chbufinx=0..chbufmax; stackinx=0..stackmax; string=packed arrayÆ1..stringmaxÅ of char; (*types used in code*) attributes=record chbufp:chbufinx; bufferstart : 1..typebuffersize; (* start index in type buffer for this element *) oldlabelscope : integer; end; hashindex = 0..hashtablesize; namelength = 0.. maxnamelength; spixrange = 0.. maxspix; nameptr = nill .. maxnamenodeindex; nameheadptr = nill .. maxnameheads; namehead = packed record length : namelength; spix : spixrange; start : nameptr; (* first chunk *) next : nameheadptr; end; namenode = packed record next : nameptr; case boolean of true: ( namepart : alfa ); false: ( integerpart : integer ); (* integerpart is only used by the hash function *) end; inclindex = 0..maxinclude; includenamenode = record next : inclindex; namepart : alfa; end; declarekind = (decl, decllist); (* used by emitdeclare *) codes = ( cnocode, cerror, cerrortext, cerrorno, coption, cnewline, ceom, cstandardname, (* parameters to 'standardname' *) canonymous, (* first std name *) cboolean, cchar, cshadow, creference, csemaphore, cson, cexception, cabs, csucc, cpred, cord, (* last std name *) cinclude, cendinclude, ccontext, cerrcontext, cendcontext, cendprefix, cbeginlevel, cendlevel, cdeclaration, cdeclare, cdeclarelist, cexternal, cforward, cendformallist, cendformal, cendprocdecl, cendfuncdecl, cendtypedecl, cendconstantdecl, cnoinit, cinit, cendvardecl, cenddeclarations, cstartlabelscope, cendlabelscope, cbegincode, ccodeline, cendcode, cendblock, ctypeid, cendtype, cwithout_data, cnewtype, cendscalar, cendsubrange, cendarray, cendfield, cendrecord, cendset, cendpool, cendpointer, cendreadonly, cpacked, cbegin, cend, clabeldef, ccasestat, ccaseexpr, ccaselabel, ccaselabelrange, ccaselist, ccaseelement, cotherwise, cendcase, cforstat, cforvar, cup, cdown, cendfor, cifstat, cifexpr, celse, cendif, crepeatstat, cuntil, cendrepeat, cwhilestat, cwhileexpr, cendwhile, clockstat, cwithstat, cwithvar, cnolocaldecl, cendlocaldeclare, cwithcomma, cdo, cendwith, cgotostat, cendgoto, cchannelstat, cchanvar, cendchannel, cendassign, cendexchange, ccallprocedure, (* expression codes *) cendexpression, ceq, cne, clt, cle, cgt, cge, cin, cuplus, cuminus, cplus, cminus, cor, cstar, cslash, cdiv, cmod, cand, cnot, cgetvalue, cindex, (* <<< used internally by pass3 *) (* operand codes *) csetlist, cs_element, cm_element, cendsetlist, cliteral, cid, cskipparam, cfield, cuparrow, crangefirst, (* <<< used internally by pass3 *) cactualparam, cdoubleparam, cendactual, (* the following few lines are all for internal pass3-use *) cfunctrailer, cfunctemp, cerrorarg, cargument, cfcall, cendproc, cstrucrecord, cstrucarray, cendstruc, (* namekinds i.e. parameters for 'declaration' *) cprocess, cprocedure, cfunction, ctype, cscalarelem, crecfield, cconstant, cvar, cvarp, cvaluep, cfuncval (* <<< used internally by pass3 *), clabel, cprefix, cundeclared (* <<< used internally by pass3 *), (* typekinds *) calias (* <<< used internally by pass3 *), (* typekinds i.e. parameters for 'newtype' *) cerrorkind (* <<< used internally by pass3 *), cscalar, csubrange, carray, crecord, cset, cpool, cpointer, creadonly, (* standard types *) cinteger, creal, cniltype, ctext, (* used for string-literals *) clastcode (* used internally by pass1/pass3 *) ); codeindex = 0 .. 200; (* number of codes *) \f (* end pass 1 codes *) var i : integer; inputfile : boolean; systemparamno : integer; (* reference to next fp-parameter in the command stack *) (* bobs-variables*) attstack: arrayÆstackinxÅ of attributes; chbuf: arrayÆchbufinxÅ of char; chbufi: chbufinx; ok: boolean; (*chbuf, chbufi, field chbufp of attributes, tables and ok (*should not be changed by the user *) errormarks : packed array Æ0..higherrorÅ of boolean; warningcount, errorcount : integer ; line: arrayÆ1..linemaxÅ of char; (*contains current line*) linenumber, (* current global line number *) locallinenumber, (* current relative line number of current procedure *) linelength, (*length of current line*) errorinx, (*position in line of last error mark*) indention, (*number of leading spaces on a line *) lineinx: integer; (*position in line of current ch*) more_sources_allowed, (* true until prefix or process met *) call_pass_3, (* option '$ 1 2 1 ' *) programlist, (* option list.yes or '$ 1 1 1' *) printed: boolean; (*true if current line has been printed*) anonymousspix, (* spix of '?' *) lastspix, (* highest spix in use *) currentlabelscope, (* the actual label level *) lastlabelscope : integer; (* highest used scope nr *) before_standard_defs , contextparsing, nametable_dump : boolean; (* option survey.yes or no *) dimension_count, (* count nested arrays, i.e. the number of dimensions *) lastbuffered : integer; (* last used element in typebuffer *) typebuffer : array Æ0..typebuffersizeÅ of integer; typebufferflag : boolean; (* indicates whether the codes are to be buffered or not *) lastnamehead, (* last used name head *) nameheadfreelist : nameheadptr; lastnamenode, (* last used name node *) namenodefreelist : nameptr; nameheads : array Æ nameheadptr Å of namehead; namenodes : array Æ nameptr Å of namenode; namehashtable : array Æ hashindex Å of nameheadptr; (* the global variables used in emit-procedures *) symbfile, codefile : file of integer; spixtable : text; \f (* bobs-procedures*) procedure stop(n: integer); forward; procedure printline; var i :integer; begin if programlist then begin write(linenumber:5,' '); if locallinenumber < 0 then write(' ':5) else write(locallinenumber : 4, ' '); if indention>0 then write(' ':indention); for i:=1 to linelength do write(lineÆiÅ); writeln; end; printed:=true end; (*printline*) procedure warning(n: integer); var i : integer; prgrlst : boolean; begin warningcount := warningcount + 1; errormarksÆnÅ := true; if not printed then begin prgrlst := programlist; programlist := true; (* force printing of erroneous line *) printline; programlist := prgrlst; end; if errorinx=0 then begin write(' *********'); if indention>0 then write(' ':indention); end; for i:=errorinx to lineinx-2 do write(' '); write('^', n:1); errorinx:=lineinx+3 end; (* warning *) procedure markerror(n : integer); var oldwarning : integer; begin errorcount := errorcount + 1; oldwarning := warningcount; warning(n); warningcount := oldwarning; end; (* markerror *) procedure printerrors; var i, currenttextno : integer; ch : char; begin page(output); writeln(output,'number of errors :', errorcount : 4); writeln(output,'number of warnings:', warningcount : 4); writeln(output); writeln(output,'error description'); open(input,'platonerror'); reset(input); currenttextno := -1; for i := currenttextno + 1 to higherror do if errormarksÆiÅ then begin (* find the text *) while i > currenttextno do begin if not eof(input) then readln(input); if not eof(input) then read(currenttextno) else currenttextno := higherror + 1; end; write(output,i : 4, ': '); if i <> currenttextno then write(output, ' (no text) ') else while not eoln(input) do begin read(ch); write(output,ch); end; writeln(output); end; (* for i := .... *) end; (* printerrors *) procedure emit( code : codes; param1, param2 : integer; descriptor : codes ); begin if not typebufferflag then begin if code <> cnocode then write(codefile, ord(code)); if param1 <> nill then write(codefile, param1); if param2 <> nill then write(codefile, param2); if descriptor <> cnocode then write(codefile, ord(descriptor)); end; if typebufferflag then begin if typebuffersize - lastbuffered < 4 then stop(12); (*fatal error*) if code <> cnocode then begin lastbuffered := lastbuffered + 1; typebufferÆlastbufferedÅ := ord(code); end; if param1 <> nill then begin lastbuffered := lastbuffered + 1; typebufferÆlastbufferedÅ := param1; end; if param2 <> nill then begin lastbuffered := lastbuffered + 1; typebufferÆlastbufferedÅ := param2; end; if descriptor <> cnocode then begin lastbuffered := lastbuffered + 1; typebufferÆlastbufferedÅ := ord(descriptor); end; end; (* buffered mode *) end; (* emit *) procedure emitcode(code : codes ); begin emit(code, nill, nill, cnocode); end; procedure emitboth( code : codes ; param1, param2 : integer ); begin emit(code, param1, param2, cnocode); (* write the code on file for labels *) write(symbfile, ord(code)); if param1 <> nill then write(symbfile, param1); if param2 <> nill then write(symbfile, param2); end; procedure emitdeclare(kind : declarekind; spix : integer); var code : codes; begin case kind of decl: code := cdeclare; decllist: code := cdeclarelist; end; (* case *) emit(code, spix, nill, cnocode); end; (* emitdeclare *) procedure emitname(name : nameheadptr); (* write the name and the corresponding spix on file spixtable *) var namep : nameptr; begin with nameheadsÆ name Å do begin write(spixtable, spix : 4, ' '); namep := start; end; (* with name *) while namep <> nill do with namenodesÆ namep Å do begin write(spixtable, namepart); namep := next; end; (* while *) writeln(spixtable); end; (* emit name *) procedure returnname(name : nameheadptr); forward; function searchname( name : nameheadptr ) : spixrange; (* search the name in the name structure, if not found then insert the name; the function result is the spix which is associated with the name *) var current, former, result : nameheadptr; found : boolean; hashvalue : hashindex; name1, name2 : nameptr; begin hashvalue := namenodesÆ nameheadsÆ name Å.start Å.integerpart mod hashtablesize; current := namehashtableÆhashvalueÅ; former := nill; found := false; while current <> nill do with nameheadsÆ current Å do begin if length < nameheadsÆ name Å.length then begin former := current; current := next; end else if length = nameheadsÆ name Å.length then begin (* compare names *) name1 := start; name2 := nameheadsÆ name Å.start; while name1 <> nill do with namenodesÆ name1 Å do if namepart <> namenodesÆ name2 Å.namepart then name1 := nill (* exit, different *) else begin name1 := next; name2 := namenodesÆ name2 Å.next; end; if name2 = nill then (*current = name *) begin found := true; result := current; current := nill; (* exit *) end else (* different *) begin former := current; current := next; end; end (* current length = name length *) else (* current length > name length, i.e. insert *) current := nill; (* exit while *) end; (* while current <> nil *) if not found then (* insert *) with nameheadsÆ name Å do begin result := name; lastspix := lastspix + 1; spix := lastspix; if nametable_dump then emitname(name); if former = nill then (* insert name as the first name in the list *) begin next := namehashtableÆhashvalueÅ; namehashtableÆhashvalueÅ := name; end else (* insert name after 'former' *) begin next := nameheadsÆ former Å.next; nameheadsÆ former Å.next := name; end; end (* not found *) else returnname(name); (* now result points at the searched name *) searchname := nameheadsÆ result Å.spix; end; (* search name *) function getnamehead : nameheadptr; var nameheadp : nameheadptr; begin if nameheadfreelist = nill then begin if lastnamehead < maxnameheads then lastnamehead := lastnamehead + 1 else stop(11); (* fatal error *) nameheadp := lastnamehead; end else begin nameheadp := nameheadfreelist; nameheadfreelist := nameheadsÆ nameheadp Å.next; (* next keeps the chain of free elements *) end; with nameheadsÆ nameheadp Å do begin (* initialize the fields *) length := 0; start := nill; next := nill; spix := 0; end; getnamehead := nameheadp; end; (* get name head *) function getnamenode : nameptr; var name : nameptr; begin if namenodefreelist = nill then begin if lastnamenode < maxnamenodeindex then lastnamenode := lastnamenode + 1 else stop(10); (* fatal error *) name := lastnamenode; end else begin name := namenodefreelist; namenodefreelist := namenodesÆ name Å.next; end; with namenodesÆ name Å do begin next := nill; namepart := blank; end; getnamenode := name; end; (* get name node *) procedure returnname(name : nameheadptr); (* insert the name head and the name parts into the freelists *) var localnext, namelist : nameptr; begin (* return the head *) nameheadsÆ name Å.next := nameheadfreelist; nameheadfreelist := name; (* return the name part *) namelist := nameheadsÆ nameheadfreelist Å.start; while namelist <> nill do with namenodesÆ namelist Å do begin localnext := next; next := namenodefreelist; namenodefreelist := namelist; namelist := localnext; end; end; (* return name *) procedure read_and_parse_prefix(name : nameheadptr); (* parse a prefix-file as a context, i.e. no code is generated, only declarations *) const lookup_entry = 42; var lookupname : alfa; tail : array Æ1..10Å of integer; begin lookupname := namenodesÆ nameheadsÆ name Å.start Å.namepart; if monitor(lookup_entry, lookupname, tail) <> 0 then begin emitcode(cerrcontext); emitcode(cendcontext); end else begin open(input, lookupname); (* stack zone *) reset(input); end; end; (* read and parse prefix *) procedure predef_environment; (* generate code for standard names and standard types *) type double_alfa = packed array Æ 1 .. 24 (* 2 * alfalength *) Å of char; var codeword, kind : codes; step, spix, length : integer; function spix_of_name(name : double_alfa) : integer; (* convert the name into internal representation and search the name table for the spix *) var nameheadp : nameheadptr; locallength : integer; begin nameheadp := getnamehead; with nameheadsÆ nameheadp Å do begin start := getnamenode; with namenodes Æ start Å do begin for locallength := 1 to alfalength do namepart Æ locallength Å := name Æ locallength Å ; if name Æ alfalength + 1 Å <> ' ' then begin next := getnamenode; with namenodes Æ next Å do for locallength := 1 to alfalength do namepart Æ locallength Å := name Æ alfalength + locallength Å ; end; (* if name Æ alfalength + 1 Å <> space *) end; (* with namenodes Æ start Å *) locallength := alfalength * 2; if name <> blank then begin while nameÆ locallength Å = ' ' do locallength := locallength-1; length := locallength; spix_of_name := searchname(nameheadp); end else begin returnname(nameheadp); spix_of_name := nill; end; end; (* with nameheadsÆ nameheadp Å ... *) end; (* spix of name *) procedure standardnames(name : double_alfa; namecode : codes); (*insert the name into the name table and emit: standardname(spix stdname *) var spix : integer; begin spix := spix_of_name(name); if name = '? ' then anonymousspix := spix; emit( cstandardname, spix, nill, namecode); end; procedure standardtypes(name : double_alfa; typeflag : codes); (* insert the name into the nametable and emit: declaration( type ) declare( spix declnr ) newtype( typeflag ) endtypedecl *) var spix : integer; begin spix := spix_of_name(name); emit( cdeclaration, nill, nill, ctype); emitdeclare(decl, spix); emitcode(cendformal); emit( cnewtype, nill, nill, typeflag); emitcode(cendtypedecl); end; begin (* predef environment *) (* generate code for the standard names and types (build in types) *) (* note: the name-strings must be in upper case (internal representation) *) standardnames('? ', canonymous); standardnames('SUCC', csucc); standardnames('PRED', cpred); standardnames('ORD', cord); standardnames('CHR', cchr); standardnames('PROCESS_DESCRIPTOR', cson ); standardnames('PROCESSREC', cprocessrec); standardnames('ABS', cabs); standardnames('SHADOW', cshadow); standardnames('REFERENCE', creference); standardnames('CHAR', cchar); standardnames('BOOLEAN', cboolean); standardnames('SEMAPHORE', csemaphore); standardnames('EXCEPTION', cexception); standardtypes('INTEGER', cinteger); standardtypes('REAL', creal); standardtypes('NILTYPE', cniltype); before_standard_defs := false; end; (* predefine environment *) \f procedure readcall; (* read the call of the compiler from current input *) const power12=4096; equality=6; point=8; list = 'list '; yes = 'yes '; no = 'no '; survey= 'survey '; codesize = 'codesize'; (* option for pass6, the size of a program page *) stop = 'stop'; (* option stop.<pass nr> *) spacing = 'spacing'; includ= 'include '; var i,j, int, stop_code, separator, length : integer; a, codefilename, sourcefilename : alfa; first : boolean; read_env_flag : boolean; param : (list_program, filename, code_size, surveyinfo, stop_param, spacing_param); procedure checkleftside; (* check the call of the compiler, look for 'include' and if found then read environment from the specified file, else read standard environment, after the call systemparamno is the number of the first input information parameter *) begin systemparamno := 1; if system(systemparamno, int, a) div power12 = equality then begin (* left hand side present *) i := system(0, int, codefilename); for i := 1 to alfalength div 2 do begin emit(coption, 6, 80 + i, cnocode); emit(cnocode, ord( codefilename Æ i * 2 - 1 Å ) * 256 + ord( codefilename Æ i * 2 Å ), nill, cnocode ); end; (* output codefilename *) systemparamno := systemparamno + 1; (* skip name platon *) end; end; (* checkcall *) procedure error; begin writeln(' ??? error in call of pascal80 compiler'); goto 10; end; begin read_env_flag := systemparamno = nill; if read_env_flag then checkleftside; if inputfile then begin close(input); inputfile := false; end; j:=system(systemparamno,int,a); first:=true; param := pred(filename); (* param <> filename *) while ((j mod power12) <> 0) and ((j div power12) <> 2) and (param <> filename) do begin separator:=j div power12; length:=j mod power12; if first then begin first:=false; if separator = point then error else if a = list then param:=list_program else if a = codesize then param := code_size else if a = spacing then param := spacing_param else if a = stop then param := stop_param else if a = survey then param := surveyinfo else begin param := filename; sourcefilename := a; end; end else begin first:=true; if (separator <> point) and (param <> filename) then error else case param of list_program:if length <> 10 then error else if (a=yes) or (a=no) then programlist := a=yes else error; stop_param: if length <> 4 then error else (* generate an option for the pass to stop after *) if (int = 3) or (int = 4) or (int = 5) then begin case int of 3: stop_code := stop3; 4: stop_code := stop4; 5: stop_code := stop5; end; (* case *) emit(coption, int, nill, cnocode); emit(cnocode, stop_code, 0, cnocode); end (* 3, 4, 5 *) else if (int = 1) or (int = 2) then call_pass_3 := false; surveyinfo: if length <> 10 then error else if (a = yes) or (a = no) then begin if a = yes then begin emit( coption, 5, 3, cnocode ); (* generate statistics in pass 5 *) emit( cnocode, 1, nill, cnocode ); emit( coption, 6, 10, cnocode ); (* generate statistics in pass 6 *) emit( cnocode, 1, nill, cnocode ); end; nametable_dump := a = yes end else error; code_size: if length <> 4 then error else begin emit(coption, 6, 3, cnocode); (* !!!! must be as defined by pass6 !!! *) emit(cnocode, int, nill, cnocode); end; spacing_param: if length <> 4 then error else begin emit(coption, 6, 9, cnocode); (* must be as defined by pass6 !!! *) emit(cnocode, int, nill, cnocode); end; filename: systemparamno := systemparamno - 1; (* make the next increment dummy *) end; (* case *) end; (* second *) systemparamno := systemparamno + 1; j:=system(systemparamno,int,a); end; if read_env_flag then begin sourcefilename := 'platonenv'; if param = filename then systemparamno := systemparamno - 1 (* do not skip file name *) else param := filename; (* force open call *) end; if param = filename then begin open(input, sourcefilename); reset(input); inputfile := true; end; end; (* read call *) procedure initialize; var ch:char; step : integer; dato, tim:alfa; begin date(dato); time(tim); writeln(dato,tim:15,version:50); writeln; (* initialize global variables and open files *) systemparamno := nill; more_sources_allowed := true; inputfile := false; (* inputfile met in the call *) programlist := false; (* list.no is default *) call_pass_3 := true; (* automatical call of pass3 if no errors detected *) locallinenumber := -1; linenumber := 0; for step := 1 to higherror do errormarksÆstepÅ := false; errorcount := 0; warningcount := 0; lastspix := 0; lastlabelscope := 0; currentlabelscope := lastlabelscope; nametable_dump := false; (* survey.no *) lastbuffered := 0; typebufferflag := false; nameheadfreelist := nill; lastnamehead := nill; namenodefreelist := nill; lastnamenode := nill; for step := 0 to hashtablesize do namehashtableÆstepÅ := nill; rewrite(symbfile); rewrite(codefile); rewrite(spixtable); (* force generation of code for the predefined names and types *) before_standard_defs := true; end; (* bobs procedure code*) (*$r+*) procedure code(oldtop,newtop: stackinx; prod: integer); (*$r-*) (* bobs local procedures*) procedure getstring(sy,start: integer; var str:string; var length: integer); var i,j,t:integer; begin if sy>=0 then t:=newtop+(sy-1) else t:=oldtop+(sy-1); length:=attstackÆtÅ.chbufp-attstackÆt-1Å.chbufp+start-1; if length>stringmax-start+1 then stop(5); j:=start; for i:=attstackÆt-1Å.chbufp to attstackÆtÅ.chbufp-1 do begin strÆjÅ:=chbufÆiÅ; j:=j+1 end end; (*getstring*) procedure outtest; (*outtest produces a sequence of snaphots of the parse (*outtest may be removed by the user *) (*during the parse, snapshots are written on file output *) (*program lines which writes snapshots contains the comment:*) (***snapshot***) var s: string; i,j,l:integer; ch:char; begin writeln(output); write(output,' production:',prod:3); for i:=1 to oldtop-newtop+1 do begin getstring(i,1,s,l); if l>0 then begin writeln(output); write(output,' symb',i:1,' '); for j:=1 to l do write(output,sÆjÅ) end end end; (*outtest*) function readname : nameheadptr; (* read the name from chbuf(oldtop) into a name structure and return a reference to the head *) var localhead : nameheadptr; chbufindex, charcount : integer; localname : nameptr; begin localhead := getnamehead; (* allocate a new name head *) with nameheadsÆ localhead Å do begin length := attstackÆoldtopÅ.chbufp - attstackÆoldtop-1Å.chbufp; start := getnamenode; localname := start; charcount := 0; chbufindex := attstackÆoldtop-1Å.chbufp; repeat with namenodesÆ localname Å do namepartÆ (charcount mod alfalength) + 1 Å := chbufÆ chbufindex Å; charcount := charcount + 1; chbufindex := chbufindex + 1; if ((charcount mod alfalength) = 0) and (charcount < length) then with namenodesÆ localname Å do begin (* get a new name node *) next := getnamenode; localname := next; end; until charcount = length; end; (* with ... *) readname := localhead; end; (* read name *) procedure errorsection; begin emitcode(cerror); end; procedure literals( prod : integer ; convert : boolean ); (* section 4 *) var length, stepvar : integer; codekind : codes; ord_char : integer; begin case prod of 401: (* <unsigned constant> ::= string *) codekind := ctext; 402: (* <unsigned number> ::= <unsigned integer> *) codekind := cinteger; 403: (* <unsigned number> ::= realkonst *) codekind := creal; 404: (* <unsigned integer> ::= # name *) codekind := cinteger; end; (* case *) (* code: literal(length codekind) string *) length := attstackÆoldtopÅ.chbufp - attstackÆoldtop-1Å.chbufp; if prod = 404 then length := length + 1; (* '#' *) emitcode(cliteral); emit(codekind, length, nill, cnocode); if prod = 404 then (* emit( '#' ) *) emit(cnocode, ord('#'), nill, cnocode ); for stepvar := attstackÆoldtop-1Å.chbufp to attstackÆoldtopÅ.chbufp-1 do begin ord_char := ord( chbuf Æ stepvar Å ); if (convert or (prod <> 401)) and (ord_char >= ord('A')) and (ord_char <= ord('Z')) then ord_char := ord_char + ord('a') - ord('A'); (* convert to lower case *) emit(cnocode, ord_char, nill, cnocode); end; end; (* literals *) \f procedure constantdeclaration; (* section 5 *) var name : nameheadptr; namespix : integer; begin case prod of 501: (* <constant definition> ::= <constname> = <expression> <semicolons> *) (*code: endconstantdecl *) emitcode(cendconstantdecl); 502: (* <constname> ::= name *) (* declaration(constant) declare(spix) *) begin name := readname; namespix := searchname(name); emit( cdeclaration, nill, nill, cconstant); emitdeclare(decl, namespix); end; (* 502 *) 503: (* <constant definition> ::= <constname> error *) (* code: id(anonymous) endexpression endconstantdecl *) begin emit(cid, anonymousspix, nill, cendexpression); emitcode(cendconstantdecl); end; end; (* case *) end; (* constant declaration *) \f procedure typedefinition; (* section 6 *) var codeword : codes; name : nameheadptr; stepvar, namespix : integer; begin if (prod >= 601) and (prod < 620) then begin case prod of 601: (* <type definition> ::= <type name> <formal parameters> <eq> <type> <semicolons> *) (* code: endtypedecl endlevel *) begin emitcode(cendtypedecl); codeword := cendlevel; end; 602: (* <eq> ::= = *) (* no code *) codeword := cnocode; 603: (* <type> ::= <variable> *) (* code: endtype *) begin typebufferÆ attstackÆ newtop - 1 Å.bufferstartÅ := ord(ctypeid); (* i.e. change the former generated id to typeid *) codeword := cendtype; end; 604: (* <type> ::= <structured type> *) (* ! <pool type> *) (* no code *) codeword := cnocode; 605: (* <type> ::= <uparrow> <type> *) (* code: endpointer *) codeword := cendpointer; 606: (* <type> ::= <read only> <type> *) (* code: endreadonly *) codeword := cendreadonly; 607: (* <type> ::= <start scalar> <identifier list> ) *) (* code: endscalar *) codeword := cendscalar; 608: (* <type> ::= <expression> <end subrange> *) (* code: endsubrange *) begin with attstackÆ newtop - 1 Å do begin typebufferÆ bufferstart - 2 Å := ord(cnewtype); typebufferÆ bufferstart - 1 Å := ord(csubrange); end; (* with *) codeword := cendsubrange; end; 609: (* <array type> ::= <array start> <type> <component type> *) (* code: endarray *) begin for stepvar := 1 to dimension_count do emitcode(cendarray); codeword := cendarray; end; 610: (* <record type> ::= <record> <field list> end *) (* code: endlevel endrecord *) begin emitcode(cendlevel); codeword := cendrecord; end; 611: (* <record section> ::= <start section> <field identifier list> <type colon> <type> *) (* code: endfield *) codeword := cendfield; 612: (* <set type> ::= <set of> <type> *) (* code: endset *) codeword := cendset; 613: (* <pool type> ::= <pool> <expression> <type size> *) (* code: endpool *) codeword := cendpool; 614: (* <structured type> ::= packed <unpacked structured type> *) (* code: packed *) codeword := cpacked; end; (* case 601..619 *) if (prod >= 603) and (prod <= 608) then if (lastbuffered > 0) and (attstackÆ newtop - 1 Å.bufferstart = 3) then (* i.e. if anything buffered and <type> is the outermost incarnation *) begin typebufferflag := false; for stepvar := 1 to lastbuffered do emit( cnocode, typebufferÆstepvarÅ, nill, cnocode); lastbuffered := 0; end; (* if buffered *) emitcode(codeword); end; (* if .... *) if (prod >= 620) and (prod < 630) then begin case prod of 620: (* <uparrow> ::= ^ *) (* code: newtype pointer *) codeword := cpointer; 621: (* <startscalar> ::= ( name , *) (* code: newtype scalar *) (* declaration( scalarelem ) and *) (* declarelist( name ) is generated after the case statement *) codeword := cscalar; 622: (* <read only> ::= ! *) (* code: newtype readonly *) codeword := creadonly; 623: (* <array> ::= array ( *) (* code: newtype array *) codeword := carray; 624: (* <record> ::= record *) (* code: newtype record beginlevel *) codeword := crecord; 625: (* <set of> ::= set <of type> *) (* code: newtype set *) codeword := cset; 626: (* <pool> ::= pool *) (* code: newtype pool *) codeword := cpool; end; (* case .. *) emit(cnewtype, nill, nill, codeword); if (* scalarlist start *) prod = 621 then begin emit(cdeclaration, nill, nill, cscalarelem ); oldtop := oldtop - 1 ; (* let oldtop denote name *) name := readname; oldtop := oldtop + 1; (* reset oldtop *) namespix := searchname(name); emitdeclare(decllist, namespix); end (* start scalar *) else if (* record *) prod = 624 then emitcode(cbeginlevel); end; (* 620..629 *) if (prod >= 630) and (prod <= 639) then case prod of 630: (* <scalar list> ::= <scalar list>, name *) (* ! name *) (* code: declarelist( spix ) *) begin name := readname; namespix := searchname(name); emitdeclare(decllist, namespix); end; 631: (* <field identifier list> ::= <field identifier list> , name *) (* ! name *) (* code: declarelist( spix ) *) begin name := readname; namespix := searchname(name); emitdeclare(decllist, namespix); end; (* 631 *) 632: (* <start section> ::= empty *) (* code: declaration( recfield ) *) emit(cdeclaration, nill, nill, crecfield); 633: (* <name colon> ::= name : *) (* formal parameter of a parameterized type specification of a formal parameter *) (* code: declaration( valuep ) declarelist( spix ) *) begin oldtop := oldtop - 1; (* let oldtop denote name *) name := readname; oldtop := oldtop + 1; (* reset oldtop *) emit(cdeclaration, nill, nill, cvaluep); emitdeclare(decllist, searchname(name)); end; 635: (* <type size> ::= empty *) (* code: without_data *) (* code for a pool of headers, i.e. without data parts *) emitcode(cwithout_data); 636: (* <component type> ::= ) <of type> <type> *) (* ! error *) (* action: initialize dimension count *) begin dimension_count := 0; if newtop = oldtop (* i.e. error *) then emitcode(cerror); end; 637: (* <component type> ::= <new dimension> <type> <component type> *) (* action: increase dimension count *) dimension_count := dimension_count + 1; end; (* case 630..639 *) if prod = 600 then begin (* <type name> ::= name *) (* code: declaration( type ) declare( spix ) *) name := readname; namespix := searchname(name); emit( cdeclaration, nill, nill, ctype); emitdeclare(decl, namespix); end; (* 600 *) (* if before <type> then *) if (prod=602) or (prod=620) or (prod=622) or (prod=623) or (prod=625) or (prod=633) or (prod=640) then begin if lastbuffered + 3 > typebuffersize then stop(12); (* avoid destroying the buffermark because of newline, i.e. the newline codes are generated in front of the marked codes in stead of the (random) places where the newlines are met *) emit(cnewline, linenumber, nill, cnocode); typebufferflag := true; typebufferÆ lastbuffered + 1 Å := nill; typebufferÆ lastbuffered + 2 Å := nill; (* reserve room for a possible newtype .. *) lastbuffered := lastbuffered + 2; attstackÆ newtop Å . bufferstart := lastbuffered + 1; end; end; (* section 6 *) \f procedure variabledefinition; (* section 7 *) var name : nameheadptr; namespix : integer; begin case prod of 700: (* <start var> ::= empty *) (* code: declaration( var ) *) emit(cdeclaration, nill, nill, cvar); 701, (* <ident> ::= name *) 704: (* ! ? *) (* code: declarelist( spix ) *) begin if prod = 701 then begin name := readname; namespix := searchname(name); end else namespix := anonymousspix; emitdeclare(decllist, namespix); end; 702: (* <initialization> ::= <expression> *) (* code: init *) emitcode(cinit); 703: (* <var decl> ::= <start var> <identifier list> <type colon> <type> <initialization> <semicolons> *) (* code: endvardecl *) emitcode(cendvardecl); 705: (* <initialization> ::= empty *) (* code: noinit *) emitcode(cnoinit); end; (* case ... *) end; (* section 7 *) procedure expression; (* section 8 *) var codeword1, codeword2 : codes; var_or_field_spix : integer; name : nameheadptr; begin if prod <= 808 then codeword2 := cendexpression else codeword2 := cnocode; var_or_field_spix := nill; case prod of 801: (* <expression> ::= <simple expression> *) (* code: endexpression *) codeword1 := cnocode; 802: (* <expression> ::= <simple expression> = <simple expression> *) (* code: eq endexpression *) codeword1 := ceq; 803: (* <expression> ::= <simple expression> <> <simple expression> *) (* code: ne endexpression *) codeword1 := cne; 804: (* <expression> ::= <simple expression> < <simple expression> *) (* code: lt endexpression *) codeword1 := clt; 805: (* <expression> ::= <simple expression> <= <simple expression> *) (* code: le endexpression *) codeword1 := cle; 806: (* <expression> ::= <simple expression> > <simple expression> *) (* code: gt endexpression *) codeword1 := cgt; 807: (* <expression> ::= <simple expression> >= <simple expression> *) (* code: ge endexpression *) codeword1 := cge; 808: (* <expression> ::= <simple expression> in <simple expression> *) (* code: in endexpression *) codeword1 := cin; 810: (* <simple expression> ::= <simple expression> + <term> *) (* code: plus *) codeword1 := cplus; 811: (* <simple expression> ::= <simple expression> - <term> *) (* code: minus *) codeword1 := cminus; 812: (* <simple expression> ::= <simple expression> or <term> *) (* code: or *) codeword1 := cor; 813: (* <simple expression> ::= + <term> *) (* code: uplus *) codeword1 := cuplus; 814: (* <simple expression> ::= - <term> *) (* code: uminus *) codeword1 := cuminus; 816: (* <term> ::= <term> * <factor> *) (* code: star *) codeword1 := cstar; 817: (* <term> ::= <term> / <factor> *) (* code: slash *) codeword1 := cslash; 818: (* <term> ::= <term> div <factor> *) (* code: div *) codeword1 := cdiv; 819: (* <term> ::= <term> mod <factor> *) (* code: mod *) codeword1 := cmod; 820: (* <term> ::= <term> and <factor> *) (* code: and *) codeword1 := cand; 825: (* <factor> ::= <set> *) (* code: endsetlist *) codeword1 := cendsetlist; 826: (* <start set> ::= (. *) (* code: setlist *) codeword1 := csetlist; 827: (* <element> ::= <expression> *) (* code: s_element *) codeword1 := cs_element; 828: (* <element> ::= <expression> .. <expression> *) (* code: m_element *) codeword1 := cm_element; 830: (* <factor> ::= <variable> *) (* code: endvariable *) codeword1 := cendvariable; 831: (* <factor> ::= not <factor> *) (* code: not *) codeword1 := cnot; 835: (* <variable> ::= name *) (* code: id( spix ) may later on be changed to typeid(spix) *) begin codeword1 := cid; name := readname; var_or_field_spix := searchname(name); end; 836: (* <variable> ::= <variable> . name *) (* code: field( spix ) *) begin codeword1 := cfield; name := readname; var_or_field_spix := searchname(name); end; 837: (* <variable> ::= <variable> <begin actual> <actual parameter list> ) *) (* code: endactual *) codeword1 := cendactual; 838: (* <variable> ::= <variable> ^ *) (* code: uparrow *) codeword1 := cuparrow; 839: (* <begin actual> ::= ( *) (* code: beginactual *) codeword1 := cbeginactual; end; (* case ... *) emit( codeword1, var_or_field_spix, nill, codeword2); end; (* section 8 *) \f procedure statement; (* section 9 *) var codeword, codeword2 : codes; param1 : integer; name : nameheadptr; begin codeword2 := cnocode; param1 := nill; case prod of 901: (* <compound statement> ::= <begin> <statement list> end *) (* code: end *) codeword := cend; 902: (* <begin> ::= begin *) (* code: begin *) codeword := cbegin; 903: (* <procedure call> ::= <variable> *) (* code: callprocedure *) codeword := ccallprocedure; 904: (* <actual parameter> ::= <expression> *) (* code: actualparam *) begin codeword := cactualparam; end; 905: (* <actual parameter> ::= <expression> *** <expression> *) (* code: doubleparam *) begin codeword := cdoubleparam; end; 906: (* <assignment statement> ::= <variable> := <expression> *) (* code: endassign *) codeword := cendassign; 907: (* <exchange statement> ::= <variable> :=: <variable> *) (* code: endexchange *) codeword := cendexchange; 909: (* <case statement> ::= <selector part> <case list> <end case part> *) (* code: endcase *) codeword := cendcase; 910: (* <selector part> ::= <case> <expression> of *) (* code: caseexpr *) codeword := ccaseexpr; 911: (* <case> ::= case *) (* code: casestat *) codeword := ccasestat; 912: (* <case list element> ::= <case label list> <end label list> <statement> *) (* <end case part> ::= <otherwise> <statement> end *) (* code: caseelement *) codeword := ccaseelement; 913: (* <label range> ::= <expression> .. <expression> *) (* code: caselabelrange *) codeword := ccaselabelrange; 914: (* <label range> ::= <expression> *) (* code: caselabel *) codeword := ccaselabel; 915: (* <end label list> ::= : *) (* code: caselist *) codeword := ccaselist; 916: (* <otherwise> ::= otherwise *) (* code: otherwise caselist *) begin codeword := cotherwise; codeword2 := ccaselist; end; 917, (* <statement> ::= <for do> <start labelscope> <statement> <end labelscope> *) 933, (* ! <while do> <start labelscope> <statement> <end labelscope> *) 936, (* ! <with or lock> <start labelscope> <statement> <end labelscope> *) 947: (* ! <channel do> <start labelscope> <statement> <end labelscope> *) (* <balanced statement> ::= <for do> <start labelscope> <balanced statement> <end labelscope> *) (* ! <while do> <start labelscope> <balanced statement> <end labelscope> *) (* ! <with or lock> <start labelscope> <balanced statement> <end labelscope> *) (* ! <channel do> <start labelscope> <balanced statement> <end labelscope> *) (* code: endfor/endwhile/endwith/endchannel *) begin case prod of 917: codeword := cendfor; 933: codeword := cendwhile; 936: codeword := cendwith; 947: codeword := cendchannel; end; (* case *) end; (* 917, 933, 936, 947 *) 918: (* <for do> ::= <for to> <expression> do *) (* code: up *) codeword := cup; 919: (* ! <for downto> <expression> do *) (* code: down *) codeword := cdown; 920: (* <for assign> ::= <for> <variable> := *) (* code: forvar *) codeword := cforvar; 921: (* <for> ::= for *) (* code: forstat *) codeword := cforstat; 922: (* <goto statement> ::= <goto> <lab name> *) (* code: endgoto *) codeword := cendgoto; 923: (* <goto> ::= goto *) (* code: gotostat *) codeword := cgotostat; 924: (* <lab name> ::= name *) (* ! konst *) (* code: id ( spix ) *) begin name := readname; param1 := searchname(name); codeword := cid; end; 925: (* <statement> ::= <if then> <statement> *) (* ! <if then else> <statement> *) (* <balanced statement> ::= <if then else> <balanced statement> *) (* code: endif *) begin codeword := cendif; end; 926: (* <if then> ::= <if part> <expression> then *) (* code: ifexpr *) codeword := cifexpr; 927: (* <if part> ::= if *) (* code: ifstat *) codeword := cifstat; 928: (* <if then else> ::= <if then> <balanced statement> else *) (* code: else *) codeword := celse; 929: (* <until> ::= until *) (* code: until *) begin codeword := cuntil; end; 930: (* <repeat statement> ::= <repeat until> <expression> *) (* code: endrepeat *) codeword := cendrepeat; 931: (* <repeat until> ::= <repeat> <statement list> until *) (* code: endlabelscope( scopenr ) *) begin codeword := cendlabelscope; param1 := currentlabelscope; currentlabelscope := attstackÆnewtopÅ.oldlabelscope; end; 932: (* <repeat> ::= repeat *) (* code: repeatstat *) codeword := crepeatstat; 934: (* <while do> ::= <while> <expression> do *) (* code: whileexpr *) codeword := cwhileexpr; 935: (* <while> ::= while *) (* code: whilestat *) codeword := cwhilestat; 937: (* <with or lock part> ::= with *) (* code: withstat *) codeword := cwithstat; 938: (* <with comma> ::= , *) (* code: withcomma *) codeword := cwithcomma; 939: (* <with variable> ::= <variable> *) (* code: withvar nolocaldeclare *) begin codeword := cwithvar; codeword2 := cnolocaldeclare; end; 940: (* <as> ::= as *) (* code: withvar *) codeword := cwithvar; 941: (* <local name> ::= name *) (* code: declaration( var ) declare( spix ) *) begin name := readname; emit( cdeclaration, nill, nill, cvar); emitdeclare(decl, searchname(name)); (* the code is generated here, and the general mechanism of this section is not used ( codeword = nocode ) *) codeword := cnocode; end; (* 941 *) 942: (* <with variable> ::= <variable> <as> <local name> <type colon> < type> *) (* code: endlocaldeclare *) codeword := cendlocaldeclare; 948: (* <channel do> ::= <channel> <variable> do *) (* code: chanvar *) codeword := cchanvar; 949: (* <channel> ::= channel *) (* code: channelstat *) codeword := cchannelstat; 950: (* <with do> ::= <with as> <local declaration> do *) (* code: do *) codeword := cdo; 955: (* <actual parameter> ::= ? *) (* code: skipparam *) codeword := cskipparam; 965: (* <with or lock part> ::= lock *) (* code: lockstat *) codeword := clockstat; end; (* case .... *) (* now the parameters for the emit call has been set up *) emit( codeword, param1, nill, codeword2); end; (* section 9 *) \f procedure emitroutinedecl( routine_kind : codes; name : nameheadptr); (* emit: declaration ( routine_kind ) . literal( text length) 'name' . declare( spix ) *) begin emit(cdeclaration, nill, nill, routine_kind); literals( 401 (* i.e. text *) , true (* covnert to small letters *) ); emitdeclare(decl, searchname( name ) ); end; (* emitroutinedecl *) procedure proceduredeclaration; (* section 10 *) (* this section covers - in addition to procedure declarations - the parsing of <formal parameters> and <block> and <declarations> *) var name : nameheadptr; codeword : codes; step : integer; begin case prod of 1002: (* <routine heading> ::= <procedure heading> *) (* code: endprocdecl *) begin emitcode(cendprocdecl); end; 1003: (* <procedure name> ::= name *) (* code: declaration( procedure ) literal( text length) 'name' declare( spix ) *) begin name := readname; emitroutinedecl( cprocedure, name ); end; 1006: (* <parameter description> ::= <var or value> <parameter group> <type colon> <type> *) (* code: endformallist *) emitcode(cendformallist); 1007: (* <formal parameters> ::= <init formal> *) (* ! <init formal> ( <formal list> ) *) (* <actual parameter> ::= <name colon> <type> *) (* formal parameter of a parameterized type which is used as formal type specification *) (* code: endformal *) emitcode(cendformal); 1008: (* <parameter group> ::= name *) (* ! <parameter group> , name *) (* code: declarelist( spix ) *) begin name := readname; emitdeclare(decllist, searchname(name)); end; 1009: (* <declarations> ::= <decl start> <decls> *) (* code: enddeclarations *) (* action: change input file if context parsing *) begin if contextparsing then begin linenumber := 0; locallinenumber := -1; (* suppress local line numbering *) end else locallinenumber := 0; emitcode(cenddeclarations); end; 1010: (* <decl start> ::= empty *) (* code: beginlevel *) begin emitcode(cbeginlevel); end; 1011: (* <block> ::= <declarations> <start labelscope> <compound statement> <end labelscope> *) (* code: endblock endlevel endlevel *) (* action: stop local line numbering *) begin emitboth(cendblock, nill, nill); emit( cendlevel, nill, nill, cendlevel); locallinenumber := -1; (* suppress printing of local line numbers *) end; 1020, (* <block> ::= external *) 1021: (* ! forward *) (* code: external/forward endlevel *) begin if prod = 1020 then codeword := cexternal else codeword := cforward; emitcode(codeword); emitcode(cendlevel); locallinenumber := -1; end; 1022: (* <init formal> ::= empty *) (* code: beginlevel *) emitcode(cbeginlevel); 1023, (* <var or value> ::= empty *) 1024: (* ! var *) (* code: declaration( valuep/varp ) *) begin if prod = 1023 then codeword := cvaluep else codeword := cvarp; emit( cdeclaration, nill, nill, codeword); end; end; (* case *) end; (* section 10 *) \f procedure functiondeclaration; (* section 11 *) begin case prod of 1101: (* <routine heading> ::= <function heading> *) (* code: endfuncdecl *) begin emitcode(cendfuncdecl); end; 1102: (* <function name> ::= name *) (* code: declaration ( function ) . literal ( text length ) 'name' . declare ( spix ) *) begin emitroutinedecl( cfunction, readname ); end; end; (* case *) end; (* section 11 *) \f procedure labeldeclaration; (* section 12 *) begin case prod of 1201: (* <label name> ::= name *) (* ! konst *) (* code: if declarations then declaration( label ) declare( spix ) else labeldef( currentlabelscope spix), labeldef( currentlabelscope spix ) *) if locallinenumber = -1 then (* i.e. declaration of a label *) begin emit( cdeclaration, nill, nill, clabel); emitdeclare(decl,searchname(readname)); end else begin emitboth(clabeldef, currentlabelscope, searchname(readname)); end; 1202: (* <start labelscope> ::= empty *) (* code: startlabelscope( scope ) *) begin attstackÆ newtop Å . oldlabelscope := currentlabelscope; lastlabelscope := lastlabelscope + 1; currentlabelscope := lastlabelscope; emit(cstartlabelscope, currentlabelscope, nill, cnocode); end; 1203: (* <end labelscope> ::= empty *) (* code: endlabelscope( scope ) *) begin emit(cendlabelscope, currentlabelscope, nill, cnocode); currentlabelscope := attstackÆ newtop - 2 Å . oldlabelscope; (* i.e. get the scope stored in attstackÆ <start labelscope> Å *) end; end; (* case *) end; (* section 12 *) \f procedure processdeclaration; (* section 13, process and prefix declaration *) var name : nameheadptr; codeword : codes; begin case prod of 1301: (* <context name> ::= name *) (* code: context( spix ) *) begin if before_standard_defs then predef_environment; name := readname; emit(ccontext, searchname(name), nill, cnocode); contextparsing := true; end; 1302: (* <include list> ::= <include list> , name *) (* ! name *) (* pick up the name and store it into the includelist *) (* not implemented yet *) writeln(output,nl, nl, '****** include not implemented yet '); 1303: (* <body> ::= <process declaration> *) (* ! <prefix declaration> *) (* code: eom *) begin emitcode(ceom); ok := false; (* stop parsing *) if not printed then printline; (* print the last line *) end; 1304: (* <procsems> ::= <semicolons> *) (* code: endprocdecl *) begin emitcode(cendprocdecl); end; 1305, (* <process name> ::= name *) 1306: (* <prefix name> ::= name *) (* code: declaraton( process/prefix ) declare( spix ) *) begin name := readname; if prod = 1305 then codeword := cprocess else codeword := cprefix; emitroutinedecl( codeword, name ); end; 1307: (* <prefix declaration> ::= <prefex heading> <semicolons> <declarations> *) (* code: endprefix *) begin emitcode(cendprefix); end; 1310: (* <external> ::= <context name> <semicolons> <declarations> . *) (* code: endcontext *) (* action: contextparsing := false *) begin contextparsing := false; emitcode(cendcontext); end; 1311: (* <external part> ::= <externals> *) (* code: endinclude beginlevel *) begin more_sources_allowed := false; emit(cendinclude, nill, nill, cbeginlevel); end; end; (* case *) end; (* section 13 *) \f begin (* code *) if testoutput then outtest;(***snapshot***) case prod div 100 of 0: ; (* nothing is done *) 1: errorsection; (* ** ::= error *) 2, 3: ; (* not used *) 4: literals( prod, false (* do not convert literals to small letters *) ); 5: constantdeclaration; 6: typedefinition; 7: variabledefinition; 8: expression; 9: statement; 10: proceduredeclaration; 11: functiondeclaration; 12: labeldeclaration; 13: processdeclaration; end; (* case ... *) end;(*code*) (* bobs procedures continuated*) procedure stop; begin markerror(0); writeln(output);writeln(output); case n of 1: writeln(output,' *** parse stack overflow. const ''stackmax'' too small'); 2: writeln(output,' *** end of file encountered '); 3: writeln(output,' *** recovery abandoned '); 4: writeln(output,' *** reduction buffer overflow. const ''redumax'' too small'); 5: writeln(output,' *** const ''stringmax'' too small '); 6: writeln(output,' *** const ''chbufmax'' too small '); 10: writeln(output,' *** const ''maxnamenodeindex'' too small '); 11: writeln(output, ' *** const ''maxnameheads'' too small '); 12: writeln(output, ' *** const ''typebuffersize'' too small '); end; goto 10; (*exit*) end;(*stop*) procedure parser; const (*BOBS, constants generated by the generator *) symbmax = 223; prodmax = 278; lrmax = 1077; lxmax = 185; errorval = 47; nameval = 46; constval = 45; stringval = 48; stringch = ''''; combegin = 77; comlength = 2; (*BOBS) (*-end-of-generated-constants-*) realkonst = 49; skipch=' '; (*-end-of-parser-constants-*) type symbol=0..symbmax; errno=0..prodmax; prodno=0..prodmax; rslength=-1..symbmax; mode=0..6; lrinx=0..lrmax; lrelm=packed record chain: lrinx; (*next item in this state*) next: lrinx; (*next state*) case kind: mode of 1,2,4,6: (symb: symbol; err: errno); 0,3 : (rs: rslength; prod: prodno); 5: (lb: lrinx) end; lxinx=0..lxmax; lxelm=packed record np,hp: lxinx; tv: symbol; ch:char end; stackelm=packed record link: stackinx; table: lrinx end; (*-end-of-parser-types-*) var lr: arrayÆlrinxÅ of lrelm; (* lr-parse tables *) parsestack: arrayÆstackinxÅ of stackelm; (*parse stack*) entry: arrayÆcharÅ of lxelm; lx: arrayÆlxinxÅ of lxelm; (*lexical tables*) namech, (*chars used in names*) digitch:set of char; (*chars used for digits*) newsymb: symbol; (*current terminal symbol*) ch: char; (*current char*) stringescape: integer; (*internal value of the stringescape terminal*) oldbufi: chbufinx; (*first char in chbuf of current lexical token *) moreinput:boolean; (*becomes false when input is exhausted*) comend : arrayÆ1..comlengthÅ of char ; (*string which ends a comment *) prodtab : array ÆprodnoÅ of integer; (*-end-of-parser-variables-*) procedure dumplr; var i:integer; begin writeln(' i ',' chain next kind symb prod'); for i:=1 to lrmax do with lrÆiÅ do begin write(' ',i:3,chain:6,next:5,kind:5); case kind of 1,2,4,6: writeln(symb:5,err:5); 0,3 : writeln(rs:5,prod:5); 5: writeln(lb:5) end end end; (* procedures for input/output of characters*) (*$r+*) procedure readline; label 102; (* skip lines longer than 'linemax' characters *) var lgt : integer; ch : char; begin 102: lineinx:=0; lgt:=-1; printed:=false; errorinx:=0; if locallinenumber >= 0 then locallinenumber := locallinenumber + 1; linenumber:=linenumber+1; (* avoid destroying the buffer mark in case of type buffering *) if not typebufferflag then emit(cnewline, linenumber, nill, cnocode); if input^ = nl then readln(input); if eof(input) then begin if more_sources_allowed then readcall; (* more sources ??? *) if eof(input) then moreinput := false; end; ch:=' '; while (ch = ' ') and not eoln(input) do begin lgt:=lgt+1; read(ch); end; indention:=lgt; if not moreinput then ch := '.'; (* ch <> skipch *) lineÆ1Å:=ch; lgt:=2; while (not eoln(input) or (input^ = ff)) and (lgt < linemax) do (* let ff be blind *) begin read(lineÆlgtÅ); lgt:=lgt+1 end; if eoln(input) then begin lineÆlgtÅ:=' '; end else begin markerror( 102 ); (* line too long *) writeln; while not eoln(input) do get(input); (* skip line *) goto 102; (* try the next line *) end; linelength:=lgt; end; (*readline*) procedure inchar; begin if lineinx=linelength then begin if not printed and moreinput then printline; if errorinx>0 then writeln; readline; end; lineinx:=lineinx+1; ch:=lineÆlineinxÅ; if (ch>='a') and (ch <= 'z') then ch := chr(ord(ch) - ord('a') + ord('A')); (* convert to upper case *) end; (*inchar*) (*$r-*) (*end of input/output procedures*) procedure initialize(var tables : text); var cc,ch1:char; a,b,c,d,e,i:integer; firstlb : integer; newlb : boolean; begin ok := true; moreinput:=true; lineinx:=1; chbufi:=0; linelength:=1; printed:=true; errorinx:=0; parsestackÆ0Å.table:=0; attstackÆ0Å.chbufp:=chbufi; ch:=' '; parsestackÆ0Å.link:=0; digitch:=Æ'0'..'9'Å; namech:=Æ'A'..'Z','0'..'9','_'Å; readln(tables,i); (* i := number of constants to skip *) for i := i downto 1 do readln(tables); for i:=1 to comlength do read(tables,comendÆiÅ) ; readln(tables) ; for ch1:=minch to maxch do begin readln(tables,cc,cc,a,b,c); with entryÆccÅ do begin ch:=cc; np:=a; hp:=b; tv:=c end end; entryÆ'"'Å:=entryÆ''''Å; for i:=0 to lxmax do with lxÆiÅ do begin readln(tables,cc,cc,a,b,c); ch:=cc; np:=a; hp:=b; tv:=c end; if stringch=' ' then (*string facility is not used *) stringescape:=-2 else stringescape:= entryÆstringchÅ.tv; newlb:=true; for i:=0 to lrmax do with lrÆiÅ do begin read(tables,a,b,c,d); if c <> 5 then readln(tables,e) else readln(tables) ; chain:=a; next:=b; kind:=c; case c of 1,2,4,6: begin symb:=d; err:=e end; 0,3 : begin rs:=d; prod:=e end; 5 :begin lb:=d; if newlb then begin firstlb:=i; newlb:=false; end; if a=0 then begin lrÆfirstlbÅ.chain:=i; newlb:=true; end; end end end ; prodtabÆ0Å := 0; (* read the production labels *) for i := 1 to prodmax do readln(tables, a, prodtabÆaÅ); end;(*initialize*) (*$r+*) procedure lexical; (*$r-*) (* returns next terminal in newsymb*) label 999; (* after skipcomment newsymb is empty and an extra turn is needed, this is done by means of a 'goto start' *) var newi: integer; oldch: char; lxnode: lxelm; procedure skipcomment; (* read next char on input until comend is recognized *) var start_line, passnr, optnr, optvalue : integer; commentend : char; begin (* skip comment *) start_line := linenumber; (* remember current line number in case of unterminated comment *) if chbufÆ chbufi Å = '(' then commentend := ')' else commentend := '>'; if ch = '$' then (* option *) begin (* the syntax of option is: $ passnr optnr optvalue *) while not (( ch >= '0') and (ch <= '9')) do inchar; (* skip *) passnr := ord(ch) - ord('0'); repeat inchar; (* skip delimiter *) until (ch >= '0') and (ch <= '9'); optnr := 0; while (ch >= '0') and (ch <= '9') do begin if optnr < 100 then optnr := optnr * 10 + ord(ch) - ord('0'); inchar; end; (*option number *) while not ((ch >= '0') and (ch <= '9')) do inchar; (* skip delimiter *) optvalue := 0; while (ch >= '0') and (ch <= '9') and (optvalue < 100 ) do begin optvalue := optvalue * 10 + ord(ch) - ord('0'); inchar; end; if passnr = 1 then begin case optnr of 1: programlist := optvalue = 1; 2: call_pass_3 := optvalue = 1; end (* case *) otherwise ; end else begin (* emit the option *) emit(coption, passnr, optnr, cnocode); emit(cnocode, optvalue, nill, cnocode); end; end; (* option *) repeat while (ch <> '*') and moreinput do inchar; inchar; until (ch = commentend) or not moreinput; if not moreinput then begin markerror( 103 ); (* comment did not terminate *) write(output,'(* comment started in line ', start_line:1, ' *)'); end; inchar; end; (* skip comment *) (*$r+*) procedure pushch; (*$r-*) begin chbufÆchbufiÅ:=ch; if chbufi<chbufmax then chbufi:=chbufi+1 else stop(6); if testoutput then write(output,ch); (***snapshot***) end; (*pushch*) procedure readstring; var strch:char; instring : boolean; begin strch:=oldch; ch:=lineÆlineinxÅ; (* maybe ch was converted to upper case *) instring := true; while ( instring (* preceding character was not a string delimiter *) or ( ch = strch ) (* this character is a delim *) ) and ( lineinx <> linelength ) (* stop at eoln *) do begin instring := (ch <> strch) or not instring; (* false at first delim after character, else true *) if instring then pushch; lineinx := lineinx + 1; ch := lineÆlineinxÅ; (* inchar without converting to upper case *) end; if instring or (ch=strch) then markerror(101); (* string did not terminate within line *) newsymb:=stringval end; (*readstring*) begin (*lexical*) 999: if testoutput then begin writeln(output); write(output,' lexical: '); (***snapshot***) end; while ch = skipch do inchar; oldbufi:=chbufi; if not moreinput then begin if newsymb=0 then (*third*) stop(2) else if newsymb=1 then (*second*) newsymb:=0 else (*first*) newsymb:=1 end else if ch in digitch then begin (*konst*) repeat pushch; inchar; until not (ch in digitch); newsymb:=constval; if (ch='.') and (lineÆlineinx+1Å<>'.') and (line Æ lineinx + 1 Å <> ')' ) then begin (*decimal fraction*) pushch; inchar; if ch in digitch then repeat pushch; inchar; until not (ch in digitch) else markerror(100); (* error in realconstant: digit expected *) newsymb:=realkonst; end; if ch='e' then begin (*exponent*) pushch; inchar; if ch in Æ'+','-'Å then begin pushch; inchar; end; if ch in digitch then repeat pushch; inchar; until not (ch in digitch) else markerror(100); newsymb:=realkonst; end; end else (* not konst *) begin (* search in termtree *) pushch; lxnode:=entryÆchÅ; newi:=lxnode.hp; inchar; if newi <> 0 then repeat if lxÆnewiÅ.ch=ch then begin pushch; lxnode:=lxÆnewiÅ; newi:=lxnode.hp; inchar end else newi:=lxÆnewiÅ.np; until newi=0; oldch:=chbufÆchbufi-1Å; if (oldch in namech) and (ch in namech) then begin repeat pushch; inchar; until not(ch in namech); newsymb:=nameval end else if lxnode.tv > 0 then (*valid terminal*) begin if lxnode.tv=realkonst then newsymb:=nameval (* the name 'realkonst' is not a reserved word *) else begin newsymb:=lxnode.tv; chbufi:=oldbufi; if newsymb=stringescape then readstring else if newsymb=combegin then begin skipcomment ; goto 999; (* enter lexical once more *) end end end else if oldch in namech then newsymb:=nameval else markerror(0) end end; (*lexical*) procedure special_code(oldtop, newtop : stackinx; prod : integer); (* this procedure is only used for handling of open routines *) (* handling of open routines by hand ( do not use parse ) *) (* syntax: beginbody appetite : pass5code endbody code: . literal begincode . codeline( length ) ..... . . . . . . . endcode *) var stepvar : integer; function not_endbody : boolean; (* see if the next word is 'endbody', lineix is only changed if succes i.e. parsing may continue as if the routine body only consisted of : 'beginbody appetite : ' *) var step, oldindex : integer; endbody : alfa; found : boolean; (* local result *) begin found := false; while ch = skipch do inchar; oldindex := lineinx; (* remember index of first character *) if ch = 'E' then (* possibly endbody *) begin endbody := 'endbody'; step := 1; while (endbody Æ step Å = line Æ lineinx Å ) and (endbody Æ step Å <> ' ') do begin step := step + 1; lineinx := lineinx + 1; end; found := (endbody Æ step Å = ' ') and not (line Æ lineinx Å in namech); if not found then lineinx := oldindex (* reset lineinx *) else ch := line Æ lineinx Å; (* prepare return to parse *) end; (* maybe endbody *) not_endbody := not found; end; (* not_endbody *) begin (* special code *) (* just read 'beginbody appetite' *) while ch = skipch do inchar; if ch = ':' then inchar; emitcode(cbegincode); while not_endbody and moreinput do begin emit(ccodeline, linelength - lineinx, nill, cnocode); for stepvar := lineinx to linelength - 1 do emit(cnocode, ord( line Æ stepvar Å ), nill, cnocode); lineinx := linelength; (* now current line is processed *) inchar; end; (* while *) emitcode(cendcode); end; (* special code *) (*$r+*) procedure parse; const redumax= 25; (* reduction buffer size *) type reduinx= 0..redumax; reduelem= record oldtop,newtop: stackinx; prod: prodno end; var redubuf: arrayÆreduinxÅ of reduelem; (* reduction buffer *) redutop: reduinx; stacktop,pseudotop,validtop,top : stackinx; startinx,lri,start: lrinx; procedure advance; var i: integer; begin (*perform reductions*) for i:=1 to redutop do with redubufÆiÅ do begin if prodtabÆprodÅ > 0 then code(oldtop,newtop,prodtabÆprodÅ) else if prodtab Æ prod Å <> 0 then special_code(oldtop, newtop, prodtab Æ prod Å ); attstackÆnewtopÅ.chbufp:=attstackÆnewtop-1Å.chbufp end; (*update stack*) for i:=1 to stacktop-validtop do parsestackÆvalidtop+iÅ:=parsestackÆtop+iÅ; if redutop>0 then (* possible pop of chbuf *) if oldbufi=chbufi then (* newsymb notin Æname,konst,stringÅ*) chbufi:=attstackÆstacktop-1Å.chbufp else (*newsymb in Æname,konst,stringÅ*) attstackÆstacktopÅ.chbufp:=oldbufi; (*shift*) if stacktop=stackmax then stop(1); stacktop:=stacktop+1; parsestackÆstacktopÅ.table:=startinx; attstackÆstacktopÅ.chbufp:=chbufi; (* freeze new stack situation, ready for new lookahead *) top:=stacktop; pseudotop:=stacktop; validtop:=stacktop; start:=lri; redutop:=0 end; (*advance*) procedure backtrack( btop: stackinx; bstart: lrinx); begin stacktop:= btop; validtop:= btop; pseudotop:= btop; startinx:= bstart; lri:= bstart; redutop:= 0 end; (* backtrack *) procedure pseudoshift; begin if pseudotop=stackmax then stop(1); stacktop:= stacktop+1; pseudotop:= top+(stacktop-validtop); parsestackÆpseudotopÅ.table:= startinx; attstackÆpseudotopÅ.chbufp:=chbufi; end; (* pseudoshift *) function lookahead( lsymbol: symbol): boolean; label 11,12; var decided: boolean; li,si,locallri,low,high,k,locallb: lrinx; procedure queue( rs: rslength; p: prodno); begin if redutop=redumax then stop(4); redutop:= redutop+1; with redubufÆredutopÅ do begin oldtop:= stacktop; stacktop:= stacktop-rs; newtop:= stacktop; if stacktop <= validtop then begin pseudotop:= stacktop; validtop:= stacktop end else pseudotop:= pseudotop-rs; prod:=p end end; (* queue *) begin decided:= false; locallri:=lri; repeat startinx:= locallri; case lrÆlocallriÅ.kind of 0: begin decided:= true; lookahead:= true; ok:= false end; 1: begin while lrÆlocallriÅ.symb<>lsymbol do begin li:= lrÆlocallriÅ.chain; if li=0 then goto 11; (* exit loop *) locallri:= li end; 11: decided:= true; lookahead:= lrÆlocallriÅ.symb=lsymbol end; 2,4,6: begin while lrÆlocallriÅ.symb<>lsymbol do begin li:= lrÆlocallriÅ.chain; if li=0 then goto 12; (* exit loop *) locallri:= li end; 12: if lrÆlocallriÅ.kind= 2 then begin decided:= true; lookahead:= true end else if lrÆlocallriÅ.kind= 6 then begin pseudoshift; stacktop:=stacktop-1; pseudotop:=pseudotop-1; queue(-1,lrÆlocallriÅ.err) end end; 3: begin queue(lrÆlocallriÅ.rs,lrÆlocallriÅ.prod) end; 5: begin si:= parsestackÆpseudotopÅ.table; low:=locallri; locallri:=lrÆlocallriÅ.chain; high:=locallri-1; while low < high do begin k:=(low+high) div 2; locallb:=lrÆkÅ.lb; if locallb > si then high:=k-1 else if locallb < si then low:=k+1 else begin high:=k; low:=high; end; end; k:=(low+high+1) div 2; if lrÆkÅ.lb = si then locallri:=k; end end; (* case *) locallri:= lrÆlocallriÅ.next; until decided; lri:=locallri; end; (* lookahead *) procedure syntaxerror; var success: boolean; s,s1: stackinx; begin if testoutput then write(output,' <---syntaxerror'); (***snapshot***) markerror(lrÆstartinxÅ.err); backtrack(top,start); pseudoshift; s:= 0; for s1:= 0 to top do begin backtrack( top, start ) ; (* 80.03.21 *) pseudoshift; backtrack(s1,parsestackÆs1+1Å.table); if lookahead(errorval) then begin parsestackÆs1Å.link:= s; s:= s1 end end; success:= false; repeat s1:= s; repeat backtrack( top, start ); (* 80.03.21 *) pseudoshift; backtrack(s1,parsestackÆs1+1Å.table); if lookahead(errorval) then begin pseudoshift; success:= lookahead(newsymb) end; s1:= parsestackÆs1Å.link; until (s1=0) or success; if not success then begin (* mark previous symbol skipped *) if testoutput then write(output,' <---skipped'); (***snapshot***) lexical end; until success or (not ok); if not ok then stop(3) end; (* syntaxerror *) begin (* parse *) top:=0; start:=1; backtrack(top,start); while ok do begin lexical; if not lookahead(newsymb) then syntaxerror; advance; end; end; (*parse*) (*$r-*) begin (* parser *) open(input,'platontable'); reset(input); initialize(input); close(input); parse; end; (*parser*) begin initialize; readcall; parser; 10: if inputfile then close(input); close(codefile); close(symbfile); close(spixtable); if errorcount > 0 then printerrors else begin if (warningcount > 0) and (errorcount = 0) then (* no errors but warnings *) printerrors; if call_pass_3 then replace('platonpass3'); end; writeln('*** compilation terminated after pass1 '); end. (*BOBS*) ▶EOF◀