DIRECTORY Rope USING [ROPE, Length], StructuredStreams USING [Create, Begin, End, Bp], List, Atom, JunoParseUnparse, IO USING[PutF, PutRope, PutChar, ROS, RopeFromROS, Put, atom, real, int, STREAM, CR]; JunoUnparserImpl: PROGRAM IMPORTS StructuredStreams, Atom, IO, JunoParseUnparse, Rope EXPORTS JunoParseUnparse = BEGIN OPEN Str: StructuredStreams, JunoParseUnparse, Rope; Unparse: PUBLIC PROC [expr: LIST OF Se, table: Table, culprit: Se _ NIL, openCount: INTEGER_0, leftMargin: INTEGER _ 0, rightMargin: INTEGER _ 69] RETURNS [ROPE] = BEGIN ros: IO.STREAM _ IO.ROS[]; stream: IO.STREAM _ Str.Create[onTopOf: ros, margin: rightMargin]; Unp: PROC [ex, uncle: LIST OF Se, opn: INTEGER] = BEGIN IF ex = culprit THEN stream.PutChar[0C]; WITH ex.first SELECT FROM fi: REF INT => stream.PutF["%g1", IO.int[fi^]]; fx: REF REAL => stream.PutF["%g1.5", IO.real[fx^]]; fa: ATOM => stream.Put [IO.atom[fa]]; fr: Rope.ROPE => {stream.PutChar['"]; stream.PutRope[fr]; stream.PutChar['"]}; fl: LIST OF REF ANY => UnpList[fl, uncle, opn]; ENDCASE => NULL; IF ex = culprit THEN stream.PutChar[0C] END; UnpList: PROC [lst, uncle: LIST OF Se, opn: INTEGER] = BEGIN op: ATOM = NARROW[lst.first]; arg1: LIST OF Se = lst.rest; arg2: LIST OF Se = lst.rest.rest; opProps: REF Props = GetAtomProps[op, table].rp; type: UnparseType _ opProps.unparseType; SELECT TRUE FROM type = infixA AND arg2 # NIL => {Str.Begin[stream]; Unp[arg1, NIL, 0]; stream.PutChar[' ]; Str.Bp[stream, TRUE, 0]; Unp[lst, NIL, 0]; stream.PutChar[' ]; Unp[arg2, NIL, opn]; Str.End[stream]}; type = infixC AND arg2 # NIL => {IF uncle = NIL OR op # uncle.first THEN Str.Begin[stream]; Unp[arg1, NIL, 0]; Unp[lst, NIL, 0]; Str.Bp[stream, FALSE, -1]; stream.PutChar[' ]; Unp[arg2, lst, opn]; IF uncle = NIL OR op # uncle.first THEN Str.End[stream]}; type = matchB AND arg2 = NIL => {Unp[lst, NIL, 0]; Unp[arg1, NIL, opn - 1]; IF opn <= 0 THEN stream.Put[IO.atom[opProps.closer]]}; type = matchB AND arg2 # NIL => {Str.Begin[stream]; Unp[arg1, NIL, 0]; Str.Bp[stream, TRUE, - 1 - Length[Atom.GetPName [op]]]; Unp[lst, NIL, 0]; Unp[arg2, NIL, opn - 1]; IF opn <= 0 THEN stream.Put[IO.atom[opProps.closer]]; Str.End[stream]}; type = infixD AND arg2 # NIL => {IF uncle = NIL OR op # uncle.first THEN Str.Begin[stream]; Unp[arg1, NIL, 0]; Str.Bp[stream, TRUE, - 1 - Length[Atom.GetPName [op]]]; Unp[lst, NIL, 0]; stream.PutChar[' ]; Unp[arg2, lst, opn]; IF uncle = NIL OR op # uncle.first THEN Str.End[stream]}; type = infixE AND arg2 # NIL => {Str.Begin[stream]; Unp[arg1, NIL, 0]; stream.PutChar[' ]; Unp[lst, NIL, 0]; stream.PutChar[' ]; Str.Bp[stream, FALSE, 0]; Unp[arg2, lst, opn]; Str.End[stream]}; opProps.infix AND arg2 # NIL => {IF uncle = NIL OR op # uncle.first THEN Str.Begin[stream]; Unp[arg1, NIL, 0]; Str.Bp[stream, TRUE, - 2 - Length[Atom.GetPName [op]]]; stream.PutChar[' ]; Unp[lst, NIL, 0]; stream.PutChar[' ]; Unp[arg2, lst, opn]; IF uncle = NIL OR op # uncle.first THEN Str.End[stream]}; opProps.matchfix AND arg2 = NIL => {Unp[lst, NIL, 0]; stream.PutChar[' ]; Unp[arg1, NIL, opn - 1]; IF opn <= 0 THEN {stream.PutChar[' ]; stream.Put[IO.atom[opProps.closer]]}}; opProps.prefix AND arg2 = NIL => {Unp[lst, NIL, 0]; stream.PutChar[' ]; Unp[arg1, NIL, opn]}; opProps.postfix AND arg2 = NIL => {Unp[arg1, NIL, opn]; stream.PutChar[' ]; Unp[lst, NIL, 0]}; opProps.subfix AND arg2 # NIL => {Str.Begin[stream]; Unp[arg1, NIL, 0]; stream.PutChar[' ]; Str.Bp[stream, TRUE, - 2 - Length[Atom.GetPName [op]]]; Unp[lst, NIL, 0]; stream.PutChar[' ]; Unp[arg2, NIL, opn - 1]; stream.PutChar[' ]; IF opn <= 0 THEN stream.Put[IO.atom[opProps.closer]]; Str.End[stream]}; opProps.busfix AND arg2 # NIL => {Unp[lst, NIL, 0]; Str.Begin[stream]; stream.PutChar[' ]; Unp[arg1, NIL, 0]; stream.PutChar[' ]; Str.Bp[stream, TRUE, - Length[Atom.GetPName [opProps.closer]]]; stream.Put[IO.atom[opProps.closer]]; stream.PutChar[' ]; Unp[arg2, NIL, opn]; Str.End[stream]}; ENDCASE => ERROR Error END; stream.PutRope[" "]; -- indent two spaces Unp[expr, NIL, openCount ! Error => CONTINUE]; stream.PutChar[IO.CR]; RETURN [IO.RopeFromROS[ros]] END; Error: ERROR = CODE; END. l JunoUnparserImpl.mesa (was OldUnparserImpl.mesa) Last Edited by: Gnelson, November 2, 1983 11:59 am Last edited by GNelson January 17, 1984 11:33 am Last edited by Stolfi June 15, 1984 8:04:10 am PDT For unparsing, the operators fall into the following classes: infixA: Infix ops preceded by their breakpoint with offset zero: -> := cong para infixB. Infix ops preceded by their breakpoints with negative offsets: // | and matchA. Matchfix ops with space-padded arguments: if do infixC. Infix ops followed by their breakpoint with zero offset: , ; : prefix. Prefix ops: hor, ver, cc, draw, ex matchB. Matchfix ops with un-space-padded arguments that are also Subfix ops with un-space-padded arguments: ( infixD. Infix ops preceded by their breakpoints with negative offsets, but with no space before them: , and ; infixE. ??? �Ê'˜™1™J™2J™0J™5Jšœ—™——šœÏk ˜ Jšœ�œ�œ�œ9�œ�œ�œ(�œ�œ˜Ä——šœÏbœ�˜šœ�˜Jšœ�œ˜4—šœ�˜Jšœ˜——šœ�œ�œ0˜;šœÏnœ�œ�œ �œ�œ'�œ�œ�œ�œ �œ�œ˜´šœ˜Jš œ�œ�œ�œ�œ �œ�œ1˜^š œŸœ�œ �œ�œ �œ˜2šœ�˜Jš-œ�œ�œ�œ �œ�œ �œ�œ�œ�œ�œ�œ�œ�œ�œJ�œ�œ�œ�œ!�œ�œ�œ�œ˜ž—Jšœ�œ˜—š œŸœ�œ�œ�œ �œ˜8šœ˜Jšœ�œ�œ�œ�œ�œ�œ�œM˜·Jšœ�œ�œ�˜Jš œ�œ�œ*�œ5�œ�œ0�œ˜íJš)œ�œ�œ�œ �œ�œ�œ&�œ�œ�œH�œ �œ�œ�œ&�œ�œ�œ�œ�œ �œ �œ˜ÐJšœ�œ�œ/�œ�œ7�œ�œ�œ �œ �œ2˜°Jšœ�œ�œ�œ �œ�œ�œ$�œ�œ4�œA�œ �œ�œ�œ˜ÂJš œ�œ�œ-�œ3�œ9�œ<˜ƒJšœ�œ�œ�œ �œ�œ�œ$�œ�œN�œA�œ �œ�œ�œ˜ÜJšœ�œ�œ�œ4�œ�œ �œ,�œ˜ÖJš œ�œ�œ�œ6�œ˜tJš œ�œ�œ�œ7�œ˜uJšœ�œ�œ/�œ;�œ7�œ6�œ2�œ �œ �œ2˜„Jšœ�œ�œ�œR�œ;�œA�œH�œ"˜÷Jšœ�œ�œ˜—Jšœ�œ˜—Jš œÏcœ �œ�œ�œ�œ˜�—J˜Jšœ˜—Jšœ�œ�œ˜—Jšœ�œ˜—…—¬?