<> <> <> DIRECTORY CS: TYPE USING [RopeFromStamp, z], IO: TYPE USING [ atom, card, EndOf, GetChar, GetIndex, int, Put, PutChar, PutF, PutRope, rope, SetIndex, STREAM], PrincOpsUtils: TYPE USING [Codebase], Rope: TYPE USING [Map, ROPE], SMCommentTable: TYPE USING [Index, Ref, Text], SMCommentTableOps: TYPE USING [Create, Explode, FindNext, Reset], SMFI: TYPE USING [BcdFileInfo, SrcFileInfo], SMLDriver: TYPE USING [Create], SMOps: TYPE USING [ModelState, MS], SMP1: TYPE P1 USING [InstallParseTable, Parse], SMParseData: TYPE USING [], SMTree: TYPE Tree USING [ AttrId, Handle, Id, Link, NodeName, Name, Number, Stamp, Text, null, nullId, nullName], SMTreeOps: TYPE TreeOps USING [ TM, Scan, Create, GetName, NthSon, PopTree, ScanSons], SMUtil: TYPE USING []; SMReaderImpl: CEDAR MONITOR -- this monitor protects the model parsing code IMPORTS CS, IO, PrincOpsUtils, Rope, SMCommentTableOps, SMLDriver, SMP1, SMTreeOps, SMParseData EXPORTS SMUtil, SMOps ~ { OPEN P1~~SMP1, Tree~~SMTree, TreeOps~~SMTreeOps; tabSize: CARDINAL ~ 4; <> parserCondition: CONDITION; parserBusy: BOOL _ FALSE; <> AcquireModelParser: ENTRY PROC ~ { ENABLE UNWIND => {NULL}; WHILE parserBusy DO WAIT parserCondition ENDLOOP; parserBusy _ TRUE}; ReleaseModelParser: ENTRY PROC ~ { ENABLE UNWIND => {NULL}; parserBusy _ FALSE; NOTIFY parserCondition}; <> ParseStream: PUBLIC PROC[m: SMOps.MS, source: IO.STREAM] RETURNS[root: Tree.Link] ~ { ENABLE UNWIND => {ReleaseModelParser[]}; AcquireModelParser[]; IF m.comments # NIL THEN (m.comments).Reset; {complete: BOOL _ TRUE; nTokens, nErrors: CARDINAL _ 0; TRUSTED {[complete, nTokens, nErrors] _ P1.Parse[m, source]}; root _ (IF complete AND nErrors = 0 THEN (m.tm).PopTree ELSE Tree.null); }; ReleaseModelParser}; <> WriteQuotedText: PROC[s: Rope.ROPE, out: IO.STREAM] ~ { EachChar: PROC[c: CHAR] RETURNS[BOOL_FALSE] ~ { out.PutChar[c]; IF c = '" THEN out.PutChar['"]}; IF s # NIL THEN { out.PutChar['"]; [] _ Rope.Map[base~s, action~EachChar]; out.PutChar['"]}; }; Indent: PROC[n: NAT, out: IO.STREAM] ~ { out.PutChar['\n]; THROUGH [1..n/tabSize] DO out.PutChar['\t] ENDLOOP; THROUGH [1..(n MOD tabSize)] DO out.PutChar[' ] ENDLOOP}; <> PrintTree: PUBLIC PROC[m: SMOps.MS, t: Tree.Link] ~ { PrintSubTree[m.out, t, 0]; (m.out).PutChar['\n]; IF m.comments # NIL THEN { index: SMCommentTable.Index _ 0; comments: BOOL _ FALSE; DO ref: SMCommentTable.Ref ~ (m.comments).FindNext[index]; IF ref = NIL THEN EXIT; IF ~comments THEN (m.out).PutRope["\nComments:"]; comments _ TRUE; (m.out).PutChar['\n]; (m.out).PutChar[' ]; (m.out).Put[IO.card[index]]; index _ SMCommentTableOps.Explode[ref].start + 1; ENDLOOP; IF comments THEN (m.out).PutChar['\n]}; }; PrintSubTree: PUBLIC PROC[out: IO.STREAM, t: Tree.Link, nBlanks: NAT] ~ { Printer: TreeOps.Scan ~ { Indent[nBlanks, out]; IF t = Tree.null THEN out.PutRope[""] ELSE WITH t SELECT FROM name: Tree.Name => PrintName[name, out]; id: Tree.Id => PrintId[id, out]; node: Tree.Handle => { WriteNodeName[node.name, out]; IF node.info # 0 THEN { out.PutRope[" info="]; out.Put[IO.card[node.info]]}; IF node.attrs # ALL[FALSE] THEN { IF node.info # 0 THEN out.PutChar[' ]; out.PutChar['(]; FOR i: Tree.AttrId IN Tree.AttrId DO IF node.attrs[i] THEN out.PutChar[VAL[i+'0.ORD]] ENDLOOP; out.PutChar[')]}; nBlanks _ nBlanks + 2; TreeOps.ScanSons[t, Printer]; nBlanks _ nBlanks - 2}; fiSrc: SMFI.SrcFileInfo => out.PutF["(fiSrc: %g)", IO.rope[fiSrc.localName]]; fiBcd: SMFI.BcdFileInfo => out.PutF["(fiBcd: %g)", IO.rope[fiBcd.localName]]; ENDCASE => PrintLiteral[t, out]; }; Printer[t]}; WriteNodeName: PROC[n: Tree.NodeName, out: IO.STREAM] ~ { out.PutRope[SELECT n FROM $none => "node", $lambda => "lambda", $let => "let", $arrow => "arrow", $arrow2 => "arrow2", $apply => "apply", $applyDefault => "applyDefault", $subscript => "subscript", $union => "union", $then => "then", $exclusion => "exclusion", $restriction => "restriction", $splitUpper => "splitUpper", $splitLower => "splitLower", $group => "group", $decl => "decl", $declElem => "declElem", $bind => "bind", $bindRec => "bindRec", $bindElem => "bindElem", $type => "type", $env => "env", $nil => "nil", $control => "control", $unitId => "unitId", $uiList => "uiList", $unQuote => "unQuote", $typeTYPE => "typeTYPE", $typeDECL => "typeDECL", $typeBINDING => "typeBINDING", $typePATTERN => "typePATTERN", $typeSTRING => "typeSTRING", $nBind => "nBind", $nBindRec => "nBindRec", $stamp => "stamp", $cross => "cross", $cross2 => "cross2", $locator => "locator", ENDCASE => ERROR] }; PrintLiteral: PROC[t: Tree.Link, out: IO.STREAM] ~ { WITH t SELECT FROM text: Tree.Text => WriteQuotedText[text, out]; num: Tree.Number => out.Put[IO.int[num^]]; stamp: Tree.Stamp => out.PutRope[CS.RopeFromStamp[stamp^]]; n: REF LONG CARDINAL => out.Put[IO.card[n^]]; ENDCASE => out.PutChar['?]; }; PrintName: PROC[name: Tree.Name, out: IO.STREAM] ~ { out.Put[IF name = Tree.nullName THEN IO.rope["(anon)"] ELSE IO.atom[name]]}; PrintId: PROC[id: Tree.Id, out: IO.STREAM] ~ { IF id = Tree.nullId THEN out.PutRope[""] ELSE { d: Tree.Handle ~ (IF id.db.name = $decl THEN id.db ELSE NARROW[id.db[1]]); out.Put[IO.atom[TreeOps.GetName[TreeOps.NthSon[d[id.p], 1]]]]; out.PutChar['[]; out.Put[IO.card[id.p]]; out.PutChar[']]}; }; <> NewModel: PUBLIC PROC[in, out, msgout: IO.STREAM] RETURNS[SMOps.MS] ~ { tm: TreeOps.TM; tm _ TreeOps.Create[CS.z]; RETURN [(CS.z).NEW[SMOps.ModelState _ [ in~in, out~out, msgOut~msgout, z~CS.z, tm~tm, comments~SMCommentTableOps.Create[CS.z], ls~SMLDriver.Create[CS.z, tm, out]]]] }; ErrorContext: PUBLIC PROC[source, out: IO.STREAM, message: Rope.ROPE, tokenIndex: INT] ~ { saveIndex: INT ~ source.GetIndex; lineIndex, start: INT _ tokenIndex; char: CHAR; FOR n: NAT IN [1..100] UNTIL lineIndex = 0 DO lineIndex _ lineIndex - 1; source.SetIndex[lineIndex]; IF source.GetChar[] = '\n THEN EXIT; start _ lineIndex; ENDLOOP; source.SetIndex[start]; -- start points for the first char on the line FOR n: NAT IN [1..100] UNTIL source.EndOf DO char _ source.GetChar[]; SELECT char FROM '\n => EXIT; ENDCASE => out.PutChar[char]; ENDLOOP; out.PutChar['\n]; source.SetIndex[start]; UNTIL source.GetIndex[] = tokenIndex OR source.EndOf DO char _ source.GetChar[]; -- print out the right number of spaces out.PutChar[IF char = '\t THEN '\t ELSE ' ]; ENDLOOP; out.PutF["^ %g [%d]\n", IO.rope[message], IO.card[tokenIndex]]; source.SetIndex[saveIndex]}; <> TRUSTED { P1.InstallParseTable[LOOPHOLE[PrincOpsUtils.Codebase[LOOPHOLE[SMParseData]]]]}; }.