-- 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.