//TODO: need to rewrite, looks ugly private bool Recover() { //for recovery the current token must be error token, we rely on it if (!_currentToken.IsError()) { _currentToken = _context.CreateErrorToken(_currentToken.Location, _currentToken.Text); } //Check the current state and states in stack for error shift action - this would be recovery state. ActionRecord action = GetCurrentAction(); if (action == null || action.ActionType == ParserActionType.Reduce) { while (Stack.Count > 0) { _currentState = Stack.Top.State; Stack.Pop(1); action = GetCurrentAction(); if (action != null && action.ActionType != ParserActionType.Reduce) { break; //we found shift action for error token } }//while }//if if (action == null || action.ActionType == ParserActionType.Reduce) { return(false); //could not find shift action, cannot recover } //We found recovery state, and action contains ActionRecord for "error shift". Lets shift it. ExecuteShiftAction(action);//push the error token // Now shift all tokens from input that can be shifted. // These are the ones that are found in error production after the error. We ignore all other tokens // We stop when we find a state with reduce-only action. while (_currentToken.Terminal != Grammar.Eof) { //with current token, see if we can shift it. action = GetCurrentAction(); if (action == null) { NextToken(); //skip this token and continue reading input continue; } if (action.ActionType == ParserActionType.Reduce || action.ActionType == ParserActionType.Operator) { //we can reduce - let's reduce and return success - we recovered. ExecuteReduceAction(action); return(true); } //it is shift action, let's shift ExecuteShiftAction(action); }//while return(false); // }