//List container is created by MakePlusRule, MakeStarRule with allowTrailingDelimiter = true // it is a special case for parser. The "real" list in grammar is the "container", but list members had been accumulated under // the transient "plus-list" which is a child of this container. So we need to copy all "grandchildrent" from child to parent. private ParseTreeNode ReduceListContainer(ParserAction action) { int childCount = action.ReduceProduction.RValues.Count; int firstChildIndex = Context.ParserStack.Count - childCount; var span = ComputeNewNodeSpan(childCount); var newNode = new ParseTreeNode(action.ReduceProduction, span); if (childCount > 0) //if it is not empty production - might happen for MakeStarRule { var listNode = Context.ParserStack[firstChildIndex]; //get the transient list with all members - it is the first child node newNode.ChildNodes.AddRange(listNode.ChildNodes); //copy all list members } return(newNode); }
private ParserAction GetShiftActionInCurrentState() { ParserAction result = null; if (Context.CurrentParserState.Actions.TryGetValue(Context.CurrentParserInput.Term, out result) || Context.CurrentParserInput.Token != null && Context.CurrentParserInput.Token.KeyTerm != null && Context.CurrentParserState.Actions.TryGetValue(Context.CurrentParserInput.Token.KeyTerm, out result)) { if (result.ActionType == ParserActionType.Shift) { return(result); } } return(null); }
private void ExecuteOperatorAction(ParserAction action) { var realActionType = GetActionTypeForOperation(action); if (_traceEnabled) { Context.AddTrace(Resources.MsgTraceOpResolved, realActionType); } switch (realActionType) { case ParserActionType.Shift: ExecuteShift(action); break; case ParserActionType.Reduce: ExecuteReduce(action); break; }//switch }
private ParseTreeNode ReduceExistingList(ParserAction action) { int childCount = action.ReduceProduction.RValues.Count; int firstChildIndex = Context.ParserStack.Count - childCount; var listNode = Context.ParserStack[firstChildIndex]; //get the list already created - it is the first child node listNode.Span = ComputeNewNodeSpan(childCount); var listMember = Context.ParserStack.Top; //next list member is the last child - at the top of the stack if (ShouldSkipChildNode(listMember)) { return(listNode); } CheckCreateAstNode(listMember); listNode.ChildNodes.Add(listMember); return(listNode); }
// --> START EDIT ALEX private void ExecuteReduceOnError(ParserAction action) { var reduceProduction = action.ReduceProduction; //final reduce actions ---------------------------------------------------------- Context.ParserStack.Pop(1); //Push new node into stack and move to new state //First read the state from top of the stack Context.CurrentParserState = Context.ParserStack.Top.State; if (_traceEnabled) { Context.AddTrace(Resources.MsgTracePoppedState, reduceProduction.LValue.Name); } // Shift to new state (LALR) - execute shift over non-terminal var shift = Context.CurrentParserState.Actions[reduceProduction.LValue]; Context.ParserStack.Push(new ParseTreeNode(action.ReduceProduction.LValue), shift.NewState); Context.CurrentParserState = shift.NewState; }
private void ExecuteReduce(ParserAction action) { var reduceProduction = action.ReduceProduction; ParseTreeNode resultNode; if (reduceProduction.IsSet(ProductionFlags.IsListBuilder)) { resultNode = ReduceExistingList(action); } else if (reduceProduction.LValue.Flags.IsSet(TermFlags.IsListContainer)) { resultNode = ReduceListContainer(action); } else if (reduceProduction.LValue.Flags.IsSet(TermFlags.IsTransient)) { resultNode = ReduceTransientNonTerminal(action); } else { resultNode = ReduceRegularNode(action); } //final reduce actions ---------------------------------------------------------- Context.ParserStack.Pop(reduceProduction.RValues.Count); //Push new node into stack and move to new state //First read the state from top of the stack Context.CurrentParserState = Context.ParserStack.Top.State; if (_traceEnabled) { Context.AddTrace(Resources.MsgTracePoppedState, reduceProduction.LValue.Name); } // Shift to new state (LALR) - execute shift over non-terminal var shift = Context.CurrentParserState.Actions[reduceProduction.LValue]; Context.ParserStack.Push(resultNode, shift.NewState); Context.CurrentParserState = shift.NewState; //Copy comment block from first child; if comments precede child node, they precede the parent as well. if (resultNode.ChildNodes.Count > 0) { resultNode.Comments = resultNode.ChildNodes[0].Comments; } //Invoke event reduceProduction.LValue.OnReduced(Context, reduceProduction, resultNode); }
private ParseTreeNode ReduceTransientNonTerminal(ParserAction action) { var topIndex = Context.ParserStack.Count - 1; var childCount = action.ReduceProduction.RValues.Count; for (int i = 0; i < childCount; i++) { var child = Context.ParserStack[topIndex - i]; if (ShouldSkipChildNode(child)) { continue; } CheckCreateAstNode(child); return(child); } //Otherwise return an empty transient node; if it is part of the list, the list will skip it var span = ComputeNewNodeSpan(childCount); return(new ParseTreeNode(action.ReduceProduction, span)); }
private void ExecuteConflictAction(ParserAction action) { var args = new ConflictResolutionArgs(Context, action); _grammar.OnResolvingConflict(args); switch (args.Result) { case ParserActionType.Reduce: ExecuteReduce(new ParserAction(ParserActionType.Reduce, null, args.ReduceProduction)); break; case ParserActionType.Operator: ExecuteOperatorAction(new ParserAction(ParserActionType.Operator, action.NewState, args.ReduceProduction)); break; case ParserActionType.Shift: default: ExecuteShift(action); break; } Context.AddTrace(Resources.MsgTraceConflictResolved); }
private void ExecuteReduce(ParserAction action) { var reduceProduction = action.ReduceProduction; ParseTreeNode newNode; if (reduceProduction.IsSet(ProductionFlags.IsListBuilder)) { newNode = ReduceExistingList(action); } else if (reduceProduction.LValue.FlagIsSet(TermFlags.IsListContainer)) { newNode = ReduceListContainer(action); } else if (reduceProduction.LValue.FlagIsSet(TermFlags.IsTransient)) { newNode = ReduceTransientNonTerminal(action); } else { newNode = ReduceRegularNode(action); } //final reduce actions ---------------------------------------------------------- Context.ParserStack.Pop(reduceProduction.RValues.Count); //Push new node into stack and move to new state //First read the state from top of the stack Context.CurrentParserState = Context.ParserStack.Top.State; if (_traceEnabled) { Context.AddTrace(Resources.MsgTracePoppedState, reduceProduction.LValue.Name); } // Shift to new state (LALR) - execute shift over non-terminal var shift = Context.CurrentParserState.Actions[reduceProduction.LValue]; Context.ParserStack.Push(newNode, shift.NewState); Context.CurrentParserState = shift.NewState; }
private void ExecuteConflictAction(ParserAction action) { var args = action.ResolveConflict(_grammar, Context); switch (args.Result) { case ParserActionType.Reduce: ExecuteReduce(new ParserAction(ParserActionType.Reduce, null, args.ReduceProduction)); break; case ParserActionType.Operator: ExecuteOperatorAction(new ParserAction(ParserActionType.Operator, action.NewState, args.ReduceProduction)); break; case ParserActionType.Shift: default: ExecuteShift(action); break; } if (_traceEnabled) { Context.AddTrace(Resources.MsgTraceConflictResolved); } }
private bool TryRecoverImpl() { //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 nextAction = FindErrorShiftActionInStackTemp(); if (nextAction == null) { return(false); } var firstBnfTerm = nextAction.NewState.Actions.Keys.FirstOrDefault(); Context.AddTrace(Resources.MsgTraceRecoverReducing); Context.AddTrace(Resources.MsgTraceRecoverAction, nextAction); // Inject faked node var newLineNode = new ParseTreeNode(firstBnfTerm); Context.ParserInputStack.Insert(0, newLineNode); var saveParserInput = Context.CurrentParserInput; Context.CurrentParserInput = newLineNode; nextAction = FindActionForStateAndInput(); while (nextAction != null && Context.CurrentParserInput != null) { switch (nextAction.ActionType) { case ParserActionType.Shift: ExecuteShift(nextAction); break; case ParserActionType.Operator: ExecuteOperatorAction(nextAction); break; case ParserActionType.Reduce: ExecuteReduce(nextAction); break; case ParserActionType.Code: ExecuteConflictAction(nextAction); break; case ParserActionType.Accept: ExecuteAccept(nextAction); break; } nextAction = FindActionForStateAndInput(); } Context.ParserInputStack.RemoveAt(0); Context.CurrentParserInput = saveParserInput; if (!Context.CurrentParserState.Actions.TryGetValue(Context.CurrentParserInput.Term, out nextAction)) { Context.ParserInputStack.Clear(); Context.CurrentParserInput = null; } return(true); //ExecuteShiftTemp(firstBnfTerm, nextAction); /* * var action = GetReduceActionInCurrentState(); * if (action != null) * { * //Clear all input token queues and buffered input, reset location back to input position token queues; * //Reduce error production - it creates parent non-terminal that "hides" error inside * ExecuteReduce(action); * return true; //we recovered * } * return true; * * ParserAction errorShiftAction = FindErrorShiftActionInStack(); * 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); * ExecuteShift(errorShiftAction); * //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) * ReadInput(); * if (Context.CurrentParserInput.Term == _grammar.Eof) * return false; * //Check if we can reduce * action = GetReduceActionInCurrentState(); * if (action != null) { * //Clear all input token queues and buffered input, reset location back to input position token queues; * Context.SetSourceLocation(Context.CurrentParserInput.Span.Location); * Context.ParserInputStack.Clear(); * Context.CurrentParserInput = null; * * //Reduce error production - it creates parent non-terminal that "hides" error inside * Context.AddTrace(Resources.MsgTraceRecoverReducing); * Context.AddTrace(Resources.MsgTraceRecoverAction, action); * ExecuteReduceOnError(action); * return true; //we recovered * } * //No reduce action in current state. Try to shift current token or throw it away or reduce * action = GetShiftActionInCurrentState(); * if(action != null) * ExecuteShift(action); //shift input token * else //simply read input * ReadInput(); * } */ }//method
}//method private void ExecuteShiftTemp(BnfTerm term, ParserAction action) { Context.ParserStack.Push(new ParseTreeNode(term), action.NewState); Context.CurrentParserState = action.NewState; }
public string Description; //for tracing public ConditionalEntry(ConditionChecker condition, ParserAction action, string description) { Condition = condition; Action = action; Description = description; }
public static string PrintStateList(LanguageData language) { StringBuilder sb = new StringBuilder(); foreach (ParserState state in language.ParserData.States) { sb.Append("State " + state.Name); if (state.BuilderData.IsInadequate) { sb.Append(" (Inadequate)"); } sb.AppendLine(); var srConflicts = state.BuilderData.GetShiftReduceConflicts(); if (srConflicts.Count > 0) { sb.AppendLine(" Shift-reduce conflicts on inputs: " + srConflicts.ToString()); } var ssConflicts = state.BuilderData.GetReduceReduceConflicts(); if (ssConflicts.Count > 0) { sb.AppendLine(" Reduce-reduce conflicts on inputs: " + ssConflicts.ToString()); } //LRItems if (state.BuilderData.ShiftItems.Count > 0) { sb.AppendLine(" Shift items:"); foreach (var item in state.BuilderData.ShiftItems) { sb.AppendLine(" " + item.ToString()); } } if (state.BuilderData.ReduceItems.Count > 0) { sb.AppendLine(" Reduce items:"); foreach (LRItem item in state.BuilderData.ReduceItems) { var sItem = item.ToString(); if (item.Lookaheads.Count > 0) { sItem += " [" + item.Lookaheads.ToString() + "]"; } sb.AppendLine(" " + sItem); } } sb.Append(" Transitions: "); foreach (BnfTerm key in state.Actions.Keys) { ParserAction action = state.Actions[key]; if (action.ActionType != ParserActionType.Shift) { continue; } sb.Append(key.ToString()); if (action.ActionType == ParserActionType.Shift) { sb.Append("->"); //shift } sb.Append(action.NewState.Name); sb.Append(", "); } sb.AppendLine(); sb.AppendLine(); }//foreach return(sb.ToString()); }