DIRECTORY Atom, Convert, EBMesaLisp, EmbeddedButtons, IO, RefText, Rope, RuntimeError; EBMesaLispImpl: CEDAR PROGRAM IMPORTS Atom, Convert, EmbeddedButtons, IO, RefText, Rope, RuntimeError EXPORTS EBMesaLisp = BEGIN ROPE: TYPE = Rope.ROPE; Parse: PUBLIC PROC [stream: IO.STREAM] RETURNS [val: REF ¬ NIL, endOfStream: BOOL ¬ FALSE] = { tokenKind: IO.TokenKind; token, firstToken: REF TEXT; charsSkipped: INT; done: BOOL ¬ FALSE; error: IO.TokenError; IF IO.EndOf[stream] THEN RETURN[NIL, TRUE]; firstToken ¬ token ¬ RefText.ObtainScratch[nChars: 100]; [tokenKind, token, charsSkipped, error] ¬ IO.GetCedarToken[stream, token]; IF tokenKind = tokenEOF THEN done ¬ TRUE ELSE IF error # none THEN { EmbeddedButtons.Error[IO.PutFR1["IO Syntax error at character %g", [integer[stream.GetIndex[]]] ]]; done ¬ TRUE; }; IF done THEN { RefText.ReleaseScratch[firstToken]; RETURN[NIL, TRUE]; }; SELECT tokenKind FROM tokenERROR => ERROR; tokenID => { IF RefText.Equal[token, "TRUE"] THEN val ¬ NEW[BOOL ¬ TRUE] ELSE IF RefText.Equal[token, "FALSE"] THEN val ¬ NEW[BOOL ¬ FALSE] ELSE val ¬ Atom.MakeAtomFromRefText[token]; }; tokenDECIMAL => val ¬ NEW[INT ¬ Convert.IntFromRope[RefText.TrustTextAsRope[token], 10]]; tokenOCTAL => val ¬ NEW[INT ¬ Convert.IntFromRope[RefText.TrustTextAsRope[token], 8]]; tokenHEX => val ¬ NEW[INT ¬ Convert.IntFromRope[RefText.TrustTextAsRope[token], 16]]; tokenREAL => val ¬ NEW[REAL ¬ Convert.RealFromRope[RefText.TrustTextAsRope[token]]]; tokenROPE => { val ¬ Convert.RopeFromLiteral[RefText.TrustTextAsRope[token]]; }; tokenCHAR => { val ¬ Rope.FromChar[RefText.Fetch[token, 0 ! RuntimeError.BoundsFault => {val ¬ Rope.FromChar['Z]; CONTINUE}]]; }; tokenATOM => { val ¬ Convert.AtomFromRope[RefText.TrustTextAsRope[token]]; }; tokenSINGLE => { IF RefText.Equal[token, "("] THEN val ¬ GetList[stream, closeParenAtom] ELSE IF RefText.Equal[token, "["] THEN val ¬ GetList[stream, closeBracketAtom] ELSE IF RefText.Equal[token, "{"] THEN val ¬ GetList[stream, closeCurlyBracketAtom] ELSE IF RefText.Equal[token, "<"] THEN val ¬ GetExecuteList[stream] ELSE IF RefText.Equal[token, ")"] THEN val ¬ closeParenAtom ELSE IF RefText.Equal[token, "]"] THEN val ¬ closeBracketAtom ELSE IF RefText.Equal[token, "}"] THEN val ¬ closeCurlyBracketAtom ELSE IF RefText.Equal[token, ">"] THEN val ¬ closeAngleBracketAtom ELSE val ¬ Convert.AtomFromRope[RefText.TrustTextAsRope[token]]; -- should include *, /, + and - }; tokenDOUBLE => { }; tokenCOMMENT => ERROR; tokenEOF => val ¬ NIL; ENDCASE => ERROR; RefText.ReleaseScratch[firstToken]; }; Unparse: PUBLIC PROC [object: REF ANY, prettyPrintList: LIST OF REF ANY ¬ NIL] RETURNS [result: ROPE] = { first: BOOL; listObject: LIST OF REF ANY; executeObject: BOOL ¬ FALSE; insert: ROPE ¬ NIL; insertFirst: BOOL ¬ FALSE; prettyPrintListRest: LIST OF REF ANY ¬ NIL; IF object = NIL THEN { result ¬ "()"; RETURN; } ELSE IF NOT ISTYPE[object, LIST OF REF ANY] THEN { result ¬ WITH object SELECT FROM v: REF BOOL => Convert.RopeFromBool[v­], v: REF INT => Convert.RopeFromInt[v­], v: REF REAL => Convert.RopeFromReal[v­], v: ATOM => Atom.GetPName[v], v: ROPE => Rope.Cat["\"", v, "\""], ENDCASE => ""; RETURN; }; listObject ¬ NARROW[object]; IF ISTYPE[listObject.first, ATOM] AND NARROW[listObject.first, ATOM] = $Execute THEN { listObject ¬ listObject.rest; result ¬ "<"; executeObject ¬ TRUE; } ELSE result ¬ "("; IF prettyPrintList # NIL THEN { IF ISTYPE[prettyPrintList.first, ROPE] THEN insert ¬ NARROW[prettyPrintList.first]; IF prettyPrintList.rest # NIL THEN { IF ISTYPE[prettyPrintList.rest.first, REF BOOL] THEN insertFirst ¬ NARROW[prettyPrintList.rest.first, REF BOOL]­; prettyPrintListRest ¬ prettyPrintList.rest.rest; }; }; first ¬ TRUE; FOR l: LIST OF REF ANY ¬ NARROW[listObject], l.rest UNTIL l = NIL DO IF insert # NIL AND (NOT first OR insertFirst) THEN result ¬ Rope.Concat[result, insert]; IF insert = NIL AND NOT first THEN result ¬ Rope.Concat[result, " "]; result ¬ Rope.Concat[result, Unparse[l.first, prettyPrintListRest]]; first ¬ FALSE; ENDLOOP; IF executeObject THEN result ¬ Rope.Concat[result, ">"] ELSE result ¬ Rope.Concat[result, ")"]; RETURN; }; ParseAborted: PUBLIC SIGNAL = CODE; SyntaxError: PUBLIC PROC [stream: IO.STREAM, msg: ROPE] = { EmbeddedButtons.Error[msg, NIL]; SIGNAL ParseAborted; }; GetList: PROC [stream: IO.STREAM, nestingAtom: ATOM] RETURNS [list: LIST OF REF ¬ NIL] = { val: REF ¬ NIL; endOfStream: BOOL ¬ FALSE; tail: LIST OF REF ¬ NIL; WHILE ~stream.EndOf[] DO [val, endOfStream] ¬ Parse[stream]; -- get the next token IF endOfStream THEN LOOP ELSE IF val = nestingAtom THEN EXIT; [list, tail] ¬ AddEntity[val, list, tail]; ENDLOOP; }; GetExecuteList: PROC [stream: IO.STREAM] RETURNS [list: LIST OF REF ¬ NIL] = { last: REF ANY ¬ NIL; endOfStream: BOOL ¬ FALSE; tail: LIST OF REF ANY ¬ NIL; [list, tail] ¬ AddEntity[$Execute, list, tail]; WHILE ~stream.EndOf[] DO [last, endOfStream] ¬ Parse[stream]; IF endOfStream THEN LOOP ELSE IF last = closeAngleBracketAtom THEN EXIT; [list, tail] ¬ AddEntity[last, list, tail]; ENDLOOP; }; Member: PUBLIC PROC [list: LIST OF ATOM, member: REF ANY] RETURNS[isMember: BOOL ¬ FALSE, tail: LIST OF ATOM] = { FOR l: LIST OF ATOM ¬ list, l.rest UNTIL l = NIL DO tail ¬ l; IF l.first = member THEN { isMember ¬ TRUE; RETURN; } ENDLOOP; }; AddEntity: PUBLIC PROC [entity: REF ANY, entityList, ptr: LIST OF REF ANY] RETURNS [newList, newPtr: LIST OF REF ANY] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr ¬ newList ¬ CONS[entity, NIL]; RETURN; } ELSE { newList ¬ entityList; ptr.rest ¬ CONS[entity, NIL]; newPtr ¬ ptr.rest; }; }; ReadRopeInParens: PUBLIC PROC [stream: IO.STREAM] RETURNS [rope: ROPE ¬ NIL] = { level: NAT ¬ 1; scratch, text: REF TEXT; c: CHAR; scratch ¬ text ¬ RefText.ObtainScratch[512]; -- numbers larger than 512 always allocate (yuk!) c ¬ stream.GetChar[]; text ¬ RefText.InlineAppendChar[text, c]; UNTIL level = 0 OR stream.EndOf[] DO c ¬ stream.GetChar[]; text ¬ RefText.InlineAppendChar[text, c]; IF c = '( THEN level ¬ level + 1 ELSE IF c = ') THEN level ¬ level - 1; ENDLOOP; rope ¬ Rope.FromRefText[text]; RefText.ReleaseScratch[scratch]; }; ReadRopeInAngleBrackets: PUBLIC PROC [stream: IO.STREAM] RETURNS [rope: ROPE ¬ NIL] = { level: NAT ¬ 1; scratch, text: REF TEXT; c: CHAR; scratch ¬ text ¬ RefText.ObtainScratch[512]; -- numbers larger than 512 always allocate (yuk!) c ¬ stream.GetChar[]; text ¬ RefText.InlineAppendChar[text, c]; UNTIL level = 0 OR stream.EndOf[] DO c ¬ stream.GetChar[]; text ¬ RefText.InlineAppendChar[text, c]; IF c = '< THEN level ¬ level + 1 ELSE IF c = '> THEN level ¬ level - 1; ENDLOOP; rope ¬ Rope.FromRefText[text]; RefText.ReleaseScratch[scratch]; }; ReadChar: PUBLIC PROC [f: IO.STREAM, c: CHAR] = { streamC: CHAR; [] ¬ IO.SkipWhitespace[f, TRUE]; streamC ¬ IO.GetChar[f]; IF NOT c = streamC THEN { SyntaxError[f, IO.PutFR["Expected %g not %g", [character[c]], [character[streamC]]]]; }; }; ReadKeyword: PUBLIC PROC [stream: IO.STREAM] RETURNS [keyName: ROPE] = { keyName ¬ ReadWWord[stream]; ReadChar[stream, ':]; }; ReadWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = { WordBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = CHECKED { SELECT char FROM IO.TAB, IO.CR, IO.SP, IO.LF => RETURN [break]; ENDCASE => RETURN [wwordBreaks[char]]; }; [word, ----] ¬ IO.GetTokenRope[f, WordBreakProc !IO.EndOfStream => {word ¬ NIL; CONTINUE}]; }; ReadWWord: PUBLIC PROC [f: IO.STREAM] RETURNS [word: Rope.ROPE] = { WWordBreakProc: SAFE PROC [char: CHAR] RETURNS [IO.CharClass] = { RETURN[wwordBreaks[char]]; }; [word, ----] ¬ IO.GetTokenRope[f, WWordBreakProc !IO.EndOfStream => {word ¬ NIL; CONTINUE}]; }; closeParenAtom: ATOM ¬ Atom.MakeAtom[")"]; closeBracketAtom: ATOM ¬ Atom.MakeAtom["]"]; closeCurlyBracketAtom: ATOM ¬ Atom.MakeAtom["}"]; closeAngleBracketAtom: ATOM ¬ Atom.MakeAtom[">"]; wwordBreaks: PACKED ARRAY CHAR OF IO.CharClass ¬ ALL[other]; wwordBreaks[IO.TAB] ¬ wwordBreaks[IO.CR] ¬ wwordBreaks[IO.SP] ¬ wwordBreaks[IO.LF] ¬ sepr; wwordBreaks[',] ¬ wwordBreaks[']] ¬ wwordBreaks[')] ¬ wwordBreaks['}] ¬ wwordBreaks['>] ¬ wwordBreaks['=] ¬ wwordBreaks[':] ¬ wwordBreaks[';] ¬ break; END. ΐ EBMesaLispImpl.mesa Copyright Σ 1989, 1991, 1992 by Xerox Corporation. All rights reserved. Bier, August 28, 1991 12:02 pm PDT Doug Wyatt, April 10, 1992 7:04 pm PDT Contents: Routines for parsing list expressions whose elements are Cedar tokens. token has the form: "sdfsdfds". RopeFromLiteral strips the outer quotes token has the form: 'g token has the form: $Foo. AtomFromRope strips the $ and makes an atom A single character token like: ; or , A two character token like: => Parsing Utility Routines Reads from the stream a list of tokens until the closing paren (or other closing symbol) is found. General-Purpose Parsing Routines Looks for ":". Returns . Strips the colon. [] _ IO.SkipWhitespace[stream, FALSE]; keyName _ IO.GetID[stream]; Read in characters until the next tab, space, carriage return, comma, ], ), }, =, :, ;, or >. Short for "Read Whitespace and Word" [] _ IO.SkipWhitespace[f, TRUE]; Initialization Κ P•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ<™HKšœ"™"K™&K˜—KšœQ™QK™šΟk ˜ KšœL˜L—K˜šΟnœžœž˜Kšžœ žœžœ˜GKšžœ ž˜—K˜Kšžœžœžœ˜K˜šŸœžœžœ žœžœžœžœžœžœžœ˜^Kšœ˜Kšœžœžœ˜Kšœžœ˜Kšœžœžœ˜Kšœ˜K˜Kš žœžœžœžœžœžœ˜+K˜K˜8Kšœ*žœΟb œ˜JKšžœžœž˜(šžœžœžœ˜KšœžœK˜cKšœžœ˜ K˜—šžœžœž˜Kšœ#˜#Kšžœžœžœ˜K˜—K˜šžœ ž˜Kšœžœ˜šœ ˜ šžœž˜$Kšœžœžœžœ˜—šžœžœž˜*Kšœžœžœž˜—šž˜K˜&—K˜—Kšœžœžœ<˜YKšœžœžœ;˜VKšœžœžœ<˜UKšœžœžœ9˜Tšœ˜KšœH™HK˜>K˜—šœ˜Kšœ™˜*K˜D—K˜—šœ˜KšœF™FK˜;K˜—šœ˜K™%Kšžœžœ œ  œ˜GKš žœžœžœ œ  œ˜NKš žœžœžœ œ  œ˜SKšžœžœžœ˜CKšžœžœžœ˜;Kšžœžœžœ˜=Kšžœžœžœ˜BKšžœžœžœ˜BKšžœ=Οc˜`K˜—šœ˜K™K˜—Kšœžœ˜Kšœžœžœ˜Kšžœžœ˜K˜—Kšœ#˜#K˜K˜—šŸœžœžœ žœžœžœžœžœžœžœžœ žœ˜iKšœžœ˜ Kš œ žœžœžœžœ˜Kšœžœžœ˜Kšœžœžœ˜Kšœ žœžœ˜Kš œžœžœžœžœžœ˜+K˜šžœ žœžœ˜K˜Kšžœ˜K˜K˜—fromšžœžœžœ žœžœžœžœžœ˜2šœ žœžœž˜ Lšœžœžœ˜(Kšœžœžœ˜&Kšœžœžœ˜(Kšœžœ˜Kšœžœ˜#Kšžœ˜—Kšžœ˜K˜—K˜Kšœ žœ ˜K˜šžœžœžœžœžœžœ žœ˜VK˜K˜ Kšœžœ˜K˜—šžœ˜K˜ —K˜šžœžœžœ˜Kš žœžœžœžœ žœ˜Sšžœžœžœ˜$Kšžœžœžœžœžœžœžœžœ˜qK˜0K˜—K˜K˜—Kšœžœ˜ šžœžœžœžœžœžœžœžœž˜DKš žœ žœžœžœžœžœ&˜YKš žœ žœžœžœžœ#˜EK˜DKšœžœ˜Kšžœ˜—K˜Kšžœžœ"˜7Kšžœ#˜'Kšžœ˜Kšœ˜K˜—KšŸ œž œžœ˜#procš Ÿ œž œ žœžœžœ˜;Mšœžœ˜ Mšžœ˜M˜M˜—K˜K™šŸœžœ žœžœžœžœžœžœžœžœ˜ZK™bKšœžœžœ˜Kšœ žœžœ˜Kš œžœžœžœžœ˜K˜šžœž˜Kšœ$‘˜9Kšžœ žœž˜Kšžœžœžœžœ˜$K˜*Kšžœ˜—Kšœ˜K˜—šŸœžœ žœžœžœžœžœžœžœ˜NKšœžœžœžœ˜Kšœ žœžœ˜Kš œžœžœžœžœžœ˜K˜Kšœ œ˜/šžœž˜K˜$Kšžœ žœž˜Kšžœžœžœžœ˜/K˜+Kšžœ˜—Kšœ˜K˜—šŸœž œžœžœžœ žœžœžœ žœžœžœžœžœ˜qš žœžœžœžœžœžœž˜3M˜ Mšžœžœžœžœ˜5Mšžœ˜—M˜M˜—šŸ œžœžœ žœžœžœžœžœžœžœžœžœžœžœ˜yšžœžœžœ˜Kš žœžœžœžœžœ˜#Kšœžœ žœ˜%Kšžœ˜K˜—šžœ˜K˜Kšœ žœ žœ˜K˜K˜—K˜—K˜K™ šŸœžœžœ žœžœžœžœžœ˜PKšœžœ˜Kšœžœž˜Kšœžœ˜K˜Kšœ-‘1˜^K˜K˜)šžœ žœž˜$K˜K˜)Kšžœžœ˜ Kšžœžœžœ˜&Kšžœ˜—K˜Kšœ ˜ K˜K˜—šŸœžœžœ žœžœžœžœžœ˜WKšœžœ˜Kšœžœž˜Kšœžœ˜K˜Kšœ-‘1˜^K˜K˜)šžœ žœž˜$K˜K˜)Kšžœžœ˜ Kšžœžœžœ˜&Kšžœ˜—K˜Kšœ ˜ K˜K˜—š Ÿœžœžœžœžœžœ˜1Mšœ žœ˜Mšœžœžœ˜ Mšœ žœ ˜šžœžœ žœ˜MšœžœD˜UM˜—Mšœ˜M˜—š Ÿ œž œ žœžœžœ žœ˜HJ™>Jšœžœžœ™&Jšœ žœ™K˜Kšœ˜K˜K˜—š Ÿœž œžœžœžœ žœ˜BM™]šŸ œžœžœžœžœžœžœ˜Hšžœž˜Mšžœžœžœžœžœžœžœžœžœ ˜.Mšžœžœ˜&—Mšœ˜—šœ‘œžœ˜/Mšœžœžœžœ˜+—Mšœ˜M˜—šŸ œžœžœžœžœžœ žœ˜CM™$š Ÿœžœžœžœžœžœ˜AMšžœ˜Mšœ˜—Mšœžœžœ™ šœ‘œžœ˜0Mšœžœžœžœ˜+—Mšœ˜M˜—K™K™Kšœžœ˜*Kšœžœ˜,Kšœžœ˜1Kšœžœ˜1K˜Mš œ žœžœžœžœžœ žœ˜