-- September 6, 1982 12:26 am -- ParseWindowImpl.mesa -- Last Edited by: Gnelson, November 3, 1983 3:17 pm DIRECTORY Atom, ParseWindow, ParseTable, ViewerClasses, Rope, TiogaOps, Parser, Lexer, IO, Unparser, ParserGen; ParseWindowImpl: MONITOR IMPORTS Rope, TiogaOps, Parser, Lexer, Unparser, IO, ParserGen EXPORTS ParseWindow = BEGIN OPEN ParseWindow; 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}; GenerateParser: PUBLIC PROC [h: Handle] = {l: Lexer.Handle; ph: ParseTable.Handle; o: ParserGen.OpList; p: ParserGen.ProdList; c: ParserGen.Culprit; [l, ph, o, p, c] _ ParserGen.GenParser[h.grammerfilename]; h.productions _ p; h.ph.table _ ph; h.ph.in _ l}; TiogaNode: TYPE = TiogaOps.Ref; NodeProc: TYPE = PROC [n: TiogaNode, pw: Handle] RETURNS [keepgoing: BOOL]; NodeMap: PROC [ p: NodeProc, pw: Handle] RETURNS [didAllNodes: BOOL] = { --! should lock the selection & the document root: TiogaNode _ TiogaOps.ViewerDoc[pw.viewer]; RETURN[NM2[p, TiogaOps.FirstChild[root], pw]]} ; NM2: PROC [p: NodeProc, n: TiogaNode, pw: Handle] RETURNS [didAllNodes: BOOL] = {RETURN [n = NIL OR (p[n, pw] AND NM2[p, TiogaOps.FirstChild[n], pw] AND NM2[p, TiogaOps.Next[n], pw])]}; ParseViewer: PUBLIC PROC [pw: Handle] = {newContent: LIST OF NodeContent _ NIL; success: BOOL; tree: REF; text1: ROPE; text2: ROPE; n: TiogaNode _ TiogaOps.FirstChild[TiogaOps.ViewerDoc[pw.viewer]]; 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; vc: ParserGen.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 (l.first.text1 # text1 OR 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 IsGeneratedBy and Unparse work on the CAR of their argument -- and ignore the cdr. IF pw.ph.error = NIL AND pw.ph.eof THEN {vc _ ParserGen.IsGeneratedBy[pw.productions, $S, 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, 60, pw.ph.table, pw.ph.openCount]; 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, 60, pw.ph.table, 0]; 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]; 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]]}; END.