DIRECTORY IO USING [Put1, PutRope, PutChar, STREAM], MPP1 USING [Token, Value, ValueSeq, ValueStack, nullValue, nullToken, INTSeq, ActionEntrySeq, AssignDescriptors, Atom, ErrorContext, ProcessQueue, ResetScanIndex, ScanInit, ScanReset], MPParseTable USING [ActionEntry, ActionTag, defaultMarker, endMarker, finalState, IndexTableRef, initialState, initialSymbol, InitIndexTable, InitNActions, InitNLengths, InitNStarts, InitNSymbols, InitNTDefaults, InitProdData, InitTActions, InitTLengths, InitTStarts, InitTSymbols, InitVocabulary, NActionsRef, NLengthsRef, NStartsRef, NSymbolsRef, NTDefaultsRef, NTIndex, NTState, NTSymbol, ProdDataRef, State, TActionsRef, TIndex, TLengthsRef, TStartsRef, TSymbol, TSymbolsRef, VocabularyRef], Rope USING [ROPE]; MPParser: PROGRAM IMPORTS IO, MPP1, MPParseTable EXPORTS MPP1 = { OPEN MPParseTable; ErrorLimit: CARDINAL = 10; Scan: ActionTag = [FALSE, 0]; inputSymbol: TSymbol; input: PROC [errPut: IO.STREAM] RETURNS [token: MPP1.Token]; inputLoc: INT ¬ 0; inputValue: MPP1.Value ¬ MPP1.nullValue; lastToken: MPP1.Token ¬ MPP1.nullToken; NullSymbol: TSymbol = 0; firstInit: BOOL ¬ TRUE; s: REF StateSeq ¬ NIL; StateSeq: TYPE = RECORD[SEQUENCE length: CARDINAL OF State]; l: REF MPP1.INTSeq ¬ NIL; v: MPP1.ValueStack ¬ NIL; top: CARDINAL ¬ 0; q: REF MPP1.ActionEntrySeq ¬ NIL; qI: CARDINAL; vocabIndex: IndexTableRef ¬ NIL; vocabBody: VocabularyRef ¬ NIL; tStart: TStartsRef ¬ NIL; tLength: TLengthsRef ¬ NIL; tSymbol: TSymbolsRef ¬ NIL; tAction: TActionsRef ¬ NIL; nStart: NStartsRef ¬ NIL; nLength: NLengthsRef ¬ NIL; nSymbol: NSymbolsRef ¬ NIL; nAction: NActionsRef ¬ NIL; ntDefaults: NTDefaultsRef ¬ NIL; prodData: ProdDataRef ¬ NIL; ParseInit: PROC [source: Rope.ROPE] = { IF vocabIndex = NIL THEN [vocabIndex, vocabBody] ¬ MPP1.ScanInit[source]; IF prodData = NIL THEN { tStart ¬ InitTStarts[]; tLength ¬ InitTLengths[]; tSymbol ¬ InitTSymbols[]; tAction ¬ InitTActions[]; nStart ¬ InitNStarts[]; nLength ¬ InitNLengths[]; nSymbol ¬ InitNSymbols[]; nAction ¬ InitNActions[]; ntDefaults ¬ InitNTDefaults[]; prodData ¬ InitProdData[]; }; IF firstInit THEN { ExpandStack[64]; ExpandQueue[64]; firstInit ¬ FALSE; }; }; InputLoc: PUBLIC SAFE PROC RETURNS [INT] = TRUSTED {RETURN [inputLoc]}; Parse: PUBLIC SAFE PROC [source: Rope.ROPE, errPut: IO.STREAM] RETURNS [complete: BOOL, nTokens, nErrors: CARDINAL] = TRUSTED { currentState: State; i, valid, m: CARDINAL; -- stack pointers action: ActionEntry; ParseInit[source]; input ¬ MPP1.Atom; nErrors ¬ 0; complete ¬ TRUE; i ¬ top ¬ valid ¬ 0; qI ¬ 0; s[0] ¬ currentState ¬ initialState; lastToken.class ¬ NullSymbol; inputSymbol ¬ initialSymbol; inputValue ¬ MPP1.nullValue; inputLoc ¬ 0; WHILE currentState # finalState DO { tI: TIndex ¬ tStart[currentState]; FOR tI IN [tI .. tI + tLength[currentState]) DO SELECT tSymbol[tI] FROM inputSymbol, defaultMarker => EXIT ENDCASE; REPEAT FINISHED => GOTO syntaxError; ENDLOOP; action ¬ tAction[tI]; IF ~action.tag.reduce -- scan or scan reduce entry THEN { IF qI > 0 THEN { FOR k: CARDINAL IN (valid..i] DO s[k] ¬ s[top+(k-valid)] ENDLOOP; MPP1.ProcessQueue[qI, top]; qI ¬ 0}; IF (top ¬ valid ¬ i ¬ i+1) >= s.length THEN ExpandStack[64]; lastToken.class ¬ inputSymbol; v[i] ¬ inputValue; l[i] ¬ inputLoc; [[inputSymbol, inputValue, inputLoc]] ¬ input[errPut]}; WHILE action.tag # Scan DO IF qI >= q.length THEN ExpandQueue[64]; q[qI] ¬ action; qI ¬ qI + 1; i ¬ i-action.tag.pLength; currentState ¬ s[IF i > valid THEN top+(i-valid) ELSE (valid ¬ i)]; { lhs: NTSymbol = prodData[action.transition].lhs; IF currentState <= LAST[NTState] THEN { nI: NTIndex ¬ nStart[currentState]; FOR nI IN [nI..nI+nLength[currentState]) DO IF lhs = nSymbol[nI] THEN {action ¬ nAction[nI]; GO TO nFound}; ENDLOOP}; action ¬ ntDefaults[lhs]; EXITS nFound => NULL; }; i ¬ i+1; ENDLOOP; IF (m ¬ top+(i-valid)) >= s.length THEN ExpandStack[64]; s[m] ¬ currentState ¬ action.transition; EXITS syntaxError => { lastToken.value ¬ v[top]; lastToken.index ¬ l[top]; top ¬ top - 1; complete ¬ SyntaxError[(nErrors¬nErrors+1)>ErrorLimit, errPut]; i ¬ valid ¬ top; qI ¬ 0; lastToken.class ¬ NullSymbol; currentState ¬ s[i]; [[inputSymbol, inputValue, inputLoc]] ¬ input[errPut]; IF ~complete THEN EXIT}; }; ENDLOOP; MPP1.ProcessQueue[qI, top]; {n: CARDINAL; [nTokens, n] ¬ MPP1.ScanReset[]; nErrors ¬ nErrors + n}; RETURN}; ExpandStack: PROC [delta: CARDINAL] = { newS: REF StateSeq; newL: REF MPP1.INTSeq; newV: MPP1.ValueStack ¬ NIL; newSize: CARDINAL = (IF s = NIL THEN 0 ELSE s.length) + delta; newS ¬ NEW[StateSeq[newSize]]; newL ¬ NEW[MPP1.INTSeq[newSize]]; newV ¬ IF v # NIL AND v.length >= newSize THEN v ELSE NEW[MPP1.ValueSeq[newSize]]; IF s # NIL THEN FOR i: CARDINAL IN [0..s.length) DO newS[i] ¬ s[i]; newL[i] ¬ l[i]; newV[i] ¬ v[i] ENDLOOP; s ¬ newS; l ¬ newL; v ¬ newV; MPP1.AssignDescriptors[qd:q, vd:v, ld:l, pp:prodData]}; ExpandQueue: PROC [delta: CARDINAL] = { newSize: CARDINAL = (IF q = NIL THEN 0 ELSE q.length) + delta; newQ: REF MPP1.ActionEntrySeq ¬ NEW[MPP1.ActionEntrySeq[newSize]]; IF q # NIL THEN FOR i: CARDINAL IN [0..q.length) DO newQ[i] ¬ q[i] ENDLOOP; q ¬ newQ; MPP1.AssignDescriptors[qd:q, vd:v, ld:l, pp:prodData]}; MinScanLimit: CARDINAL = 4; MaxScanLimit: CARDINAL = 12; InsertLimit: CARDINAL = 2; DiscardLimit: CARDINAL = 10; TreeSize: CARDINAL = 256; CheckSize: CARDINAL = MaxScanLimit+InsertLimit+2; ParserID: PUBLIC SAFE PROC RETURNS [Rope.ROPE] = TRUSTED {RETURN ["Flako!"]}; NodeIndex: TYPE = CARDINAL [0..TreeSize); NullIndex: NodeIndex = 0; StackNode: TYPE = RECORD[ father: NodeIndex, last: NodeIndex, state: State, symbol: TSymbol, aLeaf, bLeaf: BOOLEAN, link: NodeIndex]; tree: REF ARRAY [0..TreeSize) OF StackNode; nextNode: NodeIndex ¬ 0; maxNode: NodeIndex ¬ 0; treeLimit: CARDINAL ¬ 0; TreeFull: SIGNAL = CODE; Allocate: PROC [parent, pred: NodeIndex, terminal: TSymbol, stateNo: State] RETURNS [index: NodeIndex] = { IF (index ¬ nextNode) >= treeLimit THEN SIGNAL TreeFull; maxNode ¬ MAX[index, maxNode]; tree[index] ¬ StackNode[ father: parent, last: pred, state: stateNo, symbol: terminal, aLeaf: FALSE, bLeaf: FALSE, link: NullIndex]; nextNode ¬ nextNode+1; RETURN}; HashSize: INTEGER = 64; -- should depend on state count ? hashTable: REF ARRAY [0..HashSize) OF NodeIndex; ParsingMode: TYPE = {ATree, BTree, Checking}; parseMode: ParsingMode ¬ Checking; LinkHash: PROC [n: NodeIndex] = { htIndex: [0..HashSize) = tree[n].state MOD HashSize; tree[n].link ¬ hashTable[htIndex]; hashTable[htIndex] ¬ n}; ExistingConfiguration: PROC [stack: StackRep] RETURNS [NodeIndex] = { n, n1, n2: NodeIndex; s1, s2: State; htIndex: [0..HashSize); aTree: BOOLEAN; SELECT parseMode FROM ATree => aTree ¬ TRUE; BTree => aTree ¬ FALSE; ENDCASE => RETURN [NullIndex]; htIndex ¬ stack.extension MOD HashSize; FOR n ¬ hashTable[htIndex], tree[n].link UNTIL n = NullIndex DO IF (IF aTree THEN tree[n].aLeaf ELSE tree[n].bLeaf) THEN { s1 ¬ stack.extension; s2 ¬ tree[n].state; n1 ¬ stack.leaf; n2 ¬ tree[n].father; DO IF s1 # s2 THEN EXIT; IF n1 = n2 THEN RETURN [n]; s1 ¬ tree[n1].state; s2 ¬ tree[n2].state; n1 ¬ tree[n1].father; n2 ¬ tree[n2].father; ENDLOOP}; ENDLOOP; RETURN [NullIndex]}; FindNode: PROC [parent, pred: NodeIndex, stateNo: State] RETURNS [index: NodeIndex] = { index ¬ ExistingConfiguration[[leaf:parent, extension:stateNo]]; IF index = NullIndex THEN { index ¬ Allocate[parent, pred, 0, stateNo]; SELECT parseMode FROM ATree => {tree[index].aLeaf ¬ TRUE; LinkHash[index]}; BTree => {tree[index].bLeaf ¬ TRUE; LinkHash[index]}; ENDCASE => NULL}; RETURN}; ExtState: TYPE = [FIRST[State] .. LAST[State]+1]; NullState: ExtState = LAST[ExtState]; StackRep: TYPE = RECORD[ leaf: NodeIndex, extension: ExtState]; GetNTEntry: PROC [state: State, lhs: NTSymbol] RETURNS [ActionEntry] = { IF state <= LAST[NTState] THEN { nI: NTIndex ¬ nStart[state]; FOR nI IN [nI..nI+nLength[state]) DO IF lhs = nSymbol[nI] THEN RETURN [nAction[nI]] ENDLOOP}; RETURN [ntDefaults[lhs]]}; ActOnStack: PROC [stack: StackRep, action: ActionEntry, nScanned: [0..1]] RETURNS [StackRep] = { currentNode, thread: NodeIndex ¬ stack.leaf; count: CARDINAL ¬ nScanned; currentState: State; IF stack.extension = NullState THEN currentState ¬ tree[currentNode].state ELSE {currentState ¬ stack.extension; count ¬ count + 1}; UNTIL action.tag = Scan DO IF count > action.tag.pLength -- can be one greater THEN { currentNode ¬ FindNode[currentNode, thread, currentState]; count ¬ count - 1}; UNTIL count = action.tag.pLength DO currentNode ¬ tree[currentNode].father; count ¬ count + 1 ENDLOOP; currentState ¬ tree[currentNode].state; count ¬ 1; action ¬ GetNTEntry[currentState, prodData[action.transition].lhs]; ENDLOOP; IF count > 1 THEN currentNode ¬ FindNode[currentNode, thread, currentState]; stack.leaf ¬ currentNode; stack.extension ¬ action.transition; RETURN [stack]}; ParseStep: PROC [stack: StackRep, tSmb: TSymbol] RETURNS [StackRep] = { currentState: State ¬ IF stack.extension = NullState THEN tree[stack.leaf].state ELSE stack.extension; scanned: BOOLEAN ¬ FALSE; WHILE ~scanned DO action: ActionEntry; count: [0..1]; tI: TIndex ¬ tStart[currentState]; FOR tI IN [tI..tI+tLength[currentState]) DO SELECT tSymbol[tI] FROM tSmb, defaultMarker => EXIT ENDCASE; REPEAT FINISHED => RETURN [[NullIndex, NullState]]; ENDLOOP; action ¬ tAction[tI]; IF ~action.tag.reduce THEN {count ¬ 1; scanned ¬ TRUE} -- shift or shift reduce ELSE count ¬ 0; stack ¬ ActOnStack[stack, action, count]; currentState ¬ stack.extension; ENDLOOP; RETURN [stack]}; Insert: TYPE = ARRAY [0 .. 1+InsertLimit) OF MPP1.Token; newText: REF Insert; insertCount: CARDINAL ¬ 0; Buffer: TYPE = ARRAY [0 .. 1 + DiscardLimit + (MaxScanLimit+InsertLimit)) OF MPP1.Token; sourceText: REF Buffer; scanBase, scanLimit: CARDINAL ¬ 0; Advance: PROC [errPut: IO.STREAM] = {sourceText[scanLimit] ¬ input[errPut]; scanLimit ¬ scanLimit+1}; Discard: PROC = {scanBase ¬ scanBase+1}; UnDiscard: PROC = {scanBase ¬ scanBase-1}; RecoverInput: PROC [errPut: IO.STREAM] RETURNS [token: MPP1.Token ¬ MPP1.nullToken] = { IF insertCount <= InsertLimit THEN { token ¬ newText[insertCount]; IF (insertCount ¬ insertCount+1) > InsertLimit THEN newText ¬ NIL} ELSE { token ¬ sourceText[scanBase]; IF (scanBase ¬ scanBase+1) = scanLimit THEN {sourceText ¬ NIL; input ¬ MPP1.Atom}}; RETURN}; best: RECORD [ nAccepted: CARDINAL ¬ 0, nPassed: [0..1] ¬ 0, node: NodeIndex ¬ 0, mode: ParsingMode ¬ Checking, nDiscards: CARDINAL ¬ 0]; RightScan: PROC [node: NodeIndex] RETURNS [stop: BOOLEAN] = { savedNextNode: NodeIndex = nextNode; savedMode: ParsingMode = parseMode; savedLimit: CARDINAL = treeLimit; stack: StackRep ¬ [leaf:node, extension:NullState]; state: State ¬ tree[node].state; nAccepted: CARDINAL ¬ 0; parseMode ¬ Checking; treeLimit ¬ TreeSize; FOR i: CARDINAL IN [scanBase .. scanLimit) DO IF state = finalState THEN { nAccepted ¬ IF (sourceText[i].class = endMarker) THEN scanLimit-scanBase ELSE 0; EXIT}; stack ¬ ParseStep[stack, sourceText[i].class]; IF stack.leaf = NullIndex THEN EXIT; nAccepted ¬ nAccepted + 1; state ¬ stack.extension; ENDLOOP; nextNode ¬ savedNextNode; treeLimit ¬ savedLimit; SELECT (parseMode ¬ savedMode) FROM ATree => IF nAccepted + 1 > best.nAccepted + best.nPassed THEN best ¬ [nAccepted, 1, node, ATree, scanBase-1]; BTree => IF nAccepted > best.nAccepted + best.nPassed THEN best ¬ [nAccepted, 0, node, BTree, scanBase]; ENDCASE; RETURN [nAccepted >= MaxScanLimit]}; RowRecord: TYPE = RECORD [ index, limit: CARDINAL, stack: StackRep, next: RowHandle]; RowHandle: TYPE = REF RowRecord; NextRow: PROC [list: RowHandle] RETURNS [row: RowHandle] = { t: TSymbol ¬ TSymbol.FIRST; row ¬ NIL; FOR r: RowHandle ¬ list, r.next UNTIL r = NIL DO IF r.index < r.limit THEN { s: TSymbol = tSymbol[r.index]; IF row = NIL OR s < t THEN {row ¬ r; t ¬ s}}; ENDLOOP; RETURN}; Position: TYPE = {after, before}; Length: TYPE = CARDINAL [0..InsertLimit]; levelStart: ARRAY Position OF ARRAY Length OF NodeIndex ¬ [ALL[0], ALL[0]]; levelEnd: ARRAY Position OF ARRAY Length OF NodeIndex ¬ [ALL[0], ALL[0]]; AddLeaf: PROC [stack: StackRep, s: TSymbol, thread: NodeIndex] RETURNS [stop: BOOLEAN] = { saveNextNode: NodeIndex = nextNode; stack ¬ ParseStep[stack, s]; IF stack.leaf = NullIndex OR ExistingConfiguration[stack] # NullIndex THEN {nextNode ¬ saveNextNode; stop ¬ FALSE} ELSE { newLeaf: NodeIndex = Allocate[stack.leaf, thread, s, stack.extension]; SELECT parseMode FROM ATree => tree[newLeaf].aLeaf ¬ TRUE; BTree => tree[newLeaf].bLeaf ¬ TRUE; ENDCASE => ERROR; LinkHash[newLeaf]; stop ¬ RightScan[newLeaf]}; RETURN}; GrowTree: PROC [p: Position, n: Length] RETURNS [stop: BOOLEAN] = { tI, tLimit: TIndex; stack: StackRep; state: State; rowList, r: RowHandle; rowList ¬ NIL; FOR i: NodeIndex IN [levelStart[p][n-1] .. levelEnd[p][n-1]) DO IF tree[i].symbol # 0 OR n = 1 THEN { rowList ¬ NIL; stack ¬ [leaf:i, extension:NullState]; state ¬ tree[i].state; DO tI ¬ tStart[state]; tLimit ¬ tI + tLength[state]; r ¬ NEW[RowRecord ¬ [index: tI, limit: tLimit, stack: stack, next: rowList]]; rowList ¬ r; IF tI = tLimit OR tSymbol[tLimit-1] # defaultMarker THEN EXIT; r.limit ¬ r.limit - 1; stack ¬ ActOnStack[stack, tAction[tLimit-1], 0]; state ¬ stack.extension; ENDLOOP; UNTIL (r ¬ NextRow[rowList]) = NIL DO IF AddLeaf[r.stack, tSymbol[r.index], i] THEN GO TO found; r.index ¬ r.index + 1; ENDLOOP}; REPEAT found => stop ¬ TRUE; FINISHED => stop ¬ FALSE; ENDLOOP; rowList ¬ NIL; RETURN}; CheckTree: PROC [p: Position, n: Length] RETURNS [stop: BOOLEAN] = { FOR i: NodeIndex IN [levelStart[p][n] .. levelEnd[p][n]) DO ENABLE TreeFull => CONTINUE; IF RightScan[i] THEN GO TO found; REPEAT found => stop ¬ TRUE; FINISHED => stop ¬ FALSE; ENDLOOP; RETURN}; Accept: PROC [put: IO.STREAM] RETURNS [success: BOOL] = { s: TSymbol; discardBase: CARDINAL = best.nPassed; insertCount ¬ 1+InsertLimit; FOR p: NodeIndex ¬ best.node, tree[p].last WHILE p > rTop DO IF (s ¬ tree[p].symbol) # 0 THEN { insertCount ¬ insertCount-1; newText[insertCount] ¬ MPP1.Token[s, MPP1.nullValue, inputLoc]}; ENDLOOP; scanBase ¬ discardBase; IF best.nDiscards # 0 THEN { put.PutRope["Text deleted is: "]; FOR j: CARDINAL IN [1 .. best.nDiscards] DO TypeSym[sourceText[scanBase].class, put]; scanBase ¬ scanBase + 1; ENDLOOP}; IF insertCount <= InsertLimit THEN { IF scanBase # discardBase THEN put.PutChar['\n]; put.PutRope["Text inserted is: "]; FOR j: CARDINAL IN [insertCount .. InsertLimit] DO TypeSym[newText[j].class, put] ENDLOOP}; IF discardBase = 1 THEN {insertCount ¬ insertCount-1; newText[insertCount] ¬ sourceText[0]}; IF insertCount > InsertLimit THEN newText ¬ NIL; IF scanBase + best.nAccepted < scanLimit THEN success ¬ MPP1.ResetScanIndex[sourceText[scanBase+best.nAccepted].index] ELSE success ¬ TRUE; scanLimit ¬ scanBase + best.nAccepted; input ¬ RecoverInput}; TypeSym: PROC [sym: TSymbol, put: IO.STREAM] = { put.PutChar[' ]; IF sym IN [1..endMarker) THEN { IF vocabIndex = NIL THEN vocabIndex ¬ InitIndexTable[]; IF vocabBody = NIL THEN vocabBody ¬ InitVocabulary[]; FOR i: NAT IN [vocabIndex[sym-1]..vocabIndex[sym]) DO put.PutChar[vocabBody[i]]; ENDLOOP; } ELSE put.Put1[[integer[sym]]]; }; rTop: NodeIndex ¬ 0; Recover: PROC [errPut: IO.STREAM] = { ModeMap: ARRAY Position OF ParsingMode = [ATree, BTree]; stack: StackRep; treeLimit ¬ TreeSize - CheckSize; hashTable­ ¬ ALL[NullIndex]; rTop ¬ NullIndex; nextNode ¬ maxNode ¬ 1; best.nAccepted ¬ 0; best.nPassed ¬ 1; best.mode ¬ ATree; sourceText[0] ¬ lastToken; sourceText[1] ¬ MPP1.Token[inputSymbol, inputValue, inputLoc]; scanBase ¬ 1; scanLimit ¬ 2; THROUGH [1 .. MaxScanLimit) DO Advance[errPut] ENDLOOP; FOR i: CARDINAL IN [0 .. top) DO rTop ¬ Allocate[rTop, rTop, 0, s[i]] ENDLOOP; parseMode ¬ BTree; levelStart[before][0] ¬ rTop ¬ FindNode[rTop, rTop, s[top]]; tree[rTop].bLeaf ¬ TRUE; levelEnd[before][0] ¬ nextNode; parseMode ¬ ATree; stack ¬ ParseStep[[leaf:rTop, extension:NullState], lastToken.class]; rTop ¬ FindNode[stack.leaf, rTop, stack.extension]; tree[rTop].symbol ¬ lastToken.class; tree[rTop].aLeaf ¬ tree[rTop].bLeaf ¬ TRUE; levelStart[after][0] ¬ rTop; levelEnd[after][0] ¬ nextNode; FOR level: Length IN [1 .. LAST[Length]] DO FOR place: Position IN Position DO parseMode ¬ ModeMap[place]; IF place = before THEN UnDiscard[]; levelStart[place][level] ¬ nextNode; IF GrowTree[place, level !TreeFull => CONTINUE] THEN GO TO found; levelEnd[place][level] ¬ nextNode; THROUGH [1 .. level) DO Discard[]; IF CheckTree[place, level] THEN GO TO found; ENDLOOP; Discard[]; IF place = after THEN Advance[errPut]; FOR inserts: CARDINAL IN [0 .. level] DO IF CheckTree[place, inserts] THEN GO TO found ENDLOOP; THROUGH [1..level] DO UnDiscard[] ENDLOOP; IF place = before THEN Discard[]; ENDLOOP; REPEAT found => NULL; FINISHED => { threshold: CARDINAL ¬ (MinScanLimit+MaxScanLimit)/2; THROUGH [1..LAST[Length]] DO Discard[]; Advance[errPut] ENDLOOP; UNTIL scanBase > DiscardLimit DO IF best.nAccepted >= threshold THEN GO TO found; Discard[]; FOR inserts: CARDINAL IN Length DO FOR place: Position IN Position DO parseMode ¬ ModeMap[place]; IF place = before THEN UnDiscard[]; IF CheckTree[place, inserts] THEN GO TO found; IF place = before THEN Discard[]; ENDLOOP; ENDLOOP; Advance[errPut]; threshold ¬ IF threshold > MinScanLimit THEN threshold-1 ELSE MinScanLimit; REPEAT found => NULL; FINISHED => IF best.nAccepted < MinScanLimit THEN {best.mode ¬ ATree; best.nPassed ¬ 1}; ENDLOOP}; ENDLOOP}; SyntaxError: PROC [abort: BOOL, put: IO.STREAM] RETURNS [success: BOOL] = { IF abort THEN { MPP1.ErrorContext["Syntax Error", inputLoc, put]; put.PutRope["... Parse abandoned."]; put.PutChar['\n]; success ¬ FALSE} ELSE { sourceText ¬ NEW[Buffer ¬ ALL[MPP1.nullToken]]; newText ¬ NEW[Insert ¬ ALL[MPP1.nullToken]]; tree ¬ NEW[ARRAY [0..TreeSize) OF StackNode]; hashTable ¬ NEW[ARRAY [0..HashSize) OF NodeIndex]; Recover[put ! TreeFull => CONTINUE]; hashTable ¬ NIL; MPP1.ErrorContext["Syntax Error", sourceText[IF best.mode=BTree THEN 0 ELSE 1].index, put]; IF ~(success ¬ best.nAccepted >= MinScanLimit) OR ~Accept[put] THEN { put.PutRope["No recovery found."]; newText ¬ NIL; sourceText ¬ NIL}; tree ¬ NIL; vocabIndex ¬ NIL; put.PutChar['\n]}; put.PutChar['\n]; RETURN}; }. hMPParser.mesa Copyright Ó 1985, 1986, 1987, 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. derived from Compiler>Parser.Mesa Satterthwaite, January 12, 1981 12:58 PM Russ Atkinson (RRA) January 19, 1987 7:48:58 pm PST JKF May 24, 1990 9:18:48 am PDT Michael Plass, September 5, 1991 11:44 pm PDT globals transition tables for terminal input symbols transition tables for terminal input symbols transition tables for nonterminal input symbols production information initialization/termination * * * * Main Parsing Procedures * * * * -- * * * * Error Recovery Section * * * * -- parameters of error recovery debugging tree management parsing simulation text buffer management acceptance checking strategy management stack node indices try simple insertion (inserts=level) try discards followed by 0 or more insertions undo discards at this level Ê[–(cedarcode) style•NewlineDelimiter ˜codešœ ™ Kšœ ÏeœU™`Kšœ!™!KšÏy)™)K™3K™K™-—K˜šÏk ˜ KšŸœŸœŸœ˜*KšŸœŸœ®˜¸Kšœ ŸœÝ˜ïKšœŸœŸœ˜K˜—šÏnœŸ˜KšŸœŸœŸœ˜KšŸœŸœ˜šŸœ˜K˜——šœ™š  œŸœ˜K˜—š œŸœ˜K˜—˜K˜—Kš œŸœ ŸœŸœŸœ Ÿœ˜KšœŸœ˜KšœŸœŸœ˜!šœŸœŸœŸœ˜)KšŸœ˜KšŸœŸœŸœ˜!—š ŸœŸœŸœŸœŸœŸœ˜0KšŸœ4Ÿœ˜>—K˜KšŸœ3˜7K˜—š  œŸœ Ÿœ˜'Kš œ ŸœŸœŸœŸœŸœ˜>Kš œŸœŸœŸœŸœ˜BKšŸœŸœŸœŸœŸœŸœŸœŸœ˜NK˜ KšŸœ3˜7K˜——Kšœ)™)šœ™Kš  œŸœ˜Kš  œŸœ˜Kš  œŸœ˜Kš  œŸœ˜Kš œŸœ˜Kš  œŸœ˜1K˜—šœ ™ Kš œŸœŸœŸœŸœŸœŸœŸœ ˜MK˜—šœ™Kšœ ŸœŸœ˜)š  œ˜K˜—šœ ŸœŸœ˜K˜K˜K˜K˜KšœŸœ˜K˜K˜—KšœŸœŸœŸœ ˜+K˜K˜Kšœ Ÿœ˜š œŸœŸœ˜K˜—š œŸœ>Ÿœ˜jKšŸœ!ŸœŸœ ˜8Kšœ Ÿœ˜˜K˜K˜ K˜K˜KšœŸœ Ÿœ˜K˜—KšœŸœ˜ K˜—Kš œŸœ¡!˜@šœ ŸœŸœŸœ ˜0K˜—Kšœ Ÿœ˜-šœ"˜"K˜—š œŸœ˜!Kšœ'Ÿœ ˜4K˜šŸ˜KšŸœŸœ˜,—KšŸœ˜—K˜šŸœ˜KšŸœŸœ ¡˜AKšŸœ ˜—K˜)K˜KšŸœ˜—KšŸœ ˜K˜——šœ™Kš œŸœŸœŸœŸœ˜8Kšœ Ÿœ˜šœ Ÿœ˜K˜—šœŸœ˜KšŸœ6ŸœŸœ˜I—Kšœ Ÿœ˜šœŸœ˜"K˜—š œŸœ ŸœŸœ˜#K˜AK˜—š œŸœ˜(K˜—š  œŸœ˜*K˜—š  œŸœ ŸœŸœŸœ Ÿœ Ÿœ˜WšŸœ˜šŸœ˜K˜šŸœ,˜.KšŸœ Ÿœ˜——šŸœ˜K˜šŸœ$˜&KšŸœŸœ Ÿœ˜,———KšŸœ˜K˜——šœ™šœŸœ˜Kšœ Ÿœ˜K˜K˜K˜Kšœ Ÿœ˜K˜—š  œŸœŸœŸœ˜=K˜$K˜#Kšœ Ÿœ ˜!K˜3K˜ Kšœ Ÿœ˜K˜,šŸœŸœŸœ˜+KšŸ˜šŸœ˜šŸœ˜šœ Ÿœ"˜0KšŸœ˜KšŸœ˜—KšŸœ˜——K˜.KšŸœŸœŸœ˜$K˜4KšŸœ˜—K˜2šŸœŸ˜#˜šŸœ.˜0KšŸœ0˜4——˜šŸœ*˜,KšŸœ.˜2——KšŸœ˜—KšŸœ˜$K˜K˜——šœ™šœ ŸœŸœ˜KšœŸœ˜K˜K˜K˜—šœ ŸœŸœ ˜ K˜—š œŸœŸœ˜KšŸœŸœ˜K˜#K˜šŸœŸœ)˜EKšŸœ"Ÿœ˜-šŸœ˜K˜FšŸœ Ÿ˜KšœŸœ˜$KšœŸœ˜$KšŸœŸœ˜—K˜K˜——KšŸœ˜K˜—š œŸœŸœŸœ˜CK˜K˜K˜ K˜Kšœ Ÿœ˜šŸœŸœ*˜=KšŸ˜šŸœŸœ˜šŸœ˜Kšœ Ÿœ˜˜>KšŸ˜K˜2KšœŸœF˜MK˜ KšŸœ Ÿœ#ŸœŸœ˜>K˜K˜0K˜KšŸœ˜—šŸœŸœ˜#KšŸ˜KšŸœ'ŸœŸœŸœ˜:K˜KšŸœ˜ ———šŸ˜KšœŸœ˜KšŸœ Ÿœ˜—KšŸœ˜—Kšœ Ÿœ˜KšŸœ˜K˜—š  œŸœŸœŸœ˜DšŸœŸœ%˜8KšŸ˜KšŸœ Ÿœ˜KšŸœŸœŸœŸœ˜!šŸ˜KšœŸœ˜KšŸœ Ÿœ˜—KšŸœ˜—KšŸœ˜K˜—š  œŸœŸœŸœŸœ Ÿœ˜9K˜ Kšœ Ÿœ˜%K˜šŸœ(Ÿœ ˜9KšŸ˜šŸœ˜šŸœ˜K˜KšœŸœ Ÿœ˜@——KšŸœ˜—K˜šŸœ˜šŸœ˜K˜!šŸœŸœŸœ˜(KšŸ˜K˜CKšŸœ˜ ———šŸœ˜šŸœ˜KšŸœŸœ˜0K˜"šŸœŸœŸœ˜/KšŸœ"Ÿœ˜-———šŸœ˜KšŸœE˜I—KšŸœŸœ Ÿœ˜0šŸœ&˜(KšŸœ Ÿœ:˜MKšŸœ Ÿœ˜—K˜&K˜K˜—š œŸœŸœŸœ˜0Kšœ˜šŸœŸœ˜šŸœ˜KšŸœŸœŸœ˜7KšŸœ ŸœŸœ˜5šŸœŸœŸœ&Ÿ˜5Kšœ˜KšŸœ˜—K˜—KšŸœ˜—Kšœ˜K˜K˜——šœ™˜K˜—š œŸœ ŸœŸœ˜%Kš œŸœ Ÿœ˜8K˜K˜K˜!Kšœ Ÿœ ˜K˜*K˜K˜:K˜KšœŸœ*˜>K˜KšŸœŸœŸœ˜8šŸœŸœŸœ ˜KšŸœ&Ÿœ˜0—K˜K˜šŸœ˜K˜"Kšœ ŸœŸœ˜"——KšœŸœ˜ Kšœ Ÿœ˜K˜——K˜KšŸœ˜K˜——Kšœ˜K˜K˜—…—G cc