private bool TryBuildTreeFromStack(bool StopOnError) { TValue VT = (TValue)Activator.CreateInstance(typeof(TValue)); Stack <KeyValuePair <int, int> > BackTrack = new Stack <KeyValuePair <int, int> >();//стек пунктов для перебора с возвратом HashSet <KeyValuePair <int, int> > CheckedKernelItems = new HashSet <KeyValuePair <int, int> >(); while (StateStack.TopElement().number != 0) { //если восстановление по ходу разбора //то выходим, встретив состояние, допускающее error if (StopOnError) { if (FsaState.ParserTable != null && FsaState.ParserTable.ContainsKey(errorToken) && FsaState.ParserTable[errorToken] > 0) // shift { return(true); } } State state = StateStack.TopElement(); int ruleNum = 0; //номер пункта int pointPos = 0; //позиция точки в выбранной продукци //Формируем список еще не посещенных пунктов List <KeyValuePair <int, int> > ValidKernelItems = new List <KeyValuePair <int, int> >(); foreach (KeyValuePair <int, int> p in state.kernelItems) { if (!CheckedKernelItems.Contains(p)) { ValidKernelItems.Add(p); } } if (ValidKernelItems.Count == 0) { //непосещенных пунктов не осталось - возврат KeyValuePair <int, int> p = BackTrack.Pop(); ruleNum = p.Key; pointPos = p.Value; } else { //Среди непосещенных находим пункт с точкой в самой правой позиции foreach (KeyValuePair <int, int> p in ValidKernelItems) { if (p.Value > pointPos) { pointPos = p.Value; ruleNum = p.Key; } } if (pointPos == 1) { //точка в 1 позиции - добавляем пункты на стек и берем последний из них foreach (KeyValuePair <int, int> p in ValidKernelItems) { BackTrack.Push(p); CheckedKernelItems.Add(p); } KeyValuePair <int, int> p2 = BackTrack.Pop(); ruleNum = p2.Key; pointPos = p2.Value; } else { //точка в 2+ позиции - готовимся к новому запуску перебора с возвратом CheckedKernelItems.Clear(); BackTrack.Clear(); } } int count = rules[ruleNum].RightHandSide.Length - pointPos; //add items to stacks for (int i = 0; i < count; ++i) { valueStack.Push(VT); locationStack.Push(CurrentLocationSpan); StateStack.Push(state); } //reduce Reduce(ruleNum); } return(true); }
/// <summary> /// Main entry point of the Shift-Reduce Parser. /// </summary> /// <returns>True if parse succeeds, else false for /// unrecoverable errors</returns> public bool Parse() { Initialize(); // allow derived classes to instantiate rules, states and nonTerminals NextToken = 0; FsaState = states[0]; StateStack.Push(FsaState); valueStack.Push(CurrentSemanticValue); LocationStack.Push(CurrentLocationSpan); while (true) { #if TRACE_ACTIONS Console.Error.WriteLine("Entering state {0} ", FsaState.number); DisplayStack(); #endif int action = FsaState.defaultAction; if (FsaState.ParserTable != null) { if (NextToken == 0) { // We save the last token span, so that the location span // of production right hand sides that begin or end with a // nullable production will be correct. LastSpan = scanner.yylloc; NextToken = scanner.yylex(); #if TRACE_ACTIONS Console.Error.WriteLine("Reading: Next token is {0}", TerminalToString(NextToken)); #endif } #if TRACE_ACTIONS else { Console.Error.WriteLine("Next token is still {0}", TerminalToString(NextToken)); } #endif if (FsaState.ParserTable.ContainsKey(NextToken)) { action = FsaState.ParserTable[NextToken]; } } if (action > 0) // shift { Shift(action); } else if (action < 0) // reduce { try { Reduce(-action); if (action == -1) // accept { return(true); } } catch (AbortException) { return(false); } catch (AcceptException) { return(true); } catch (ErrorException) { if (!ErrorRecovery()) { return(false); } else { throw; // Rethrow x, preserving information. } } } else if (action == 0 && !ErrorRecovery()) // error { return(false); } } }
public bool Parse() { Initialize(); NextToken = 0; FsaState = states[0]; StateStack.Push(FsaState); valueStack.Push(CurrentSemanticValue); LocationStack.Push(CurrentLocationSpan); while (true) { #if TRACE_ACTIONS Console.Error.WriteLine("Entering state {0} ", FsaState.number); #endif int action = FsaState.defaultAction; if (FsaState.ParserTable != null) { if (NextToken == 0) { #if TRACE_ACTIONS Console.Error.Write("Reading a token: "); #endif LastSpan = scanner.yylloc; NextToken = scanner.yylex(); } #if TRACE_ACTIONS Console.Error.WriteLine("Next token is {0}", TerminalToString(NextToken)); #endif if (FsaState.ParserTable.ContainsKey(NextToken)) { action = FsaState.ParserTable[NextToken]; } } if (action > 0) { Shift(action); } else if (action < 0) { try { Reduce(-action); if (action == -1) { return(true); } } catch (Exception x) { if (x is AbortException) { return(false); } else if (x is AcceptException) { return(true); } else if (x is ErrorException && !ErrorRecovery()) { return(false); } else { throw; } } } else if (action == 0) { if (!ErrorRecovery()) { return(false); } } } }