//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);
        }
示例#3
0
        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
        }
示例#4
0
        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;
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
示例#9
0
        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;
        }
示例#10
0
        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());
        }