home *** CD-ROM | disk | FTP | other *** search
- #symbolic constants greater than 10000 have been changed to
- #negative numbers which fit in bytes. If they are enclosed in
- #parentheses in relational expressions, they should be accepted by all FORTRAN.
- define(alpha,-100)
- define(amper,38) #ampersand
- define(arb,100)
- define(atsign,64)
- define(backslash,92)
- define(backspace,8)
- define(bang,33)#exclamation point
- define(bar,124)#synonym for .or.
- define(biga,65)
- define(bigb,66)
- define(bigc,67)
- define(bigd,68)
- define(bige,69)
- define(bigf,70)
- define(bigg,71)
- define(bigh,72)
- define(bigi,73)
- define(bigj,74)
- define(bigk,75)
- define(bigl,76)
- define(bigm,77)
- define(bign,78)
- define(bigo,79)
- define(bigp,80)
- define(bigq,81)
- define(bigr,82)
- define(bigs,83)
- define(bigt,84)
- define(bigu,85)
- define(bigv,86)
- define(bigw,87)
- define(bigx,88)
- define(bigy,89)
- define(bigz,90)
- define(blank,32)
- define(bufsize,300)#pushback buffer for ngetch, putbak
- define(caret,94)#alternate not, converted to !
- define(colon,58)
- define(comma,44)
- define(deftype,-10)
- define(dig0,48)
- define(dig1,49)
- define(dig2,50)
- define(dig3,51)
- define(dig4,52)
- define(dig5,53)
- define(dig6,54)
- define(dig7,55)
- define(dig8,56)
- define(dig9,57)
- define(digit,2)
- define(dollar,36)
- define(dquote,34)
- define(eof,-3)
- define(eos,-2)
- define(equals,61)
- #define(err,-1) not used, conflicts with err=
- define(kons,3)
- define(errout,kons)#error message to console
- define(greater,62)
- define(kb,3)
- define(lbrace,123)
- define(lbrack,91)
- define(less,60)
- define(leta,97)
- define(letb,98)
- define(letc,99)
- define(letd,100)
- define(lete,101)
- define(letf,102)
- define(letg,103)
- define(leth,104)
- define(leti,105)
- define(letj,106)
- define(letk,107)
- define(letl,108)
- define(letm,109)
- define(letn,110)
- define(leto,111)
- define(letp,112)
- define(letq,113)
- define(letr,114)
- define(lets,115)
- define(lett,116)
- define(letter,1)
- define(letu,117)
- define(letv,118)
- define(letw,119)
- define(letx,120)
- define(lety,121)
- define(letz,122)
- define(lexbreak,-64)
- define(lexdigits,-60)
- define(lexdo,-66)
- define(lexelse,-62)
- define(lexfor,-68)
- define(lexif,-61)
- define(lexnext,-65)
- define(lexother,-67)
- define(lexrepeat,-69)
- define(lexuntil,-70)
- define(lexwhile,-63)
- define(lparen,40)
- define(maxcard,80)#input record size
- define(maxchars,10)#chars in ascii integer incl - and eos
- define(maxdef,200)#max chars in defn
- define(maxforstk,200)#space for reinit clauses
- define(maxline,81)#maxcard+1
- define(maxname,30)#include file name length
- define(maxptr,200)#number of defines
- define(maxstack,100)#parser stack depth
- define(maxtbl,1500)#size of definition table
- define(maxtok,200)#token size
- define(minus,45)
- #define(nchars,33)
- define(newline,10)#lf
- define(nfiles,5)#max open files
- define(no,.false.)
- define(not,bang)#use !
- define(percent,37)
- define(period,46)
- define(plus,43)
- define(qmark,63)
- define(rbrace,125)
- define(rbrack,93)
- #define(readonly,0)#not used by Microsoft
- define(rparen,41)
- define(semicol,59)
- define(sharp,35)
- define(slash,47)
- define(squote,39)
- define(star,42)
- define(stdin,7)#input unit
- define(stdout,6)
- define(tab,9)
- define(tilde,126)
- define(underline,95)
- define(yes,.true.)
- define(character,byte)
- define(abs,iabs)
- program ratfor#main program
- character name(8),namer(11),namef(11)
- data namer(9),namer(10),namer(11)/'R','A','T'/
- data namef(9),namef(10),namef(11)/'F','O','R'/
- 9 format('Addison-Wesley Ratfor adapted for FORTRAN-80 August',
- '1979 by Tim Prince, 1 EastLakeView Apt 17, Cincinnati 45237')
- write(kons,1,err=3)
- 1 format(1x,'Input file name ?')
- 3 read(kb,2,err=4)name
- 2 format(8a1)
- 4 do i=1,8
- {namer(i)=name(i);namef(i)=name(i)}
- call open(stdin,namer,0)
- call open(stdout,namef,0)
- call parse
- endfile stdout
- stop
- end
- block data initl
- include RATCOMNS
- data outp/0/#output character pointer
- #file control
- data level/1/,linect(1)/1/,infile(1)/stdin/
- data bp/0/#pushback buffer pointer
- data fordep/0/#for stack depth
- #table lookup pointers
- data lastp/0/,lastt/0/
- #keywords:
- data sdo/letd,leto,eos/,vdo/lexdo,eos/
- data sif/leti,letf,eos/,vif/lexif,eos/
- data selse/lete,letl,lets,lete,eos/
- data velse/lexelse,eos/
- data swhile/letw,leth,leti,letl,lete,eos/
- data vwhile/lexwhile,eos/
- data sbreak/letb,letr,lete,leta,letk,eos/
- data vbreak/lexbreak,eos/
- data snext/letn,lete,letx,lett,eos/
- data vnext/lexnext,eos/
- data sfor/letf,leto,letr,eos/,vfor/lexfor,eos/
- data srept/letr,lete,letp,lete,leta,lett,eos/
- data vrept/lexrepeat,eos/
- data suntil/letu,letn,lett,leti,letl,eos/
- data vuntil/lexuntil,eos/
- #if a transliteration table is required, insert it here
- end
- logical function alldig(str)#yes if str is all digits
- #called by lex
- character type,str(arb)
- alldig=no
- if(str(1)==eos)return
- for(i=1;str(i)!=eos;i=i+1)if(type(str(i))!=digit)return
- alldig=yes
- return
- end
- subroutine balpar #copy balanced paren string
- #called by ifgo
- character gettok,t,token(maxtok)
- integer*1 nlpar
- if(gettok(token,maxtok)!=lparen)
- {call synerr("missing left paren.")
- return}
- call outstr(token)
- nlpar=1
- repeat{
- t=gettok(token,maxtok)
- if(t==semicol | t==lbrace | t==rbrace | t==eof)
- {call pbstr(token)
- break}
- if(t==newline)token(1)=eos # delete lf
- else if (t==lparen)nlpar=nlpar+1
- else if (t==rparen)nlpar=nlpar-1
- call outstr(token)
- }until(nlpar<=0)
- if(nlpar!=0)call synerr("missing parenthesis in condition.")
- return
- end
- subroutine brknxt(sp,lextyp,labval,token)#break & next
- #called by parse
- integer i,labval(maxstack),sp
- character lextyp(maxstack),token
- for(i=sp;i>0;i=i-1)
- if(lextyp(i)==lexwhile | lextyp(i)==lexdo
- | lextyp(i)==lexfor | lextyp(i)==lexrepeat)
- {labout=labval(i)
- if(token==lexbreak)labout=labout+1
- call outgo(labout)
- return}
- if(token==lexbreak)call synerr("illegal break.")
- else call synerr("illegal next.")
- return
- end
- subroutine closei(fd)#file close
- #called by gettok
- integer fd
- endfile fd
- return
- end
- character function deftok(token,toksiz,fd)
- #called by gettok
- integer fd,toksiz
- character gtok,defn(maxdef),t,token(toksiz)
- logical lookup
- for(t=gtok(token,toksiz,fd);t!=eof;t=gtok(token,toksiz,fd))
- {if(t!=alpha)break #non-alpha
- if(! lookup(token,defn))break #undefined
- if(defn(1)==deftype) #get definition
- {call getdef(token,toksiz,defn,maxdef,fd)
- call instal(token,defn)}
- else call pbstr(defn)} #push replacement onto input
- deftok=t
- if(deftok==alpha) call fold(token) #convert to lower case
- return
- end
- subroutine fold(token)
- #called by deftok
- character token(arb)
- # internal numeric equivalence of letters must be sequential
- # within each case.
- integer*1 lwrmup
- lwrmup=leta-biga
- for(i=1;token(i)!=eos;i=i+1)
- if(token(i)>=biga & token(i)<=bigz)
- token(i)=token(i)+lwrmup
- return
- end
- subroutine docode(lab) #generate do
- #called by parse
- character dostr(4)
- data dostr/letd,leto,blank,eos/
- call outtab
- call outstr(dostr)
- lab=labgen(2)
- call outnum(lab)
- call eatup
- call outdon
- return
- end
- subroutine dostat(lab) #generate end do
- #called by unstak
- call outcon(lab)
- call outcon(lab+1)
- return
- end
- subroutine eatup #proc rest of statement incl continuations
- #called by docode,forcod,otherc
- character gettok,ptoken(maxtok),t,token(maxtok)
- integer*1 nlpar
- nlpar=0
- repeat{
- t=gettok(token,maxtok)
- if(t==semicol | t==newline)break
- if(t==rbrace){call pbstr(token);break}
- if(t==lbrace | t==eof){
- call synerr("unexpected brace or eof.")
- call pbstr(token)
- break}
- if(t==comma | t==underline){
- if(gettok(ptoken,maxtok)!=newline)call pbstr(ptoken)
- if(t==underline)token(1)=eos}
- else if(t==lparen)nlpar=nlpar+1
- else if(t==rparen)nlpar=nlpar-1
- call outstr(token)
- }until(nlpar<0)
- if(nlpar!=0)call synerr("unbalanced parentheses.")
- return
- end
- subroutine elseif(lab) #generate else code
- #called by parse
- call outgo(lab+1)
- call outcon(lab)
- return
- end
- logical function equal(str1,str2) #? strings equal
- #called by gettok,lex
- character str1(arb),str2(arb)
- for(i=1;str1(i)==str2(i);i=i+1)
- if(str1(i)==eos){equal=yes;return}
- equal=no
- return
- end
- subroutine error(buf)#fatal error msg; die
- #called by getdef,parse,putbak
- character buf(arb)
- call remark(buf)
- endfile stdout
- stop
- end
- subroutine forcod(lab)#begin for
- #called by parse
- character gettok,t,token(maxtok),ifnot(9)
- integer*1 i,nlpar
- include RATCOMNS
- data ifnot/leti,letf,lparen,period,letn,leto,lett,period,eos/
- lab=labgen(3)
- call outcon(0)
- if(gettok(token,maxtok)!=lparen){
- call synerr("missing left paren.")
- return}
- if(gettok(token,maxtok)!=semicol)#real init clause
- {call pbstr(token)
- call outtab
- call eatup
- call outdon}
- if(gettok(token,maxtok)==semicol)#empty condition
- call outcon(lab)
- else{ #non-empty condition
- call pbstr(token)
- call outnum(lab)
- call outtab
- call outstr(ifnot)
- call outch(lparen)
- nlpar=0
- while(nlpar>=0){
- t=gettok(token,maxtok)
- if(t==semicol)break
- if(t==lparen)nlpar=nlpar+1
- else if(t==rparen)nlpar=nlpar-1
- if(t!=newline & t!=underline)call outstr(token)}
- call outch(rparen)
- call outch(rparen)
- call outgo(lab+2)
- if(nlpar<0)call synerr("invalid for clause.")}
- fordep=fordep+1 #stack reinit clause
- j=1
- for(i=1;i<fordep;i=i+1)#find end
- j=j+length(forstk(j))+1
- forstk(j)=eos #null, in case no reinit
- nlpar=0
- while(nlpar>=0){
- t=gettok(token,maxtok)
- if(t==lparen)nlpar=nlpar+1
- else if(t==rparen)nlpar=nlpar-1
- if(nlpar>=0 & t!=newline & t!=underline){
- call scopy(token,1,forstk,j)
- j=j+length(token)}}
- lab=lab+1 #label for NEXTs
- return
- end
- subroutine fors(lab)#process end of for
- #called by unstak
- integer*1 i
- include RATCOMNS
- call outnum(lab)
- j=1
- for(i=1;i<fordep;i=i+1)
- j=j+length(forstk(j))+1
- if(length(forstk(j))>0){
- call outtab
- call outstr(forstk(j))
- call outdon}
- call outgo(lab-1)
- call outcon(lab+1)
- fordep=fordep-1
- return
- end
- character function getch(c,f)#get character from file
- #called by ngetch
- character buf(maxline),c
- integer f
- data lastc/maxline/,buf(maxline)/newline/
- #note: maxline=maxcard+1
- if(buf(lastc)==newline | lastc>=maxline){
- read(f,1,err=5,end=10)(buf(i),i=1,maxcard)
- 1 format(maxcard a1)#use r1 format if available
- #now transliterate into ascii and shift right if needed
- for(i=maxcard;i>0;i=i-1)
- if(buf(i)!=blank)break
- buf(i+1)=newline
- go to 7
- 5 buf(1)=qmark
- buf(2)=newline
- 7 if(buf(1)==newline)lastc=1
- else lastc=0
- }#Microsoft leaves newline in front; skip it
- lastc=lastc+1
- c=buf(lastc)
- getch=c
- return
- 10 c=eof
- getch=eof
- return
- end
- subroutine getdef(token,toksiz,defn,defsiz,fd)
- #called by deftok
- integer defsiz,fd,toksiz
- character gtok,ngetch,c,defn(defsiz),token(toksiz)
- integer*1 nlpar
- if(ngetch(c,fd)!=lparen)call remark("missing left paren.")
- if(gtok(token,toksiz,fd)!=alpha)
- call remark("non-alphanumeric name.")
- else if(ngetch(c,fd)!=comma)
- call remark("missing comma in define.")
- nlpar=0
- for(i=1;nlpar>=0;i=i+1)
- if(i>defsiz)call error("definition too long.")
- else if(ngetch(defn(i),fd)==eof)
- call error("missing right paren.")
- else if(defn(i)==lparen)nlpar=nlpar+1
- else if(defn(i)==rparen)nlpar=nlpar-1
- defn(i-1)=eos
- return
- end
- character function gettok(token,toksiz)
- #called by balpar,eatup,forcod,lex
- logical equal
- integer openi,toksiz
- character junk
- character deftok,name(maxname),token(toksiz),incl(8)
- include RATCOMNS
- data incl/leti,letn,letc,letl,letu,letd,lete,eos/
- for(;level>0;level=level-1){
- for(gettok=deftok(token,toksiz,infile(level));gettok!=eof;
- gettok=deftok(token,toksiz,infile(level))){
- if(! equal(token,incl))return
- junk=deftok(name,maxname,infile(level))
- if(level>=nfiles)
- call synerr("includes nested too deeply.")
- else{
- infile(level+1)=openi(name,level+1)
- linect(level+1)=1
- #open error not flagged by FORT-80;must change name anyway
- # if(infile(level+1)==err)
- # call synerr("can't open include.")
- # else
- level=level+1}}
- if(level>1)call closei(infile(level))}
- gettok=eof
- return
- end
- character function gtok(lexstr,toksiz,fd)
- #called by deftok,getdef
- integer toksiz,fd
- character ngetch,type,c,lexstr(toksiz)
- include RATCOMNS
- while(ngetch(c,fd)!=eof)if(c!=blank&c!=tab)break
- call putbak(c)
- for(i=1;i<toksiz-1;i=i+1){
- gtok=type(ngetch(lexstr(i),fd))
- if(gtok!=letter>ok!=digit)break}
- if(i>=toksiz-1)call synerr("token too long.")
- if(i>1){ #some alpha seen
- call putbak(lexstr(i))#insert eos before lexstr(i)
- lexstr(i)=eos
- gtok=alpha}
- else if(lexstr(1)==dollar){#process $( & $)
- if(ngetch(lexstr(2),fd)==lparen){
- lexstr(1)=lbrace
- gtok=lbrace}
- else if(lexstr(2)==rparen){
- lexstr(1)=rbrace
- gtok=rbrace}
- else call putbak(lexstr(2))}
- else if(lexstr(1)==squote | lexstr(1)==dquote){
- for(i=2;ngetch(lexstr(i),fd)!=lexstr(1);i=i+1)
- if(lexstr(i)==newline | i>=toksiz-1){
- call synerr("missing quote.")
- lexstr(i)=lexstr(1)
- call putbak(newline)
- break}}
- else if(lexstr(1)==sharp){ #strip comment
- while(ngetch(lexstr(1),fd)!=newline);
- gtok=newline}
- else{
- if(lexstr(1)==tilde | lexstr(1)==caret)lexstr(1)=not
- if(lexstr(1)==greater|lexstr(1)==less|lexstr(1)==not
- |lexstr(1)==equals|lexstr(1)==amper|lexstr(1)==bar)
- call relate(lexstr,i,fd)}
- lexstr(i+1)=eos
- if(lexstr(1)==newline)linect(level)=linect(level)+1
- return
- end
- subroutine ifcode(lab)#initial if code
- #called by parse
- lab=labgen(2)
- call ifgo(lab)
- return
- end
- subroutine ifgo(lab)
- #called by ifcode,unstak,whilec
- character ifnot(9)
- data ifnot/leti,letf,lparen,period,letn,leto,lett,period,eos/
- call outtab #get to column 7
- call outstr(ifnot)
- call balpar #collect & output condition
- call outch(rparen)
- call outgo(lab) #"goto lab"
- return
- end
- subroutine initkw #install "define" in definition table
- #called by parse
- #note "define"must be all lower case unless further provided.
- character defnam(7),deftyp(2)
- data defnam/letd,lete,letf,leti,letn,lete,eos/
- data deftyp/deftype,eos/
- call instal(defnam,deftyp)
- return
- end
- subroutine instal(name,defn)#add to definition table
- #called by deftok,initkw
- character defn(maxtok),name(maxdef)
- integer dlen
- include RATCOMNS
- nlen=length(name)+1
- dlen=length(defn)+1
- if(lastt+nlen+dlen>maxtbl | lastp>=maxptr){
- call putlin(name,errout)
- call remark(": too many definitions.")}
- lastp=lastp+1
- namptr(lastp)=lastt+1
- call scopy(name,1,table,lastt+1)
- call scopy(defn,1,table,lastt+nlen+1)
- lastt=lastt+nlen+dlen
- return
- end
- function itoc(int,str,size)#convert int to str
- #called by outnum,synerr
- integer size
- character k,str(size)
- intval=abs(int)
- str(1)=eos
- i=1
- repeat{
- i=i+1
- str(i)=mod(intval,10)+dig0
- intval=intval/10
- }until(intval==0 | i>=size)
- if(int<0 & i<size){ #check sign
- i=i+1
- str(i)=minus}
- itoc=i-1
- for(j=1;j<i;j=j+1) #reverse
- {k=str(i)
- str(i)=str(j)
- str(j)=k
- i=i-1}
- return
- end
- subroutine labelc(lexstr)#output label
- #called by parse
- character lexstr(arb)
- if(length(lexstr)==5) #warn about 23xxx labels
- if(lexstr(1)==dig2 & lexstr(2)==dig3)
- call synerr("warning: possible label conflict.")
- call outstr(lexstr)
- call outtab
- return
- end
- function labgen(n)#generate n labels, return first one
- #called by docode,forcod,ifcode,repcod,whilec
- data label/23000/
- labgen=label
- label=label+n
- return
- end
- function length(str)
- #called by fors,labelc,pbstr
- character str(arb)
- for(length=0;str(length+1)!=eos;length=length+1);
- return
- end
- character function lex(lexstr)
- #called by parse,unstak
- character gettok,lexstr(maxtok)
- logical alldig,equal
- include RATCOMNS
- while(gettok(lexstr,maxtok)==newline);
- lex=lexstr(1)
- if(lex==eof | lex==semicol | lex==lbrace | lex==rbrace)return
- if(alldig(lexstr))lex=lexdigits
- else if(equal(lexstr,sif))lex=vif(1)
- else if(equal(lexstr,selse))lex=velse(1)
- else if(equal(lexstr,swhile))lex=vwhile(1)
- else if(equal(lexstr,sdo))lex=vdo(1)
- else if(equal(lexstr,sbreak))lex=vbreak(1)
- else if(equal(lexstr,snext))lex=vnext(1)
- else if(equal(lexstr,sfor))lex=vfor(1)
- else if(equal(lexstr,srept))lex=vrept(1)
- else if(equal(lexstr,suntil))lex=vuntil(1)
- else lex=lexother
- return
- end
- logical function lookup(name,defn)
- #called by deftok
- character defn(maxdef),name(maxtok)
- include RATCOMNS
- for(i=lastp;i>0;i=i-1) #note last defn checked first
- {j=namptr(i)
- for(k=1;name(k)==table(j)&name(k)!=eos;k=k+1)
- j=j+1
- if(name(k)==table(j)){ #found defn
- call scopy(table,j+1,defn,1)
- lookup=yes
- return}}
- lookup=no
- return
- end
- character function ngetch(c,fd)#get char (possibly pushed back)
- #called by getdef,gtok,type,relate
- character getch,c
- integer fd
- include RATCOMNS
- if(bp>0)c=buf(bp)
- else{bp=1;buf(1)=getch(c,fd)}
- bp=bp-1
- ngetch=c
- return
- end
- integer function openi(name,level)
- #called by gettok
- character name(maxname),namer(11)
- data namer(9),namer(10),namer(11)/'R','A','T'/
- openi=level+6#use units 8,9,10 according to include level
- for(i=1;i<=8&name(i)!=eos;i=i+1)
- {if(name(i)>underline)name(i)=name(i)-blank
- namer(i)=name(i)} #strip lc bit
- if(name(i)!=eos)i=i+1 #don't blank unless eos
- while(i<=8){namer(i)=blank;i=i+1}
- call open(openi,namer,0)#current disk
- return
- end
- subroutine otherc(lexstr)#put out ordinary FORTRAN
- #called by parse
- character lexstr(arb)
- call outtab
- call outstr(lexstr)
- call eatup
- call outdon
- return
- end
- subroutine outch(c)#output by characters
- #called by forcod,ifgo,outnum,outstr,outtab
- character c
- include RATCOMNS
- if(outp>=72){#make continuation card
- call outdon
- do i=1,5
- outbuf(i)=blank
- outbuf(6)=amper#ampersand in col 6 (may want *)
- outp=6}
- outp=outp+1
- outbuf(outp)=c
- return
- end
- subroutine outcon(n)#put out "n continue"
- #called by dostat,elseif,forcod,fors,repcod,unstak,whilec,whiles
- character contin(9)
- data contin/letc,leto,letn,lett,leti,letn,letu,lete,eos/
- if(n>0)call outnum(n)
- call outtab
- call outstr(contin)
- call outdon
- return
- end
- subroutine outdon #terminate output line
- #called by docode,forcod,fors,otherc,outch,outcon,outgo
- include RATCOMNS
- outbuf(outp+1)=newline
- outbuf(outp+2)=eos
- call putlin(outbuf,stdout)
- outp=0
- return
- end
- subroutine outgo(n)#put out "goto n"
- #called by brknxt,elseif,forcod,fors,ifgo,unstak,whiles
- character goto(6)
- data goto/letg,leto,lett,leto,blank,eos/
- call outtab
- call outstr(goto)
- call outnum(n)
- call outdon
- return
- end
- subroutine outnum(n)#put out decimal number
- #called by docode,forcod,fors,outcon,outgo,outstr,whilec
- character chars(maxchars)
- len=itoc(n,chars,maxchars)
- do i=1,len
- call outch(chars(i))
- return
- end
- subroutine outstr(str)#put out string
- #called by balpar,docode,eatup,forcod,fors,ifgo,labelc,otherc,
- #outcon,outgo
- character c,str(arb)
- for(i=1;str(i)!=eos;i=i+1){
- c=str(i)
- if(c!=squote & c!=dquote)call outch(c)
- else{
- i=i+1
- for(j=i;str(j)!=c;j=j+1);#count Hollerith string
- call outnum(j-i)
- call outch(leth)
- for(;i<j;i=i+1)call outch(str(i))}}
- return
- end
- subroutine outtab#tab to column 7
- #called by docode,forcod,fors,ifgo,labelc,otherc,outcon,outgo
- include RATCOMNS
- while(outp<6)call outch(blank)
- return
- end
- subroutine parse#parse ratfor source
- #called by ratfor
- character lexstr(maxtok),lex,lextyp(maxstack),token
- integer labval(maxstack),sp
- call initkw #install initial definitions
- sp=1
- lextyp(1)=eof
- for(token=lex(lexstr);token!=eof;token=lex(lexstr)){
- if(token==lexif)call ifcode(lab)
- else if(token==lexdo)call docode(lab)
- else if(token==lexwhile)call whilec(lab)
- else if(token==lexfor)call forcod(lab)
- else if(token==lexrepeat)call repcod(lab)
- else if(token==lexdigits)call labelc(lexstr)
- else if(token==lexelse){
- if(lextyp(sp)==lexif)call elseif(labval(sp))
- else call synerr("illegal else.")}
- if(token==lexif | token==lexelse | token==lexwhile
- | token==lexfor | token==lexrepeat
- | token==lexdo | token==lexdigits | token==lbrace){
- sp=sp+1 #begin statement
- if(sp>maxstack)call error("stack overflow in parser.")
- lextyp(sp)=token #stack type and value
- labval(sp)=lab}
- else{ #end of statement - prepare to unstack
- if(token==rbrace){
- if(lextyp(sp)==lbrace)sp=sp-1
- else call synerr("illegal right brace.")}
- else if(token==lexother)call otherc(lexstr)
- else if(token==lexbreak | token==lexnext)
- call brknxt(sp,lextyp,labval,token)
- token=lex(lexstr) #peek at next token
- call pbstr(lexstr)
- call unstak(sp,lextyp,labval,token)}}
- if(sp!=1)call synerr("unexpected eof.")
- return
- end
- subroutine pbstr(in)#push string back on input
- #called by balpar,deftok,eatup,forcod,parse
- character in(arb)
- for(i=length(in);i>0;i=i-1)call putbak(in(i))
- return
- end
- subroutine putbak(c)#push character back on input
- #called by gtok,pbstr,relate
- character c
- include RATCOMNS
- bp=bp+1
- if(bp>bufsize)call error("too many characters pushed back.")
- buf(bp)=c
- return
- end
- subroutine putch(c,f)
- #called by putlin,synerr
- character buf(maxline),c,c1,q1
- integer f
- data c1/'C'/,q1/'?'/
- data lastc/0/
- if(lastc>=maxline | c==newline){
- if(lastc>0){
- write(f,1,err=5)(buf(i),i=1,lastc)
- goto 4
- 5 write(errout,1)c1,q1
- 4 continue
- 1 format(1x,maxcard a1)}# r1 where appropriate
- lastc=0}
- if(c!=newline){lastc=lastc+1
- c=c&127 #strip sign
- if(c<27)c=c+33 #map bomb chars into visible zone
- buf(lastc)=c}
- return
- end
- subroutine putlin(b,f)#put out line via putch
- #called by instal,outdon,synerr
- character b(arb)
- integer f
- for(i=1;b(i)!=eos;i=i+1)call putch(b(i),f)
- return
- end
- subroutine relate(token,last,fd)
- #called by gtok
- #called by error,getdef,instal,synerr
- character ngetch,token(arb),dotge(5),dotgt(5),dotle(5),
- dotne(5),dotnot(6),doteq(5),dotand(6),dotor(5),dotlt(5)
- integer fd
- data dotge/period,letg,lete,period,eos/,
- dotgt/period,letg,lett,period,eos/,
- dotle/period,letl,lete,period,eos/,
- dotlt/period,letl,lett,period,eos/,
- dotne/period,letn,lete,period,eos/,
- doteq/period,lete,letq,period,eos/,
- dotor/period,leto,letr,period,eos/,
- dotand/period,leta,letn,letd,period,eos/,
- dotnot/period,letn,leto,lett,period,eos/
- if(ngetch(token(2),fd)!=equals)call putbak(token(2))
- if(token(1)==greater){
- if(token(2)==equals)call scopy(dotge,1,token,1)
- else call scopy(dotgt,1,token,1)}
- else if(token(1)==less){
- if(token(2)==equals)call scopy(dotle,1,token,1)
- else call scopy(dotlt,1,token,1)}
- else if(token(1)==not){
- if(token(2)==equals)call scopy(dotne,1,token,1)
- else call scopy(dotnot,1,token,1)}
- else if(token(1)==equals){
- if(token(2)==equals)call scopy(doteq,1,token,1)
- else token(2)=eos}
- else if(token(1)==amper)call scopy(dotand,1,token,1)
- else if(token(1)==bar)call scopy(dotor,1,token,1)
- else token(2)=eos#not recognized
- last=length(token)
- return
- end
- subroutine remark(buf)#warning message
- #called by error,getdef,instal,synerr
- character buf(arb),pct
- data pct/'%'/
- for(j=1;j<63&buf(j)!=period;j=j+1){
- buf(j)=buf(j)&127
- if(buf(j)<27)buf(j)=buf(j)+33}
- write(errout,10,err=5)(buf(i),i=1,j)
- 10 format(1x,63a1)
- return
- 5 write(errout,10)pct
- return
- end
- subroutine repcod(lab)#begin repeat
- #called by parse
- call outcon(0)#in case there was a label
- lab=labgen(3)
- call outcon(lab)
- lab=lab+1 #label for NEXTs
- return
- end
- subroutine scopy(from,i,to,j)
- #called by forcod,instal,lookup,relate
- character from(arb),to(arb)
- k2=j
- for(k1=i;from(k1)!=eos;k1=k1+1){
- to(k2)=from(k1)
- k2=k2+1}
- to(k2)=eos
- return
- end
- subroutine synerr(msg)#report syntax error
- #called by balpar,brknxt,eatup,forcod,gettok,gtok,labelc,parse
- character lc(maxline),msg(maxline)
- include RATCOMNS
- call remark("error at line.")
- do i=1,level
- {call putch(blank,errout)
- junk=itoc(linect(i),lc,maxline)
- call putlin(lc,errout)}
- call putch(colon,errout)
- call putch(newline,errout)
- call remark(msg)
- return
- end
- character function type(c)#based on ascii
- #called by alldig,gtok
- character c
- if(c>=dig0 & c<=dig9)type=digit
- else if((c>=leta & c<=letz)|(c>=biga&c<=bigz))type=letter
- else type=c
- return
- end
- subroutine unstak(sp,lextyp,labval,token)#at statement end
- #called by parse
- integer labval(maxstack),sp
- character lextyp(maxstack),token
- for(;sp>1;sp=sp-1){
- if(lextyp(sp)==lbrace|(lextyp(sp)==lexif&token==lexelse))
- break
- if(lextyp(sp)==lexif)call outcon(labval(sp))
- else if(lextyp(sp)==lexelse){
- if(sp>2)sp=sp-1
- call outcon(labval(sp)+1)}
- else if(lextyp(sp)==lexdo)call dostat(labval(sp))
- else if(lextyp(sp)==lexwhile)call whiles(labval(sp))
- else if(lextyp(sp)==lexfor)call fors(labval(sp))
- else if(lextyp(sp)==lexrepeat)call untils(labval(sp),token)}
- return
- end
- subroutine untils(lab,token)#generate end of repeat
- #called by unstak
- character ptoken(maxtok),token,junk,lex
- call outnum(lab)
- if(token==lexuntil){
- junk=lex(ptoken)
- call ifgo(lab-1)}
- else call outgo(lab-1)
- call outcon(lab+1)
- return
- end
- subroutine whilec(lab)#begin while
- #called by parse
- call outcon(0) #in case there was a label
- lab=labgen(2)
- call outnum(lab)
- call ifgo(lab+1)
- return
- end
- subroutine whiles(lab)#end of while
- #called by unstak
- call outgo(lab)
- call outcon(lab+1)
- return
- end
-