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
public override void Execute(ParsingContext context) { var traceEnabled = context.TracingEnabled; if (traceEnabled) { context.AddTrace("Conditional Parser Action."); } for (int i = 0; i < ConditionalEntries.Count; i++) { var ce = ConditionalEntries[i]; if (traceEnabled) { context.AddTrace(" Checking condition: " + ce.Description); } if (ce.Condition(context)) { if (traceEnabled) { context.AddTrace(" Condition is TRUE, executing action: " + ce.Action.ToString()); } ce.Action.Execute(context); return; } } //if no conditions matched, execute default action if (DefaultAction == null) { context.AddParserError("Fatal parser error: no conditions matched in conditional parser action, and default action is null." + " State: {0}", context.CurrentParserState.Name); context.Parser.RecoverFromError(); return; } if (traceEnabled) { context.AddTrace(" All conditions failed, executing default action: " + DefaultAction.ToString()); } DefaultAction.Execute(context); } //method