JunoOldParseWindowImpl.mesa (was OldParseWindowImpl.mesa)
Coded September 6, 1982 12:26 am
Last Edited by: Gnelson, January 17, 1984 11:56 am
Last Edited by: Stolfi April 6, 1984 4:22:24 pm PST
Maintains a text viewer containing the current set of Juno procedures. Exports procedures that search this list and that append new procedures to it.
The viewer has two extra menu buttons:
Parse: parses the viewer contents, saves the result as the "current global alist",unparses it, and stuffs the unparsed text back into the viewer.
NewProc: Appends a new node to the viewer, with the skeleton of a procedure declaration (to be edited by the user).
NewProc: Appends a new node to the viewer, with the skeleton of a procedure declaration (to be edited by the user).
TO FIX: Everything.
DIRECTORY
Atom,
JunoOldParseWindow,
JunoParseTable,
ViewerClasses,
Rope,
TiogaOps,
JunoNewParser,
JunoLexer,
IO,
JunoOldUnparser;
JunoOldParseWindowImpl:
MONITOR
IMPORTS
Atom,
PT: JunoParseTable,
Rope,
TiogaOps,
JunoNewParser,
JunoLexer,
JunoOldUnparser,
IO
EXPORTS JunoOldParseWindow
=
BEGIN
OPEN
JunoOldParseWindow,
Unparser: JunoOldUnparser,
Parser: NewJunoParser,
Lexer: JunoLexer;
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};
- - - - MENU PROCEDURES
Moved here from JunoTop on April 6, 1984 3:52:04 pm PST; need to be fixed!!!
Parse:
PUBLIC
PROC =
{junoA: PWin.Handle = PEtc.junoA;
PEtc.Parse[];
IF NOT junoA.contentValid THEN Gr.Blink["Parse error"]
ELSE {p: LIST OF PWin.NodeContent ← junoA.content;
-- p is a list of pairs [text: rope, tree: REF ANY]; the trees
-- are all valid definitions, which we will add to the list of
-- definitions. Except that some are NILs that should be skipped.
WHILE p # NIL DO
IF p.first.tree # NIL
THEN {t: REF ANY = p.first.tree;
AddDef[Cadr[Cadr[t]], Caddr[Cadr[t]], Caddr[t]]};
p ← p.rest
ENDLOOP}};
NewProc:
PUBLIC
PROC =
{junoA: PWin.Handle = PEtc.junoA;
PWin.AddText[junoA, " CommandName(Args)", ": Body\n"]};
ProcFile:
PUBLIC
PROC[fileName: Rope.
ROPE] =
{PEtc.Algebra[fileName]; Parse[]};
Moved from JunoStorageImpl on April 6, 1984 3:52:04 pm PST; need to be fixed!!!
lambdaAlist: LIST OF REF ANY;
GetBody:
PUBLIC
PROC [name:
REF
ANY]
RETURNS [
REF
ANY] =
{deflist : LIST OF REF ANY ← lambdaAlist;
WHILE deflist # NIL AND deflist.first # name DO deflist ← deflist.rest.rest.rest ENDLOOP;
IF deflist # NIL THEN RETURN [Car[Cddr[deflist]]] ELSE RETURN [NIL]};
GetLocals:
PUBLIC
PROC [name:
REF
ANY]
RETURNS [
REF
ANY] =
{deflist : LIST OF REF ANY ← lambdaAlist;
WHILE deflist # NIL AND deflist.first # name DO deflist ← deflist.rest.rest.rest ENDLOOP;
IF deflist = NIL THEN RETURN [NIL] ELSE RETURN [Cadr[deflist]] };
AddDef:
PUBLIC
PROC [name, locals, body:
REF
ANY] =
{lambdaAlist ← CONS[name, CONS[locals, CONS[body, lambdaAlist]]]};
- - - - OLD STUFF
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 ← TRUE;
tree: REF;
text1: ROPE;
text2: ROPE;
pw.contentValid ← TRUE;
WHILE success AND 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.contentValid ← success;
IF success THEN pw.content ← newContent ELSE pw.content ← AppendNodeContentList[newContent, pw.content]};
AppendNodeContentList:
PROC[a, b:
LIST
OF NodeContent]
RETURNS [aa:
LIST
OF NodeContent] =
{
IF a=NIL THEN RETURN [b]
ELSE {aa ← a; WHILE a.rest#NIL DO a ← a.rest ENDLOOP; a.rest ← b};
};
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.