--RouteParse.mesa DIRECTORY IODefs: FROM "IODefs", SegmentDefs: FROM "SegmentDefs", RouteDefs:FROM "RouteDefs", StringDefs:FROM "StringDefs", SystemDefs: FROM "SystemDefs", StreamDefs: FROM "StreamDefs"; RouteParse:PROGRAM IMPORTS SegmentDefs, StringDefs, IODefs, SystemDefs, StreamDefs, RouteDefs EXPORTS RouteDefs=BEGIN OPEN RouteDefs; Error:SIGNAL=CODE; Done:SIGNAL=CODE; Feed:CHARACTER=14C; Tab:CHARACTER=' ; Comma:CHARACTER=',; SQ:CHARACTER=''; Gets:CHARACTER='←; lParen:CHARACTER='(; rParen:CHARACTER='); Plus:CHARACTER='+; Minus:CHARACTER='-; Del:CHARACTER=377C; cellCode:INTEGER=-1; posCode:INTEGER=-2; sizeCode:INTEGER=-3; endFileCode:INTEGER=-4; nameCode:INTEGER=-5; sideCode:INTEGER=-6; levelCode:INTEGER=-7; offsetCode:INTEGER=-8; northCode:INTEGER=-9; southCode:INTEGER=-10; eastCode:INTEGER=-11; westCode:INTEGER=-12; redCode:INTEGER=-13; blueCode:INTEGER=-14; bothCode:INTEGER=-15; chipCode:INTEGER=-16; leftBracketCode:INTEGER=-17; rightBracketCode:INTEGER=-18; commaCode:INTEGER=-19; netCode:INTEGER=-20; tieCode:INTEGER=-21; Ret:CHARACTER=' ; Space:CHARACTER=' ; innstream:StreamDefs.DiskHandle←NIL; fileName:STRING← [50]; GetInput:PUBLIC PROCEDURE={GetInputFile; Parse}; GetInputFile:PROCEDURE=BEGIN FOR i:INTEGER IN [0..1000) DO good:BOOLEAN←TRUE; IF chipmonk THEN GetChipmonkString[fileName,""L, "input file name= "L,""L] ELSE BEGIN IF i#0 THEN IODefs.WriteString[" no such file!"L]; AskForFileName["input file name= "]; --IF fileName.length=0 THEN ImageDefs.StopMesa[]; END; FixExtension[fileName,".txt"L]; innstream←StreamDefs.NewByteStream[fileName,StreamDefs.Read !SegmentDefs.FileNameError=>{good←FALSE; CONTINUE}]; IF good THEN EXIT; ENDLOOP; END; FixExtension: PROCEDURE [s, ext: STRING]=BEGIN FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN RETURN; ENDLOOP; StringDefs.AppendString[to: s, from: ext]; END; AskForFileName:PROCEDURE[s:STRING]= BEGIN OPEN IODefs; WriteChar[Ret]; WriteString[s]; ReadID[fileName !Rubout=>RETRY;]; END; Parse:PROCEDURE=BEGIN DictInit[]; ReadTheFile[]; innstream.destroy[innstream]; END; nextNetNo:NetNo; ReadTheFile:PROCEDURE=BEGIN cell:CellPtr←NIL; signal:SignalPtr←NIL; netNumber:INTEGER←0; t:INTEGER; problem←[]; hold←FALSE; nextNetNo←1; DO SELECT t←GetToken[] FROM >0=>Error; =0=>Error; chipCode=>problem.chipSize←ReadPoint[]; cellCode=>BEGIN cellNo:INTEGER←Number[]; cell←NIL; signal←NIL; FOR cl:CellListPtr←problem.cells,cl.t UNTIL cl=NIL DO IF cl.h.cellNo=cellNo THEN {cell←cl.h; EXIT}; ENDLOOP; IF cell=NIL THEN BEGIN cellList:CellListPtr←AllocateList[]; cell←AllocateCell[]; cell.cellNo←cellNo; cellList↑←[cell,problem.cells]; problem.cells←cellList; END; END; endFileCode=>RETURN; posCode=>IF cell=NIL THEN Error ELSE cell.pos←ReadPoint[]; sizeCode=>IF cell=NIL THEN Error ELSE cell.sizeL←ReadPoint[]; nameCode=>BEGIN j:STRING←ReadName[]; signalList:SignalListPtr←AllocateList[]; IF cell=NIL THEN Error; FOR sl:SignalListPtr←cell.signals,sl.t UNTIL sl=NIL DO s:SignalPtr=sl.h; IF SameString[j,s.name] THEN Error; ENDLOOP; signal←AllocateSignal[]; signal.name←j; signalList↑←[signal,cell.signals]; cell.signals←signalList; END; sideCode=>IF signal=NIL THEN Error ELSE signal.side←ReadSide[]; levelCode=>IF signal=NIL THEN Error ELSE signal.level←ReadLevel[]; offsetCode=>IF signal=NIL THEN Error ELSE signal.offset←Number[]; netCode=>netNumber←netNumber+1; tieCode=>BEGIN s:STRING←ReadName[]; netList:NetListPtr←AllocateList[]; net:NetPtr←AllocateNet[]; net↑←[netNumber,s,nextNetNo]; nextNetNo←nextNetNo+1; netList↑←[net,problem.wirelist]; problem.wirelist←netList; END; ENDCASE=>Error; ENDLOOP; END; ReadPoint:PROCEDURE RETURNS[c:CoordL]=BEGIN t:INTEGER←GetToken[]; IF t#leftBracketCode THEN Error; c.x←Number[]; t←GetToken[]; IF t#commaCode THEN Error; c.y←Number[]; t←GetToken[]; IF t#rightBracketCode THEN Error; END; ReadName:PROCEDURE RETURNS[STRING]={RETURN[GetRealWords[]]}; ReadSide:PROCEDURE RETURNS[Side]=BEGIN t:INTEGER←GetToken[]; SELECT t FROM northCode=>RETURN[n]; southCode=>RETURN[s]; eastCode=>RETURN[e]; westCode=>RETURN[w]; ENDCASE=>{Error; RETURN[n]}; END; ReadLevel:PROCEDURE RETURNS[What]=BEGIN t:INTEGER←GetToken[]; SELECT t FROM redCode=>RETURN[red]; blueCode=>RETURN[blue]; bothCode=>RETURN[both]; ENDCASE=>{Error; RETURN[both]}; END; --////// manage tokens and dictionary dict:ARRAY [0..100) OF Dict←ALL[[NIL,0]]; dictMax:INTEGER=LENGTH[dict]; dictEnd:INTEGER←0; dictBase:INTEGER←4; Dict:TYPE=RECORD[s:STRING,v:INTEGER]; DictInit:PROCEDURE=BEGIN dict[0]←["cell",cellCode]; dict[1]←["pos",posCode]; dict[2]←["size",sizeCode]; dict[3]←["end",endFileCode]; dict[4]←["name",nameCode]; dict[5]←["side",sideCode]; dict[6]←["level",levelCode]; dict[7]←["offset",offsetCode]; dict[8]←["n",northCode]; dict[9]←["s",southCode]; dict[10]←["e",eastCode]; dict[11]←["w",westCode]; dict[12]←["red",redCode]; dict[13]←["blue",blueCode]; dict[14]←["both",bothCode]; dict[15]←["chip",chipCode]; dict[16]←["net",netCode]; dict[17]←["tie",tieCode]; dictEnd←18; END; GetToken:PROCEDURE RETURNS[INTEGER]=BEGIN DO t:STRING←GetRealWords[]; IF t=NIL THEN RETURN[endFileCode]; SELECT t[0] FROM '[=>RETURN[leftBracketCode]; ']=>RETURN[rightBracketCode]; ',=>RETURN[commaCode]; ENDCASE=>RETURN[Lookup[t]]; ENDLOOP; END; Lookup:PROCEDURE[s:STRING] RETURNS[z:INTEGER]=BEGIN z←dictEnd; FOR i:INTEGER IN [0..z) DO IF SameString[s,dict[i].s] THEN RETURN[dict[i].v]; ENDLOOP; dict[z]←[s,z-dictBase]; dictEnd←dictEnd+1; RETURN[dict[z].v]; END; Lookup2:PUBLIC PROCEDURE[z:INTEGER] RETURNS[STRING]=BEGIN RETURN[dict[z+dictBase].s]; END; hold:BOOLEAN; holdC:CHARACTER←' ; GetRealWords:PROCEDURE RETURNS[t:STRING]=BEGIN s:STRING←GetFreeString[]; c:CHARACTER; s.length←0; t←NIL; IF hold THEN {hold←FALSE; s[0]←holdC; s.length←1; RETURN[s]}; DO IF innstream.endof[innstream] THEN RETURN[NIL]; SELECT c←GetChar[] FROM Space,Ret,Tab=>IF s.length >0 THEN RETURN[s] ELSE s.length←0; IN ['a..'z],SQ,Gets,lParen,rParen,Plus,Minus, IN ['0..'9]=> {s[s.length]←c; s.length←s.length+1}; IN ['A..'Z]=> {s[s.length]←c-'A+'a; s.length←s.length+1}; '[,'],',=> IF s.length=0 THEN {s[0]←c; s.length←1; RETURN[s];} ELSE {hold←TRUE; holdC←c; RETURN[s]}; ENDCASE=>Error;--illegal character ENDLOOP; END; Number:PROCEDURE RETURNS[INTEGER]=BEGIN found,min:BOOLEAN←FALSE; c:CHARACTER; i:INTEGER←0; DO SELECT c←GetChar[] FROM Space,Ret,Tab,Comma=>IF found THEN RETURN[IF min THEN -i ELSE i]; IN ['0..'9]=>{i←i*10+(c-'0); found←TRUE}; Minus=> min←TRUE; ENDCASE=>Error;--illegal character ENDLOOP; END; Suck:PROCEDURE= {UNTIL SELECT Get[] FROM Ret=>TRUE, ENDCASE=>FALSE DO ENDLOOP}; held:CHARACTER←Del; GetChar:PROCEDURE RETURNS[c:CHARACTER]=BEGIN IF held#Del THEN {c←held; held←Del} ELSE c←Get[]; IF c=Minus AND (held←Get[])=Minus THEN {Suck[]; held←Del; c←Ret}; END; Get:PROCEDURE RETURNS[c:CHARACTER]=--INLINE--BEGIN c←innstream.get[innstream]; END; empties:ARRAY [0..200) OF STRING←ALL[NIL]; emptyEnd:INTEGER←0; GetFreeString:PROCEDURE RETURNS[s:STRING]=BEGIN IF emptyEnd=0 THEN RETURN[SystemDefs.AllocateHeapString[10]]; emptyEnd←emptyEnd-1; RETURN[empties[emptyEnd]]; END; FreeString:PROCEDURE[s:STRING]=BEGIN IF emptyEnd<200 THEN { empties[emptyEnd]←s; emptyEnd←emptyEnd+1} ELSE SystemDefs.FreeHeapString[s]; END; END..