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šœœ˜—…—¬?