-- OldUnparserImpl.mesa, -- last edited by GNelson June 17, 1983 3:02 pm -- For unparsing, the operators fall into the following classes: -- 1. Infix ops preceded by their breakpoint with offset zero: -> := cong para -- 2. Infix ops preceded by their breakpoints with negative offsets: // | and -- 3. Matchfix ops with space-padded arguments: if do -- 4. Infix ops followed by their breakpoint with zero offset: , ; : -- 5. Prefix ops: hor, ver, cc, draw, ex -- 6. Matchfix ops with un-space-padded arguments that are also Subfix ops -- with un-space-padded arguments: ( -- 7. Infix ops preceded by their breakpoints with negative offsets, but with -- no space before them: , and ; -- -- Last Edited by: Gnelson, November 2, 1983 11:59 am DIRECTORY Rope, UnparserBuffer, List, Atom, OldUnparser, Real, IO, ParseTable; OldUnparserImpl: MONITOR IMPORTS UnparserBuffer, Atom, Real, IO, ParseTable, Rope EXPORTS OldUnparser = BEGIN OPEN PT: ParseTable; UB: UnparserBuffer.Handle ← UnparserBuffer.NewHandle[]; Unparse: PUBLIC ENTRY PROC[f: REF ANY, -- unparse Car[f], ignore Cdr[f]. culprit: REF ANY, margin: INTEGER, p: PT.Handle, openCount: INT] RETURNS [Rope.ROPE] = {UB.Init[]; UB.margin ← margin; UB.output ← IO.ROS[]; UB.Ropeb[" "]; -- indent two spaces culpritG ← culprit; Unp[f, NIL, p, openCount ! Error => CONTINUE]; UB.Newlineb[0]; RETURN [IO.RopeFromROS[UB.output]]}; culpritG: REF ANY; --! global var storing culprit, to be replaced by local Error: ERROR = CODE; Unp: PROC[f: REF ANY, uncle: REF ANY, p: PT.Handle, openCount: INT] = {ff: LIST OF REF ANY = NARROW[f]; IF ff = culpritG THEN UB.Charb[0C]; WITH ff.first SELECT FROM fi: REF INT => UnpInt[fi↑]; fa: ATOM => UB.Ropeb[Atom.GetPName[fa]]; fr: Rope.ROPE => {UB.Charb['"]; UB.Ropeb[fr]; UB.Charb['"]}; fx: REF REAL => UnpReal[fx↑]; fl: LIST OF REF ANY => UnpList[fl, uncle, p, openCount]; ENDCASE => NULL; IF ff = culpritG THEN UB.Charb[0C]; }; UnpReal: PROC [x: REAL] = {IF x < 0 THEN {UB.Charb['-]; x ← - x}; {n: INT ← Real.RoundLI[1000 * x]; UnpInt[ n / 1000]; UB.Charb['.]; n ← n MOD 1000; {i: INT ← 100; WHILE n # 0 DO UB.Charb['0 + (n / i)]; n ← n MOD i; i ← i / 10 ENDLOOP; }}}; UnpInt: PROC[i: INT] = {IF i = 0 THEN UB.Charb['0] ELSE {IF i < 0 THEN {UB.Charb['-]; i ← - i}; UnpInt2[i]}}; LexemeToRope: PUBLIC PROC[f: REF ANY] RETURNS [Rope.ROPE] = {RETURN[IO.PutFR[NIL, IO.refAny[f]]]}; UnpInt2: PROC[i: INT] = {IF i # 0 THEN {UnpInt2[i / 10]; UB.Charb['0 + (i MOD 10)]}}; UnpList: --recursive-- PROC [l: LIST OF REF ANY, uncle: REF ANY, p: PT.Handle, openCount: INT] = {op: REF ANY = l; arg1: REF ANY = l.rest; arg2: REF ANY = l.rest.rest; opType: PT.Properties = p.Search[NARROW[op, LIST OF REF ANY].first, NIL]; type: INT ← opType.unparserType; SELECT TRUE FROM type = 1 AND arg2 # NIL => {UB.Setb[]; Unp[arg1, NIL, p, 0]; UB.Charb[' ]; UB.Bp[TRUE, 0]; Unp[op, NIL, p, 0]; UB.Charb[' ]; Unp[arg2, NIL, p, openCount]; UB.Endb[]}; type = 4 AND arg2 # NIL => {IF uncle = NIL OR Car[op] # Car[uncle] THEN UB.Setb[]; Unp[arg1, NIL, p, 0]; Unp[op, NIL, p, 0]; UB.Bp[FALSE, -1]; UB.Charb[' ]; Unp[arg2, op, p, openCount]; IF uncle = NIL OR Car[op] # Car[uncle] THEN UB.Endb[]}; type = 6 AND arg2 = NIL => {Unp[op, NIL, p, 0]; Unp[arg1, NIL, p, openCount - 1]; IF openCount <= 0 THEN UB.Atomb[opType.closer.name]}; type = 6 AND arg2 # NIL => {UB.Setb[]; Unp[arg1, NIL, p, 0]; UB.Bp[TRUE, - 1 - Atom.GetPName [NARROW[NARROW[op, LIST OF REF ANY].first, ATOM]].Length]; Unp[op, NIL, p, 0]; Unp[arg2, NIL, p, openCount - 1]; IF openCount <= 0 THEN UB.Atomb[opType.closer.name]; UB.Endb[]}; type = 7 AND arg2 # NIL => {IF uncle = NIL OR Car[op] # Car[uncle] THEN UB.Setb[]; Unp[arg1, NIL, p, 0]; UB.Bp[TRUE, - 1 - Atom.GetPName [NARROW[NARROW[op, LIST OF REF ANY].first, ATOM]].Length]; Unp[op, NIL, p, 0]; UB.Charb[' ]; Unp[arg2, op, p, openCount]; IF uncle = NIL OR Car[op] # Car[uncle] THEN UB.Endb[]}; type = 8 AND arg2 # NIL => {UB.Setb[]; Unp[arg1, NIL, p, 0]; UB.Charb[' ]; Unp[op, NIL, p, 0]; UB.Charb[' ]; UB.Bp[FALSE, 0]; Unp[arg2, op, p, openCount]; UB.Endb[]}; opType.infix AND arg2 # NIL => {IF uncle = NIL OR Car[op] # Car[uncle] THEN UB.Setb[]; Unp[arg1, NIL, p, 0]; UB.Bp[TRUE, - 2 - Atom.GetPName [NARROW[NARROW[op, LIST OF REF ANY].first, ATOM]].Length]; UB.Charb[' ]; Unp[op, NIL, p, 0]; UB.Charb[' ]; Unp[arg2, op, p, openCount]; IF uncle = NIL OR Car[op] # Car[uncle] THEN UB.Endb[]}; opType.matchfix AND arg2 = NIL => {Unp[op, NIL, p, 0]; UB.Charb[' ]; Unp[arg1, NIL, p, openCount - 1]; IF openCount <= 0 THEN {UB.Charb[' ]; UB.Atomb[opType.closer.name]}}; opType.prefix AND arg2 = NIL => {Unp[op, NIL, p, 0]; UB.Charb[' ]; Unp[arg1, NIL, p, openCount]}; opType.postfix AND arg2 = NIL => {Unp[arg1, NIL, p, openCount]; UB.Charb[' ]; Unp[op, NIL, p, 0]}; opType.subfix AND arg2 # NIL => {UB.Setb[]; Unp[arg1, NIL, p, 0]; UB.Charb[' ]; UB.Bp[TRUE, - 2 - Atom.GetPName [NARROW[NARROW[op, LIST OF REF ANY].first, ATOM]].Length]; Unp[op, NIL, p, 0]; UB.Charb[' ]; Unp[arg2, NIL, p, openCount - 1]; UB.Charb[' ]; IF openCount <= 0 THEN UB.Atomb[opType.closer.name]; UB.Endb[]}; opType.busfix AND arg2 # NIL => {Unp[op, NIL, p, 0]; UB.Setb[]; UB.Charb[' ]; Unp[arg1, NIL, p, 0]; UB.Charb[' ]; UB.Bp[TRUE, - Atom.GetPName[opType.closer.name].Length]; UB.Atomb[opType.closer.name]; UB.Charb[' ]; Unp[arg2, NIL, p, openCount]; UB.Endb[]}; ENDCASE => ERROR Error}; Car: PROC [s: REF ANY] RETURNS [REF ANY] = {RETURN [NARROW[s, LIST OF REF ANY].first]}; END.