14 using System.Collections.Generic;
20 public partial class CoreParser {
22 private void ProcessParserError() {
23 Context.Status = ParserStatus.Error;
24 _grammar.ReportParseError(this.Context);
25 if (Context.Mode !=
ParseMode.CommandLine)
26 TryRecoverFromError();
30 private bool TryRecoverFromError() {
31 if (Context.CurrentParserInput.Term == _grammar.Eof)
33 Context.Status = ParserStatus.Recovering;
35 var recovered = TryRecoverImpl();
37 Context.AddTrace(msg);
38 Context.Status = recovered? ParserStatus.Parsing : ParserStatus.Error;
42 private bool TryRecoverImpl() {
45 ParserAction nextAction = FindErrorShiftActionInStackTemp();
47 if (nextAction == null)
return false;
49 var firstBnfTerm = nextAction.NewState.Actions.Keys.FirstOrDefault();
55 var newLineNode =
new ParseTreeNode(firstBnfTerm);
56 Context.ParserInputStack.Insert(0, newLineNode);
57 var saveParserInput = Context.CurrentParserInput;
58 Context.CurrentParserInput = newLineNode;
60 nextAction = FindActionForStateAndInput();
62 while (nextAction != null && Context.CurrentParserInput != null)
64 switch (nextAction.ActionType)
66 case ParserActionType.Shift:
67 ExecuteShift(nextAction);
69 case ParserActionType.Operator:
70 ExecuteOperatorAction(nextAction);
72 case ParserActionType.Reduce:
73 ExecuteReduce(nextAction);
75 case ParserActionType.Code:
76 ExecuteConflictAction(nextAction);
78 case ParserActionType.Accept:
79 ExecuteAccept(nextAction);
82 nextAction = FindActionForStateAndInput();
85 Context.ParserInputStack.RemoveAt(0);
86 Context.CurrentParserInput = saveParserInput;
88 if (!Context.CurrentParserState.Actions.TryGetValue(Context.CurrentParserInput.Term, out nextAction))
90 Context.ParserInputStack.Clear();
91 Context.CurrentParserInput = null;
146 private void ExecuteShiftTemp(BnfTerm term, ParserAction action)
148 Context.ParserStack.Push(
new ParseTreeNode(term), action.NewState);
149 Context.CurrentParserState = action.NewState;
154 private void ExecuteReduceOnError(ParserAction action)
156 var reduceProduction = action.ReduceProduction;
158 Context.ParserStack.Pop(1);
161 Context.CurrentParserState = Context.ParserStack.Top.State;
164 var shift = Context.CurrentParserState.Actions[reduceProduction.LValue];
165 Context.ParserStack.Push(
new ParseTreeNode(action.ReduceProduction.LValue), shift.NewState);
166 Context.CurrentParserState = shift.NewState;
171 Context.CurrentParserInput = null;
172 Context.ParserInputStack.Clear();
173 Context.SetSourceLocation(location);
177 while (Context.ParserStack.Count >= 1) {
179 if (Context.CurrentParserState.Actions.TryGetValue(_grammar.SyntaxError, out errorShiftAction) && errorShiftAction.ActionType == ParserActionType.Shift)
180 return errorShiftAction;
182 if (Context.ParserStack.Count == 1)
184 Context.ParserStack.Pop();
185 Context.CurrentParserState = Context.ParserStack.Top.State;
190 private ParserAction FindErrorShiftActionInStackTemp()
192 for (
int i = Context.ParserStack.Count - 1; i >= 0; i--)
194 ParserAction errorShiftAction;
195 var currentState = Context.ParserStack[i].State;
197 if (currentState.Actions.TryGetValue(_grammar.SyntaxError, out errorShiftAction) && errorShiftAction.ActionType == ParserActionType.Shift)
199 return errorShiftAction;
205 private ParserAction FindErrorShiftActionInStack(BnfTerm exitTerm)
207 while (Context.ParserStack.Count >= 1)
209 ParserAction errorShiftAction;
210 if (Context.CurrentParserState.Actions.TryGetValue(exitTerm, out errorShiftAction))
211 return errorShiftAction;
213 if (Context.ParserStack.Count == 1)
215 Context.ParserStack.Pop();
216 Context.CurrentParserState = Context.ParserStack.Top.State;
223 private ParserAction GetReduceActionInCurrentState() {
224 if (Context.CurrentParserState.DefaultAction != null)
return Context.CurrentParserState.DefaultAction;
225 foreach (var action
in Context.CurrentParserState.Actions.Values)
228 if (action.NewState.DefaultAction != null && (action.NewState.DefaultAction.ActionType ==
ParserActionType.Reduce))
229 return action.NewState.DefaultAction;
237 private ParserAction GetShiftActionInCurrentState() {
238 ParserAction result = null;
239 if (Context.CurrentParserState.Actions.TryGetValue(Context.CurrentParserInput.Term, out result) ||
240 Context.CurrentParserInput.Token != null && Context.CurrentParserInput.Token.KeyTerm != null &&
241 Context.CurrentParserState.Actions.TryGetValue(Context.CurrentParserInput.Token.KeyTerm, out result))
264 internal static StringSet ComputeGroupedExpectedSetForState(Grammar grammar, ParserState state) {
265 var terms =
new TerminalSet();
266 terms.UnionWith(state.ExpectedTerminals);
267 var result =
new StringSet();
269 foreach(var group
in grammar.TermReportGroups)
271 terms.ExceptWith(group.Terminals);
273 foreach(var group
in grammar.TermReportGroups)
275 result.Add(group.Alias);
276 terms.ExceptWith(group.Terminals);
279 foreach(var terminal
in terms)
280 result.Add(terminal.ErrorAlias);
static string MsgTracePoppedState
Looks up a localized string similar to Popped state from stack, pushing {0}.
static string MsgTraceRecovering
Looks up a localized string similar to RECOVERING: popping stack, looking for state with error shift...
void ResetLocationAndClearInput(SourceLocation location, int position)
static string MsgTraceRecoverFailed
Looks up a localized string similar to FAILED TO RECOVER.
static string MsgTraceRecoverAction
Looks up a localized string similar to RECOVERING: {0}.
static string MsgTraceRecoverReducing
Looks up a localized string similar to RECOVERING: Reached end of error production, reducing..