protected bool TryRecoverFromError(ParsingContext context) { var grammar = context.Language.Grammar; var parser = context.Parser; //1. We need to find a state in the stack that has a shift item based on error production (with error token), // and error terminal is current. This state would have a shift action on error token. ParserAction errorShiftAction = FindErrorShiftActionInStack(context); if (errorShiftAction == null) { return(false); //we failed to recover } context.AddTrace(Resources.MsgTraceRecoverFoundState, context.CurrentParserState); //2. Shift error token - execute shift action context.AddTrace(Resources.MsgTraceRecoverShiftError, errorShiftAction); errorShiftAction.Execute(context); //4. Now we need to go along error production until the end, shifting tokens that CAN be shifted and ignoring others. // We shift until we can reduce context.AddTrace(Resources.MsgTraceRecoverShiftTillEnd); while (true) { if (context.CurrentParserInput == null) { parser.ReadInput(); } if (context.CurrentParserInput.Term == grammar.Eof) { return(false); } //Check if we can reduce var nextAction = parser.GetNextAction(); if (nextAction == null) { parser.ReadInput(); continue; } if (nextAction is ReduceParserAction) { //We are reducing a fragment containing error - this is the end of recovery //Clear all input token queues and buffered input, reset location back to input position token queues; context.SetSourceLocation(context.CurrentParserInput.Span.Location); //Reduce error production - it creates parent non-terminal that "hides" error inside context.AddTrace(Resources.MsgTraceRecoverReducing); context.AddTrace(Resources.MsgTraceRecoverAction, nextAction); nextAction.Execute(context); //execute reduce return(true); //we recovered } // If it is not reduce, simply execute it (it is most likely shift) context.AddTrace(Resources.MsgTraceRecoverAction, nextAction); nextAction.Execute(context); //shift input token } }//method
protected bool TryRecoverFromError(ParsingContext context) { var grammar = context.Language.Grammar; var parser = context.Parser; //1. We need to find a state in the stack that has a shift item based on error production (with error token), // and error terminal is current. This state would have a shift action on error token. ParserAction errorShiftAction = FindErrorShiftActionInStack(context); if (errorShiftAction == null) return false; //we failed to recover context.AddTrace(Resources.MsgTraceRecoverFoundState, context.CurrentParserState); //2. Shift error token - execute shift action context.AddTrace(Resources.MsgTraceRecoverShiftError, errorShiftAction); errorShiftAction.Execute(context); //4. Now we need to go along error production until the end, shifting tokens that CAN be shifted and ignoring others. // We shift until we can reduce context.AddTrace(Resources.MsgTraceRecoverShiftTillEnd); while (true) { if (context.CurrentParserInput == null) parser.ReadInput(); if (context.CurrentParserInput.Term == grammar.Eof) return false; //Check if we can reduce var nextAction = parser.GetNextAction(); if (nextAction == null) { parser.ReadInput(); continue; } if (nextAction is ReduceParserAction) { //We are reducing a fragment containing error - this is the end of recovery //Clear all input token queues and buffered input, reset location back to input position token queues; context.SetSourceLocation(context.CurrentParserInput.Span.Location); //Reduce error production - it creates parent non-terminal that "hides" error inside context.AddTrace(Resources.MsgTraceRecoverReducing); context.AddTrace(Resources.MsgTraceRecoverAction, nextAction); nextAction.Execute(context); //execute reduce return true; //we recovered } // If it is not reduce, simply execute it (it is most likely shift) context.AddTrace(Resources.MsgTraceRecoverAction, nextAction); nextAction.Execute(context); //shift input token } }