-- September 6, 1982 12:26 am -- OldParseWindowImpl.mesa -- Last Edited by: Gnelson, October 11, 1983 9:32 pm DIRECTORY Atom, OldParseWindow, ParseTable, ViewerClasses, Rope, TiogaOps, Parser, Lexer, IO, OldUnparser; OldParseWindowImpl: MONITOR IMPORTS Atom, PT: ParseTable, Rope, TiogaOps, Parser, Lexer, OldUnparser, IO EXPORTS OldParseWindow = BEGIN OPEN OldParseWindow, Unparser:OldUnparser; ROPE: TYPE = Rope.ROPE; NewHandle: PUBLIC PROC [v: ViewerClasses.Viewer] RETURNS [h: Handle] = { h ← NEW[HandleRep] ; h.ph ← Parser.NewHandle[] ; h.ph.in ← Lexer.NewHandle[] ; h.viewer ← v ; h.content ← NIL ; h.contentValid ← FALSE}; AddOp: PUBLIC PROC [h: Handle, op: Rope.ROPE, alias: ROPE, bp: INTEGER, f: OperatorType, c: Rope.ROPE, u: INT ← 0] = {p: PT.Properties ← NEW[PT.PRec ← [name: Atom.MakeAtom[op]]]; IF alias # NIL THEN p.alias ← Atom.MakeAtom[alias]; p.bindingPower ← bp; p.closer ← IF c = NIL THEN NIL ELSE h.ph.table.Search[Atom.MakeAtom[c], NIL]; p.unparserType ← u; SELECT f FROM infix => p.infix ← TRUE; subfixMatchfix => p.subfix ← p.matchfix ← TRUE; matchfix => p.matchfix ← TRUE; prefix => p.prefix ← TRUE; infixPrefix => p.infix ← p.prefix ← TRUE; closefix => p.closefix ← TRUE ENDCASE => ERROR; h.ph.table.Enter[p]; IF Rope.Length[alias] = 2 AND h.ph.in.type[Rope.Fetch[alias, 0]] = op THEN h.ph.in.AddOpPair[alias.Fetch[0], alias.Fetch[1]]; IF Rope.Length[op] = 2 AND h.ph.in.type[Rope.Fetch[op, 0]] = op THEN h.ph.in.AddOpPair[op.Fetch[0], op.Fetch[1]]}; TiogaNode: TYPE = TiogaOps.Ref; Next: PROC[n:TiogaNode] RETURNS [TiogaNode] = {RETURN[TiogaOps.Next[n]]}; FirstChild: PROC[n:TiogaNode] RETURNS [TiogaNode] = {RETURN[TiogaOps.FirstChild[n]]}; GetRope: PROC[n:TiogaNode] RETURNS [ROPE] = {RETURN[TiogaOps.GetRope[n]]}; ViewerDoc: PROC[v: ViewerClasses.Viewer] RETURNS [TiogaNode] = {RETURN[TiogaOps.ViewerDoc[v]]}; ParseViewer: PUBLIC PROC [pw: Handle] = {newContent: LIST OF NodeContent ← NIL; n: TiogaNode ← TiogaOps.FirstChild[TiogaOps.ViewerDoc[pw.viewer]]; success: BOOL; tree: REF; text1: ROPE; text2: ROPE; pw.contentValid ← TRUE; WHILE n # NIL DO [success, tree, text1, text2] ← PN2[n, pw]; IF success THEN newContent ← CONS[[text1, text2, tree], newContent]; n ← TiogaOps.Next[n]; ENDLOOP; pw.content ← newContent}; PN2: PROC [n: TiogaNode, pw: Handle] RETURNS [success: BOOL, tree: REF ANY, text1: ROPE, text2: ROPE] = {r: Rope.ROPE; vc: VerdictAndCulprit; errorMessage: ROPE ← NIL; text1 ← TiogaOps.GetRope[n]; text2 ← TiogaOps.GetRope[TiogaOps.FirstChild[n]]; -- next three lines try to skip parsing if old parsed result is present in pw.contents: { l: LIST OF NodeContent ← pw.content ; WHILE l # NIL AND NOT(Rope.Equal[l.first.text1, text1] AND Rope.Equal[l.first.text2, text2]) DO l ← l.rest ENDLOOP ; IF l # NIL THEN { success ← TRUE ; tree ← l.first.tree ; text1 ← l.first.text1; text2 ← l.first.text2 ; RETURN } }; IF ~ pw.contentValid THEN RETURN; pw.ph.in.in ← IO.RIS[Rope.Cat[text1, text2, " "]]; pw.ph.in.eof ← FALSE; pw.ph.in.error ← NIL; pw.ph.in.Lex[]; IF pw.ph.in.eof THEN {success ← TRUE; tree ← text1 ← text2 ← NIL; RETURN}; pw.ph.Parse[]; pw.ph.result ← tree ← CONS[pw.ph.result, NIL]; -- necessary because WellFormed and Unparse work on the CAR of their argument -- and ignore the cdr. IF pw.ph.error = NIL AND pw.ph.eof THEN {vc ← pw.WellFormed[pw.ph.result]; IF vc.verdict # Yes THEN errorMessage ← "Not a WFF" ELSE {vc.culprit ← NIL; errorMessage ← NIL}} ELSE {vc.culprit ← NIL; errorMessage ← IF pw.ph.error # NIL THEN pw.ph.error ELSE "Bad Syntax"}; r ← Unparser.Unparse[pw.ph.result, vc.culprit, 57, pw.ph.table, pw.ph.openCount]; --! change "57" to "width of window" tree ← NARROW[pw.ph.result, LIST OF REF ANY].first; IF pw.ph.error # NIL OR ~pw.ph.eof THEN {r ← Rope.Cat[r, " \000", Rope.FromRefText[pw.ph.in.buf], "\000"]; WHILE ~ IO.EndOf[pw.ph.in.in] DO r ← Rope.Cat[r, Rope.FromChar[IO.GetChar[pw.ph.in.in]]] ENDLOOP}; {i: INT ← r.SkipTo[0, "\000"]; j: INT; endOfHeader: INT = r.SkipTo[0, "\n"]; firstLine: Rope.ROPE = r.Substr[0, endOfHeader]; restOfLines: Rope.ROPE = IF endOfHeader = r.Length THEN NIL ELSE r.Substr[endOfHeader + 1]; Foo: SAFE PROC[root: TiogaOps.Ref] = TRUSTED {m: TiogaNode = IF TiogaOps.FirstChild[n] = NIL THEN n ELSE TiogaOps.FirstChild[n]; TiogaOps.SelectNodes[viewer: pw.viewer, start:n, end:m, pendingDelete: TRUE, level:char]; IF i = r.Length[] THEN {TiogaOps.InsertRope[firstLine]; TiogaOps.Break[]; TiogaOps.Nest[]; TiogaOps.InsertRope[restOfLines]} ELSE {j ← r.SkipTo[i + 1, "\000"]; TiogaOps.InsertRope[Rope.Cat[r.Substr[0, i], r.Substr[i+1, j - i - 1], r.Substr[j+1]]]; TiogaOps.SetSelection[pw.viewer, [n, i], [n, j - 1]]}}; TiogaOps.CallWithLocks[Foo, TiogaOps.ViewerDoc[pw.viewer]]; success ← (errorMessage = NIL); text1 ← firstLine; text2 ← restOfLines}}; AddTree: PUBLIC PROC[pw: Handle, tree: REF] = {r: ROPE ← Unparser.Unparse[LIST[tree], NIL, 57, pw.ph.table, 0]; End: PROC[r: ROPE] RETURNS [e: INT] = { ee: INT ← r.SkipTo[0, ":"]; e ← r.SkipTo[0, "\n"]; IF e = r.Length THEN r ← Rope.Cat[r, "\n"]; IF ee < e THEN e ← ee}; endOfHeader: INT = End[r]; firstLine: Rope.ROPE = r.Substr[0, endOfHeader]; restOfLines: Rope.ROPE = IF r.Fetch[endOfHeader] = ': THEN r.Substr[endOfHeader] ELSE r.Substr[endOfHeader + 1]; nd: TiogaNode ← TiogaOps.LastWithin[TiogaOps.ViewerDoc[pw.viewer]]; Foo: SAFE PROC[root: TiogaOps.Ref] = CHECKED {TiogaOps.SelectNodes[pw.viewer, nd, nd, node, FALSE]; TiogaOps.Break[]; TiogaOps.UnNest[]; TiogaOps.InsertRope[firstLine]; TiogaOps.Break[]; TiogaOps.Nest[]; TiogaOps.InsertRope[restOfLines]}; TiogaOps.CallWithLocks[Foo, TiogaOps.ViewerDoc[pw.viewer]]; pw.content ← CONS[[firstLine, restOfLines, tree], pw.content]}; AddText: PUBLIC PROC[pw: Handle, text1, text2: ROPE] = {nd: TiogaNode ← TiogaOps.LastWithin[TiogaOps.ViewerDoc[pw.viewer]]; Foo: SAFE PROC[root: TiogaOps.Ref] = CHECKED {TiogaOps.SelectNodes[pw.viewer, nd, nd, node, FALSE]; TiogaOps.Break[]; TiogaOps.UnNest[]; TiogaOps.InsertRope[text1]; TiogaOps.Break[]; TiogaOps.Nest[]; TiogaOps.InsertRope[text2]}; TiogaOps.CallWithLocks[Foo, TiogaOps.ViewerDoc[pw.viewer]]}; HasForm: PUBLIC PROC[f: REF ANY, op: ATOM, Arg1: SyntacticPredicate, Arg2: SyntacticPredicate ← NIL] RETURNS [VerdictAndCulprit] = {WITH Car[NARROW[f]] SELECT FROM g: LIST OF REF ANY => {IF Car[g] # op THEN RETURN [[OfCourseNot, g]]; IF (Arg2 = NIL) # (Cddr[g] = NIL) THEN RETURN[[OfCourseNot, f]]; {aw: VerdictAndCulprit ← Arg1[Cdr[g]]; IF aw.verdict # Yes THEN RETURN [[No, aw.culprit]]; IF Cddr[g] = NIL THEN RETURN [[Yes, NIL]]; aw ← Arg2[Cddr[g]]; IF aw.verdict # Yes THEN RETURN [[No, aw.culprit]]; RETURN [[Yes, NIL]]}} ENDCASE => RETURN [[OfCourseNot, f]]}; Or: PUBLIC PROC [aw1, aw2: VerdictAndCulprit] RETURNS [r: VerdictAndCulprit] = {SELECT TRUE FROM aw1.verdict = Yes OR aw2.verdict = Yes => r ← [Yes, NIL]; aw1.verdict = No => r ← aw1; aw2.verdict = No => r ← aw2; aw1.verdict = OfCourseNot AND aw2.verdict = OfCourseNot => r ← aw1 ENDCASE => ERROR}; Se: TYPE = REF ANY; Car: PROC [r: Se] RETURNS [Se] = {RETURN[NARROW[r, LIST OF REF ANY].first]}; Cdr: PROC [r: Se] RETURNS [Se] = {RETURN[NARROW[r, LIST OF REF ANY].rest]}; Cadr: PROC [r: Se] RETURNS [Se] = {RETURN[Car[Cdr[r]]]}; Caddr: PROC [r: Se] RETURNS [Se] = {RETURN[Car[Cdr[Cdr[r]]]]}; Cddr: PROC [r: Se] RETURNS [Se] = {RETURN[Cdr[Cdr[r]]]}; Caar: PROC [r: Se] RETURNS [Se] = {RETURN[Car[Car[r]]]}; Cadar: PROC [l: Se] RETURNS [Se] = { RETURN[ Car[ Cdr[ Car[ l ] ] ] ] }; Caddar: PROC [l: Se] RETURNS [Se] = { RETURN[ Car[ Cdr[ Cdr[ Car[ l ] ] ] ] ] }; Cadddar: PROC [l: Se] RETURNS [Se] = { RETURN[ Car[ Cdr[ Cdr[ Cdr[ Car[ l ] ] ] ] ] ] }; Cadddr: PROC [l: Se] RETURNS [Se] = { RETURN[ Car[ Cdr[ Cdr[ Cdr[ l ] ] ] ] ] }; Caddddar: PROC [l: Se] RETURNS [Se] = { RETURN[ Car[ Cdr[ Cdr[ Cdr[ Cdr[ Car[ l ] ] ] ] ] ] ] }; Cddar: PROC [l: Se] RETURNS [Se] = { RETURN[ Cdr[ Cdr[ Car[ l ] ] ] ] }; END.