private void PerformPanicRecovery(Lexeme z, List <ParserHead> shiftedHeads) { //Panic recovery //to the 1st head: //pop stack until there's a state S, which has a Goto action of a non-terminal A //discard input until there's an token a in Follow(A) //push Goto(s, A) into stack //discard all other heads m_heads.Clear(); m_heads.AddRange(shiftedHeads.Where(h => h.ErrorRecoverLevel == 0)); shiftedHeads.Clear(); ParserHead errorHead1 = m_errorCandidates[0]; m_errorCandidates.Clear(); IProduction p = errorHead1.PanicRecover(m_transitions, z.Value.Span, z.IsEndOfStream); ProductionBase productionBase = p as ProductionBase; if (productionBase != null) { var follow = productionBase.Info.Follow; m_heads.Add(errorHead1); throw new PanicRecoverException(follow); } }
private void PerformPanicRecovery(Lexeme z, List <ParserHead> shiftedHeads) { //Panic recovery //to the 1st head: //pop stack until there's a state S, which has a Goto action of a non-terminal A //discard input until there's an token a in Follow(A) //push Goto(s, A) into stack //discard all other heads m_heads.Clear(); m_heads.AddRange(shiftedHeads.Where(h => h.ErrorRecoverLevel == 0)); shiftedHeads.Clear(); ParserHead errorHead1 = m_errorCandidates[0]; m_errorCandidates.Clear(); var candidates = errorHead1.PanicRecover(m_transitions, z.Value.Span, z.IsEndOfStream); ISet <IProduction> follows = new HashSet <IProduction>(); foreach (var candidate in candidates) { ProductionBase p = candidate.Item2 as ProductionBase; follows.UnionWith(p.Info.Follow); m_heads.Add(candidate.Item1); } if (m_heads.Count > 0) { throw new PanicRecoverException(follows); } else { throw new ParsingFailureException("There's no way to recover from parser error"); } }
private void RecoverError(Lexeme z) { List <ParserHead> shiftedHeads = m_shiftedHeads; m_heads.Clear(); int errorHeadCount = m_errorCandidates.Count; Debug.Assert(errorHeadCount > 0); if (errorHeadCount > c_panicRecoveryThreshold) { //Panic recovery //to the 1st head: //pop stack until there's a state S, which has a Goto action of a non-terminal A //discard input until there's an token a in Follow(A) //push Goto(s, A) into stack //discard all other heads m_heads.Clear(); m_heads.AddRange(shiftedHeads.Where(h => h.ErrorRecoverLevel == 0)); shiftedHeads.Clear(); ParserHead errorHead1 = m_errorCandidates[0]; m_errorCandidates.Clear(); IProduction p = errorHead1.PanicRecover(m_transitions, z.Value.Span); var follow = (p as ProductionBase).Info.Follow; m_heads.Add(errorHead1); throw new PanicRecoverException(follow); } for (int i = 0; i < errorHeadCount; i++) { var head = m_errorCandidates[i]; if (!z.IsEndOfStream) { //option 1: remove //remove current token and continue var deleteHead = head.Clone(); deleteHead.IncreaseErrorRecoverLevel(); deleteHead.AddError(new ErrorRecord(m_errorDef.TokenUnexpectedId, z.Value.Span) { ErrorArgument = z.Value }); shiftedHeads.Add(deleteHead); //option 2: replace //replace the current input char with all possible shifts token and continue ReduceAndShiftForRecovery(z, head, shiftedHeads, m_errorDef.TokenMistakeId); } //option 3: insert //insert all possible shifts token and continue ReduceAndShiftForRecovery(z, head, m_heads, m_errorDef.TokenMissingId); } }