private void CreateReduceActions()
 {
     foreach (var state in Data.States)
     {
         var stateData = state.BuilderData;
         if (stateData.ShiftItems.Count == 0 && stateData.ReduceItems.Count == 1)
         {
             state.DefaultReduceAction = ParserAction.CreateReduce(stateData.ReduceItems.First().Core.Production);
             continue;
         }
         //now create actions
         foreach (var item in state.BuilderData.ReduceItems)
         {
             //create actions
             foreach (var lkh in item.Lookaheads)
             {
                 if (state.Actions.ContainsKey(lkh))
                 {
                     continue;
                 }
                 state.Actions[lkh] = ParserAction.CreateReduce(item.Core.Production);
             }
         } //foreach item
     }     //foreach state
 }
        }//method

        private void CreateDefaultActionsForConflicts(ParserState state,
                                                      BnfTermSet shiftReduceConflicts, BnfTermSet reduceReduceConflicts)
        {
            var stateData = state.BuilderData;

            //Create default actions for these conflicts. For shift-reduce, default action is shift, and shift action already
            // exist for all shifts from the state, so we don't need to do anything. For reduce-reduce create reduce actions
            // for the first reduce item (whatever comes first in the set).
            foreach (var conflict in reduceReduceConflicts)
            {
                var reduceItems = stateData.ReduceItems.SelectByLookahead(conflict);
                var action      = ParserAction.CreateReduce(reduceItems.First().Core.Production);
                state.Actions[conflict] = action;
            }
            //Update ResolvedConflicts and Conflicts sets
            stateData.ResolvedConflicts.UnionWith(shiftReduceConflicts);
            stateData.ResolvedConflicts.UnionWith(reduceReduceConflicts);
            stateData.Conflicts.ExceptWith(stateData.ResolvedConflicts);
        }
        private bool TryResolveConflictByHints(ParserState state, BnfTerm conflict)
        {
            var stateData = state.BuilderData;
            //reduce hints
            var reduceItems = stateData.ReduceItems.SelectByLookahead(conflict);

            foreach (var reduceItem in reduceItems)
            {
                if (reduceItem.Core.Hints != null)
                {
                    foreach (var hint in reduceItem.Core.Hints)
                    {
                        if (hint.HintType == HintType.ResolveToReduce)
                        {
                            var newAction = ParserAction.CreateReduce(reduceItem.Core.Production);
                            state.Actions[conflict] = newAction; //replace/add reduce action
                            return(true);
                        }
                    }
                }
            }

            //Shift hints
            var shiftItems = stateData.ShiftItems.SelectByCurrent(conflict);

            foreach (var shiftItem in shiftItems)
            {
                if (shiftItem.Core.Hints != null)
                {
                    foreach (var hint in shiftItem.Core.Hints)
                    {
                        if (hint.HintType == HintType.ResolveToShift)
                        {
                            //shift action is already there
                            return(true);
                        }
                    }
                }
            }

            //code hints
            // first prepare data for conflict action: reduceProduction (for possible reduce) and newState (for possible shift)
            var         reduceProduction = reduceItems.First().Core.Production; //take first of reduce productions
            ParserState newState         = (state.Actions.ContainsKey(conflict) ? state.Actions[conflict].NewState : null);
            // Get all items that might contain hints; first take all shift items and reduce items in conflict;
            // we should also add lookahead sources of reduce items. Lookahead source is an LR item that produces the lookahead,
            // so if it contains a code hint right before the lookahead term, then it applies to this conflict as well.
            var allItems = new LRItemList();

            allItems.AddRange(shiftItems);
            foreach (var reduceItem in reduceItems)
            {
                allItems.Add(reduceItem);
                allItems.AddRange(reduceItem.ReducedLookaheadSources);
            }
            // Scan all items and try to find hint with resolution type Code
            foreach (var item in allItems)
            {
                if (item.Core.Hints != null)
                {
                    foreach (var hint in item.Core.Hints)
                    {
                        if (hint.HintType == HintType.ResolveInCode)
                        {
                            //found hint with resolution type "code" - this is instruction to use custom code here to resolve the conflict
                            // create new ConflictAction and place it into Actions table
                            var newAction = ParserAction.CreateCodeAction(newState, reduceProduction);
                            state.Actions[conflict] = newAction; //replace/add reduce action
                            return(true);
                        }
                    }
                }
            }
            return(false);
        }
예제 #4
0
        //Detect conflicts that cannot be handled by non-canonical NLALR method directly, by may be fixed by grammar transformation
        private void DetectNlalrFixableConflicts(ParserState state)
        {
            var stateData = state.BuilderData;
            //compute R-R and S-R conflicting lookaheads
            var reduceLkhds = new BnfTermSet();
            var rrConflicts = new BnfTermSet();
            var srConflicts = new BnfTermSet();

            foreach (var reduceItem in state.BuilderData.ReduceItems)
            {
                foreach (var lkh in reduceItem.ReducedLookaheads)
                {
                    if (stateData.ShiftTerms.Contains(lkh))
                    {
                        if (!lkh.IsSet(TermOptions.UsePrecedence))
                        {
                            srConflicts.Add(lkh); //S-R conflict
                        }
                    }
                    else if (reduceLkhds.Contains(lkh))
                    {
                        rrConflicts.Add(lkh); //R-R conflict
                    }
                    reduceLkhds.Add(lkh);
                } //foreach lkh
            }     //foreach item
            if (srConflicts.Count == 0 && rrConflicts.Count == 0)
            {
                return;
            }
            //Collect all cores to recommend for adding WrapTail hint.
            var allConflicts = new BnfTermSet();

            allConflicts.UnionWith(srConflicts);
            allConflicts.UnionWith(rrConflicts);
            foreach (var conflict in allConflicts)
            {
                var conflictingShiftItems = state.BuilderData.ShiftItems.SelectByCurrent(conflict);
                foreach (var item in conflictingShiftItems)
                {
                    if (!item.Core.IsInitial) //only non-initial
                    {
                        _coresToAddWrapTailHint.Add(item.Core);
                    }
                }
                foreach (var reduceItem in state.BuilderData.ReduceItems)
                {
                    var conflictingSources = reduceItem.ReducedLookaheadSources.SelectByCurrent(conflict);
                    foreach (var source in conflictingSources)
                    {
                        _coresToAddWrapTailHint.Add(source.Core);
                    }
                }
            }
            //still report them as conflicts
            ReportParseConflicts(state, srConflicts, rrConflicts);
            //create default actions and remove conflicts from list so we don't deal with them anymore
            foreach (var conflict in rrConflicts)
            {
                var reduceItems = stateData.ReduceItems.SelectByReducedLookahead(conflict);
                var action      = ParserAction.CreateReduce(reduceItems.First().Core.Production);
                state.Actions[conflict] = action;
            }
            //Update ResolvedConflicts and Conflicts sets
            stateData.ResolvedConflicts.UnionWith(srConflicts);
            stateData.ResolvedConflicts.UnionWith(rrConflicts);
            stateData.Conflicts.ExceptWith(stateData.ResolvedConflicts);
        }//method