begin; !takeon: convert imp grammar 31/1/77 constinteger gra=1, old=2; !in streams constinteger err=0, new=1, glist=2, dlist=3; !out streams constinteger first phrase = 200 constinteger ident=90 owninteger charmax=0, nmax=-1, inits=0 owninteger newname=0, outstring=-1 integer sym,count,gmin,gmax,kmax byteintegerarray char(1:1400) ownbyteintegerarray tran(0:255) integerarray index(0:255) integerarray item,next(-1:800), atomic(130:179), phrase(200:255) integerarray initial,initnext(0:255) integerarray keydict(32:1023) routine hwrite(integer n, m) n = n!x'FFFF0000' if n&x'8000' # 0 write(n, m) end routine read sym cycle read symbol(sym) until sym # ' ' return if sym # '&' or nextsymbol # nl skipsymbol repeat end routine print chars(integer p) integer flag flag = outstring if p # 0 start while char(p) # 0 and flag # 0 cycle flag = flag-1 printsymbol(char(p)&127) p = p+1 repeat finish end routine print name(integer n) print chars(index(n&255)) while n&x'300' # 0 cycle print symbol('<'); n = n-256 repeat if outstring < 0 start printsymbol('"') if (n&x'800' # 0 or tran(n&255) # 0) n = n>>16 if n # 0 start printsymbol('['); hwrite(n, 0); printsymbol(']') finish finish end routine read name(integername n) integer i,j,k,m i = charmax cycle i = i+1; char(i) = sym read symbol(sym) exit unless 'A'<=sym<='Z' or '0'<=sym<='9' repeat i = i+1; char(i) = 0 read sym if sym = ' ' m = nmax while m >= 0 cycle j = index(m); k = charmax+1 while j # 0 and char(j)&127 = char(k) cycle ->ok if char(k) = 0 j = j+1; k = k+1 repeat m = m-1 repeat ok: if newname # 0 start if m >= 0 start printstring("DUPLICATE: ") print chars(charmax+1) newline finish index(n) = charmax+1; charmax = i tran(n) = 1 and read sym if sym = '"' nmax = n if nmax < n else if m < 0 start printstring("UNKNOWN: ") print chars(charmax+1) newline m = 0 finish n = m finish end routine read grammar integer i,j,k,l,p,min,max,exp,end integerarray converted(-200:350), head,tail(-200:-1), token,link(1:350) integerarray map(0:800) integerfn cell(integer h,t) !creates a list cell, if necessary, with head h and tail t integer i i = t; i = 0 if i > 0 while i # min cycle i = i-1 result = i if head(i) = h and tail(i) = t repeat min = min-1; head(min) = h; tail(min) = t converted(min) = 0 result = min end integerfn union(integer x,y) integer hx,hy result = x if x = y hx=x and x=y and y=hx if x < y if x >= 0 start result = cell(x,y) if y >= 0 hy = head(y) result = cell(x,y) if x > hy result = cell(hy,union(x,tail(y))) if x # hy result = y finish hx = head(x); hy = head(y) result = cell(hx,union(tail(x),y)) if hx > hy result = cell(hy,union(x,tail(y))) if hx # hy result = cell(hx,union(tail(x),tail(y))) end routine concatenate(integer x,y) integer i,j i = x cycle j = link(i); link(i) = y; i = j exit if i = x repeat; ! %until i = x end routine accept exp(integername exp,exp end) !inputs a regular expression and creates intermediate graph representation integer i,string,string end,unit,unit end, n exp = 0 s: string = 0 u: if sym = '(' start read sym accept exp(unit,unit end) ->err if unit = 0 or sym # ')' read sym else if 'A' <= sym <= 'Z' or sym = '%' start read name(i) char(index(i)) = char(index(i))!128 if i # 0 i = i!tran(i)<<11 i = i+256 and read sym while sym = '<' if sym = '"' start; ! force transparent readsym i = i!1<<11 finish if sym = '[' start read(n); ->err if n>>4 # 0 i = i+n<<16 readsym; ->err if sym # ']' read sym finish else ->err if sym # '+' i = 0 i = i+256 and read sym while sym = '+' finish max = max+1; token(max) = i; link(max) = max unit = max; unit end = max finish if sym = '*' or sym = '!' start max = max+1; token(max) = -1; link(max) = max min = min-1; head(min) = max; tail(min) = unit concatenate(unit end,min); unit end = max unit = min if sym = '*' read sym finish if sym = '?' start max = max+1; token(max) = -1 link(max) = link(unit end); link(unit end) = max min = min-1; head(min) = max; tail(min) = unit unit = min read sym finish if string=0 then string=unit else concatenate(string end,unit) string end = unit end ->u unless sym = ',' or sym = ')' or sym = nl if exp = 0 start exp = string exp end = string end else exp = union(string,exp) i = link(exp end) link(exp end) = link(string end) link(string end) = i finish return unless sym = ',' read sym until sym # nl ->s err:exp = 0 end routine convert integer i,j,k,m,n,gmax1,loopstop routine tcount(integer x) integer t cycle return if x = 0 if x < 0 start tcount(tail(x)) x = head(x) finish t = token(x) exit if t >= 0 return if t = loopstop token(x) = loopstop x = link(x) repeat k = k-1 end routine add components(integer x) owninteger i,k,t,u while x # 0 cycle if x < 0 start add components(tail(x)) x = head(x) finish t = token(x) exit if t >= 0 return if t = loopstop token(x) = loopstop x = link(x) repeat if x # 0 then x = link(x) else t = 0 u = t&(x'F0000'+15<<11+255) i = gmax1 cycle i = i+1 exit if i > gmax k = item(i) next(i)=union(next(i),x) and return if k = t if k&(x'F0000'+15<<11+255) = u start print name(p) unless p = 0 printstring("-CLASH: "); print name(k); space; print name(t) newline finish k = k&255 if u = ident or (u&255<k and k>=180) or k = 0 start cycle i = gmax,-1,i item(i+1) = item(i) next(i+1) = next(i) repeat exit finish repeat gmax = gmax+1 item(i) = t; next(i) = x end loopstop = -1; gmin = gmax+1 cycle i = min,1,max converted(i) = 0 repeat n = next(0) 1: gmax1 = gmax loopstop = loopstop-1 add components(n) item(gmax) = item(gmax)+1024 if gmax1 = 0 start inits = gmax inits = inits-1 while inits # 0 and item(inits)&255 >= first phrase finish converted(n) = gmax1+1 m = 0 cycle i = gmin,1,gmax j = next(i) if j # 0 start k = converted(j) if k = 0 start loopstop = loopstop-1 tcount(j) converted(j) = k finish if k < m start m = k; n = j finish finish repeat ->1 if m # 0 cycle i = gmin,1,gmax k = next(i) k = converted(k) if k # 0 next(i) = k repeat end; !convert routine minimize integer i,j,k,m,n integerarray stack(1:150) integerfn ult map(integer i) integer j j=i and i=map(i) until i = j or i = 0 result = j end integerfn equivalent(integer nn,mm) integer i,j,k,pos1,pos2 pos1 = 0; pos2 = 0 1: cycle k = item(mm) ->9 unless item(nn) = k i = next(nn); j = next(mm) ->9 if (i=0 and j#0) or (i#0 and j=0) pos1 = pos1+1; stack(pos1) = nn; map(nn) = mm nn = nn+1; mm = mm+1 exit if k&1024 # 0; !last alternative repeat 2: result = 1 if pos2 = pos1 pos2 = pos2+1; i = stack(pos2) nn = ult map(next(i)); mm = ult map(next(map(i))) ->2 if nn = mm if nn < mm start i = nn; nn = mm; mm = i finish ->1 if nn > n 9: while pos1 # 0 cycle i = stack(pos1); map(i) = i pos1 = pos1-1 repeat result = 0 end cycle i = 0,1,gmax map(i) = i repeat return if gmin > gmax cycle n = gmin,1,gmax if map(n) = n start if n = gmin or item(n-1)&1024 # 0 start m = 1 while m # n cycle exit if map(m) = m and equivalent(n,m) # 0 m = m+1 repeat finish else map(n) = ult map(n) finish repeat j = gmin-1 cycle i = gmin,1,gmax k = map(i) if k = i start j = j+1; map(i) = j item(j) = item(i); next(j) = next(i) else map(i) = map(k) finish repeat gmax = j cycle i = gmin,1,gmax k = next(i) next(i) = map(k) if k # 0 repeat end; !minimize gmax = 0 1: read sym until sym # nl ->10 if sym = '/' if sym = 'S' and next symbol = 'S' start skip symbol; p = 0 else read name(p); stop if p = 0 finish min = 0; max = 0 read sym until sym#nl and sym#'-' and sym#'>' accept exp(exp,end) ->9 if exp = 0 or sym # nl concatenate(end,0) item(0) = 2047; next(0) = exp convert i = gmin minimize i = map(gmin) if p = 0 start; !ss !!! j = item(i);! k = next(i) !!! k = k-inits;! %stop %if k <= 0 !!! %if i <= inits %start !!! ->99 %if l >= first phrase !!! %signal 0,25 %if initial(l) # 0 !!! %else !!! %finish !!! gmax = gmax-inits cycle i = 1, 1, inits l = item(i)&255 continue if l >= 200 l = atomic(l) if 130 <= l < 180 signal 0,25 if initial(l) # 0 initial(l) = i; initnext(l) = item(i) repeat select output(glist) newline else phrase(p) = i select output(glist) newline print name(p); printstring(" =>") hwrite(i,1) finish k = 1024 cycle i = gmin,1,gmax if k&1024 # 0 start newline; hwrite(i,3); j = 0 finish j = j+1 if j > 5 start newline; spaces(4); j = 1 finish spaces(3) k = item(i) if k&255 # 0 start print name(k) else printstring("*E") print symbol('+') and k=k-256 while k&x'300' # 0 finish hwrite(next(i),1) repeat select output(err) ->1 9: printstring("WRONG FORMAT AT: ") while sym # nl cycle print symbol(sym); read sym repeat newline ->1 !deal with initial phrase !assumes exactly one (imp) 10: if inits = 1 start; ! not imp!!! selectoutput(err) printstring("NOT AN IMP GRAMMAR"); newline return finish p = phrase(item(inits+1)&255) signal 0,26 if p = 0 cycle j = item(p); k = j&255 signal 0,27 if k >= 160 k = atomic(k) if k >= 120 signal 0,28 if initial(k) # 0 initial(k) = p!x'8000'; initnext(k) = j exit if j&1024 # 0 p = p+1 repeat initial(0) = initial(182); !%decl select output(glist) newlines(2) cycle i = 0,1,119 k = initial(i) if k # 0 start hwrite(i,2); printstring(": ") print name(initnext(i)) hwrite(k&255, 3) printsymbol('`') if k < 0 newline finish repeat select output(err) end; !read grammar routine read atoms integer i,j,k,dict,dmax,code,class,sub integerarray char,cont,alt(0:1000) routine read code integer n code = next symbol; sub = 0 if code # ',' and code # nl start skip symbol if code = '$' start read(code); return finish return unless code = '(' read(sub) while nextsymbol = '+' cycle skipsymbol; read(n); sub = sub+n repeat skip symbol finish code = class+128 end routine insert in(integername x) cycle while char(x) < code cycle cont(x) = sub if cont(x) = 0 x == alt(x) repeat if char(x) # code start dmax = dmax+1; char(dmax) = code cont(dmax) = 0; alt(dmax) = x; x = dmax finish exit if code&128 # 0 read code x == cont(x) repeat sub = cont(alt(x)) if sub = 0 and alt(x) # 0 cont(x) = sub end routine store(integer x) integer m,n,v, mm, q cycle kmax = kmax+1; n = kmax m = alt(x); mm = m store(m) and m=x'8000' if m # 0 v = char(x); x = cont(x) exit if v&128 # 0 if m = 0 start; !no alternatives if alt(x) = 0 and char(x)&128 = 0 start v = char(x)<<7+v; x = cont(x) finish else q = kmax-n+1 if q>>7 # 0 start selectoutput(0) printstring("Keydict overflow!"); newline signal 15,15 stop finish v = q<<7+v!x'8000' finish keydict(n) = v repeat if mm = 0 start kmax = kmax+1; keydict(kmax) = 0 else kmax = kmax-1 finish keydict(n) = m + x'4000' + (keydict(n+1)&127)<<7 + v&127 keydict(n+1) = x end dict = 0; dmax = 0; char(0) = 999 1: cycle sym = next symbol exit unless sym = '[' or sym = nl read symbol(sym) until sym = nl repeat ->10 if sym = '/' read(class) newname = 1 read sym; read name(class) newname = 0 if class < 130 start if sym # '[' start read(sym) if sym = '$' cycle code = sym; insert in(dict) read symbol(sym) exit if sym # ',' read symbol(sym) until sym # ' ' and sym # nl repeat finish else if class <= first phrase and sym = '=' start read sym; read name(atomic(class)) finish finish read symbol(sym) while sym # nl ->1 routine display(integer i,s) integer j routine show(integer sym) sym = '$' if sym = nl printsymbol(sym) end 1: j = keydict(i) if j&x'4000' = 0 start show(j&127) if j&x'8000' = 0 start j = j>>7 show(j) and s=s+1 if j # 0 space i = i+1; s = s+2 ->1 finish space display(j>>7&127+i,s+2) else print symbol(':'); print name(j&127) space and print name(j>>7&127) unless j>>7&127 = 0 j = keydict(i+1)&x'3FFF' hwrite(j, 4) unless j = 0 newline return finish return if j>>15 = 0 spaces(s); i = i+1 ->1 end 10: select output(dlist); newlines(2) kmax = 126; keydict(32) = 0 cycle i = 33,1,126 print symbol(i); space if char(dict) = i start j = (kmax+1)<<2 store(cont(dict)) dict = alt(dict) display(j>>2,2) else print symbol('?'); newline j = 32<<2 finish !let:0 dig:1 term:2 other:3 j = j+3 unless 'A'<=i<='Z' j = j-2 if '0'<=i<='9' j = j-1 if i = ';' keydict(i) = j repeat keydict('~') = keydict('^') newlines(2) select output(err) end integer i,j,k charmax = 0 item(i) = 0 and next(i) = 0 for i = -1, 1, 800 index(i) = 0 for i = 0, 1, 255 atomic(i) = i for i = 130, 1, 179 phrase(i) = 0 for i = first phrase, 1, 255 initnext(i) = 0 and initial(i) = 0 for i = 0, 1, 255 select output(err) read symbol(i) until i = '/' read symbol(i) until i = nl read atoms read symbol(i) until i = nl read grammar !write required values select output(new) printstring(" %endoflist"); newline printstring("%conststring(8)%array text(0:255) = %c ""Z"",") k = 5; outstring = 8 cycle j = 1, 1, 255 printsymbol('"'); PRINT NAME(J); PRINTSYMBOL('"') printsymbol(',') unless j = 255 k = k-1; k = 6 and newline if k <= 0 repeat newline outstring = -1 printstring("%constinteger gmax1="); hwrite(gmax,0) newline printstring("%owninteger gmax="); hwrite(gmax,0); newline printstring("%constinteger imp phrase ="); hwrite(inits+1, 0) newlines(2) printstring("%ownshortintegerarray phrase(200:255) = %C") for i = 200, 1, 255 cycle newline if i&7 = 0 hwrite(phrase(i),3) print symbol(',') unless i = 255 repeat newlines(2) printstring("%constbyteintegerarray atomic(130:179) = %c") k = 0 cycle i = 130,1,179 newline if k&7 = 0 k = k+1 hwrite(atomic(i),3) print symbol(',') unless i = 179 repeat newlines(2) integerfn packed(integer j,k) j = (j&1024)<<5 + (j&x'0300')<<4 + (j>>3&x'0100')<<6 + (j>>8&x'F00') result = j+k&255 end printstring("! FLAG<1> 0<1> SS<2> 0<3> T<1> LINK<8>"); newline printstring("%constshortintegerarray initial(0:119) = %c") cycle i = 0,1,119 newline if i&7 = 0 hwrite(initial(i), 7) print symbol(',') unless i = 119 repeat newlines(2) printstring("! MORE<1> 0<1> ORDER<2> TYPE<4> CLASS<8>"); newline printstring("%ownshortintegerarray gram(0:max grammar) = %c") cycle i = 0,1,gmax newline if i&7 = 0 k = 0 k = packed(item(i)!!1024,item(i)) if i # 0 hwrite(k,7) print symbol(',') repeat newline; printstring("0(max grammar-") write(gmax, 0); printsymbol(')') newlines(2) printstring("%ownshortintegerarray glink(0:max grammar) = %c") cycle i = 0, 1, gmax newline if i&7 = 0 hwrite(next(i), 7) printsymbol(',') repeat newline; printstring("0(max grammar-") write(gmax, 0); printsymbol(')') newlines(2) printstring("%constshortintegerarray kdict(32:"); hwrite(kmax,0) printstring(") = %c") cycle i = 32,1,kmax newline if i&7 = 0 hwrite(keydict(i),7) print symbol(',') unless i = kmax repeat newline printstring(" %list"); newline printstring("%endoffile"); newline selectoutput(0) printstring("Grammar complete"); newline endofprogram