public BnfTermSet GetReduceReduceConflicts()
        {
            var result = new BnfTermSet();

            result.UnionWith(Conflicts);
            result.ExceptWith(ShiftTerms);
            return(result);
        }
        public BnfTermSet GetShiftReduceConflicts()
        {
            var result = new BnfTermSet();

            result.UnionWith(Conflicts);
            result.IntersectWith(ShiftTerms);
            return(result);
        }
        public string ToString(BnfTermSet exceptLookaheads)
        {
            string s = Core.ToString();

            if (!this.Core.IsFinal)
            {
                return(s);
            }
            var lkhds = new BnfTermSet();

            lkhds.UnionWith(Lookaheads);
            lkhds.ExceptWith(exceptLookaheads);
            s += " [" + lkhds.ToString() + "]";
            return(s);
        }
Esempio n. 4
0
 private void ComputeReportedExpectedSet(ParserState state)
 {
     //2. Compute reduced expected terms - to be used in error reporting
       //2.1. Scan Expected terms, add non-terminals with non-empty DisplayName to reduced set, and collect all their firsts
       var reducedSet = state.ReportedExpectedSet = new BnfTermSet();
       var allFirsts = new BnfTermSet();
       foreach (var term in state.ExpectedTerms) {
     var nt = term as NonTerminal;
     if (nt == null) continue;
     if (!reducedSet.Contains(nt) && !string.IsNullOrEmpty(nt.DisplayName) && !allFirsts.Contains(nt)) {
       reducedSet.Add(nt);
       allFirsts.UnionWith(nt.Firsts);
     }
       }
       //2.2. Now go thru all expected terms and add only those that are NOT in the allFirsts set.
       foreach (var term in state.ExpectedTerms) {
     if (!reducedSet.Contains(term) && !allFirsts.Contains(term) && (term is Terminal || !string.IsNullOrEmpty(term.DisplayName)))
       reducedSet.Add(term);
       }
       //Clean-up reduced set, remove pseudo terms
       if (reducedSet.Contains(_grammar.Eof)) reducedSet.Remove(_grammar.Eof);
       if (reducedSet.Contains(_grammar.SyntaxError)) reducedSet.Remove(_grammar.SyntaxError);
 }
 //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
    }//method

    #region some explanations
    //Computes  non-canonical lookaheads and jump lookaheads - those that cause jump
    // to non-canonical state
    // We are doing it top-down way, starting from most reduced lookaheads - they are not conflicting. 
    // (If there were conflicting reduced lookaheads in a state initially, the grammar transformation algorithm 
    // should have already wrapped them into non-conflicting "tail" non-terminals.) 
    // We want to eliminate reduced lookaheads as much as possible, and replace them with expanded "child" 
    // terms, to have only those non-canonical lookaheads that are absolutely necessary. 
    // So for each reduced lookahead we check if we can replace it with its expanded, "child" terms 
    // (from DirectFirsts set). We do it only if lookaheads child terms are all non-conflicting as lookaheads in 
    // the state. If however, at least one child is conflicting, the reduced parent should stay. 
    // What if we have some children conflicting and some not? We leave the parent reduced lookahead in state, 
    // to cover (hide) the conflicting children, but we also add non-conflicting children as well, to allow 
    // the parser automaton to use them (in canonical state) as soon as they are recognized, without need 
    // to reduce the parent and switch back to canonical state. 
    #endregion 
    private void ComputeStateNonCanonicalLookaheads(ParserState state) {
      var stateData = state.BuilderData;
      //rename for shorter code
      var jumps = stateData.JumpLookaheads; // conflicting lookaheads, that must result in jump to non-canonical state         
      var valids = stateData.NonCanonicalLookaheads; // valid non-canonical lookaheads, non-terminals only
      jumps.Clear(); 
      valids.Clear(); 
      var alreadyChecked = new BnfTermSet();
      var toCheck = new BnfTermSet();   //terms to check for expansion
      //1. precompute initial set to check
      foreach (var reduceItem in stateData.ReduceItems) 
        toCheck.UnionWith(reduceItem.ReducedLookaheads);
      toCheck.RemoveWhere(t => t is Terminal); //we are interested in non-terminals only
      //2. Try to expand all initial (reduced) lookaheads, and replace original lookaheads with expanded versions
      while (toCheck.Count > 0) { // do until no terms to check left
        var lkhInCheck = toCheck.First() as NonTerminal;
        toCheck.Remove(lkhInCheck);
        //to prevent repeated checking of mutually recursive terms 
        if (alreadyChecked.Contains(lkhInCheck)) continue; 
        alreadyChecked.Add(lkhInCheck);
        //Now check children for conflicts; go through all direct firsts of lkhInCheck and check them for conflicts
        bool hasJumpChild = false; 
        foreach (var lkhChild in lkhInCheck.DirectFirsts) {
          if (lkhChild == lkhInCheck) continue;
          if (jumps.Contains(lkhChild)) {
            hasJumpChild = true;
            continue;
          }
          var ntChild = lkhChild as NonTerminal;
          if (ntChild != null && valids.Contains(ntChild))   continue;
          //the child has not been tested yet; check if it is a conflict in current state
          var occurCount = GetLookaheadOccurenceCount(state, lkhChild);
          if (occurCount > 1) {            
            //possible conflict, check precedence
            if (lkhChild.IsSet(TermOptions.UsePrecedence)) {
              if (ntChild != null) {
                valids.Add(ntChild); //if it is terminal, it is valid;
                if (!alreadyChecked.Contains(lkhChild))  toCheck.Add(ntChild); 
              } //if ntChild
            } else {
              //conflict!
              hasJumpChild = true;
              jumps.Add(lkhChild);
              //if it is non-terminal, add its Firsts to conflict as well
              if (ntChild != null) {
                jumps.UnionWith(ntChild.Firsts);
                //valids.ExceptWith(ntChild.Firsts); 
              }
            }//if IsSet... else...

          } else { //occurCount == 1
            //no conflict: if it is non-terminal, add it to toCheck set to check in the future 
            if (ntChild != null && !alreadyChecked.Contains(ntChild))
              toCheck.Add(ntChild); //if nonterminal and not checked yet, add it to toCheck for further checking
          }//if ...else...
        }//foreach lkhChild
        //Ok, we finished checking all direct children; if at least one of them has conflict, 
        // then lkhInCheck (parent) must stay as a lookahead - we cannot fully expand it replacing by all children
        if (hasJumpChild)
          valids.Add(lkhInCheck);         
      }//while toCheck.Count > 0
      //remove conflicts
      stateData.Conflicts.Clear();
    }//method
Esempio n. 7
0
        //computes DirectFirsts, Firsts for non-terminals and productions
        private static void ComputeFirsts(GrammarData data)
        {
            //compute prod direct firsts and initialize NT.Firsts
              foreach (var nt in data.NonTerminals) {
            foreach (var prod in nt.Productions) {
              foreach (var term in prod.RValues) {
            prod.DirectFirsts.Add(term);
            nt.DirectFirsts.Add(term);
            nt.Firsts.Add(term);
            if (!term.IsSet(TermOptions.IsNullable)) break; //foreach term
              }
            }
              }//foreach nt

              //propagate NT.Firsts
              int time = 0;
              var done = false;
              var newSet = new BnfTermSet();
              while (!done) {
            done = true;
            foreach (var nt in data.NonTerminals) {
              newSet.Clear();
              foreach (var first in nt.Firsts) {
            var ntFirst = first as NonTerminal;
            if (ntFirst != null && ntFirst._lastChanged >= nt._lastChecked)
              newSet.UnionWith(ntFirst.Firsts);
              }
              nt._lastChecked = time++;
              var oldCount = nt.Firsts.Count;
              nt.Firsts.UnionWith(newSet);
              if (nt.Firsts.Count > oldCount) {
            done = false;
            nt._lastChanged = time;
              }
            }//foreach nt
              }//while

              //compute prod.Firsts
              foreach (var nt in data.NonTerminals) {
            foreach (var prod in nt.Productions) {
              prod.Firsts.UnionWith(prod.DirectFirsts);
              foreach (var directFirst in prod.DirectFirsts) {
            var ntDirectFirst = directFirst as NonTerminal;
            if (ntDirectFirst != null)
              prod.Firsts.UnionWith(ntDirectFirst.Firsts);
              }//foreach directFirst
            }//foreach prod
              }//foreach nt
        }
Esempio n. 8
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
Esempio n. 9
0
        }//method

        #region some explanations
        //Computes  non-canonical lookaheads and jump lookaheads - those that cause jump
        // to non-canonical state
        // We are doing it top-down way, starting from most reduced lookaheads - they are not conflicting.
        // (If there were conflicting reduced lookaheads in a state initially, the grammar transformation algorithm
        // should have already wrapped them into non-conflicting "tail" non-terminals.)
        // We want to eliminate reduced lookaheads as much as possible, and replace them with expanded "child"
        // terms, to have only those non-canonical lookaheads that are absolutely necessary.
        // So for each reduced lookahead we check if we can replace it with its expanded, "child" terms
        // (from DirectFirsts set). We do it only if lookaheads child terms are all non-conflicting as lookaheads in
        // the state. If however, at least one child is conflicting, the reduced parent should stay.
        // What if we have some children conflicting and some not? We leave the parent reduced lookahead in state,
        // to cover (hide) the conflicting children, but we also add non-conflicting children as well, to allow
        // the parser automaton to use them (in canonical state) as soon as they are recognized, without need
        // to reduce the parent and switch back to canonical state.
        #endregion
        private void ComputeStateNonCanonicalLookaheads(ParserState state)
        {
            var stateData = state.BuilderData;
            //rename for shorter code
            var jumps  = stateData.JumpLookaheads;         // conflicting lookaheads, that must result in jump to non-canonical state
            var valids = stateData.NonCanonicalLookaheads; // valid non-canonical lookaheads, non-terminals only

            jumps.Clear();
            valids.Clear();
            var alreadyChecked = new BnfTermSet();
            var toCheck        = new BnfTermSet(); //terms to check for expansion

            //1. precompute initial set to check
            foreach (var reduceItem in stateData.ReduceItems)
            {
                toCheck.UnionWith(reduceItem.ReducedLookaheads);
            }
            toCheck.RemoveWhere(t => t is Terminal); //we are interested in non-terminals only
            //2. Try to expand all initial (reduced) lookaheads, and replace original lookaheads with expanded versions
            while (toCheck.Count > 0)                // do until no terms to check left
            {
                var lkhInCheck = toCheck.First() as NonTerminal;
                toCheck.Remove(lkhInCheck);
                //to prevent repeated checking of mutually recursive terms
                if (alreadyChecked.Contains(lkhInCheck))
                {
                    continue;
                }
                alreadyChecked.Add(lkhInCheck);
                //Now check children for conflicts; go through all direct firsts of lkhInCheck and check them for conflicts
                bool hasJumpChild = false;
                foreach (var lkhChild in lkhInCheck.DirectFirsts)
                {
                    if (lkhChild == lkhInCheck)
                    {
                        continue;
                    }
                    if (jumps.Contains(lkhChild))
                    {
                        hasJumpChild = true;
                        continue;
                    }
                    var ntChild = lkhChild as NonTerminal;
                    if (ntChild != null && valids.Contains(ntChild))
                    {
                        continue;
                    }
                    //the child has not been tested yet; check if it is a conflict in current state
                    var occurCount = GetLookaheadOccurenceCount(state, lkhChild);
                    if (occurCount > 1)
                    {
                        //possible conflict, check precedence
                        if (lkhChild.IsSet(TermOptions.UsePrecedence))
                        {
                            if (ntChild != null)
                            {
                                valids.Add(ntChild); //if it is terminal, it is valid;
                                if (!alreadyChecked.Contains(lkhChild))
                                {
                                    toCheck.Add(ntChild);
                                }
                            } //if ntChild
                        }
                        else
                        {
                            //conflict!
                            hasJumpChild = true;
                            jumps.Add(lkhChild);
                            //if it is non-terminal, add its Firsts to conflict as well
                            if (ntChild != null)
                            {
                                jumps.UnionWith(ntChild.Firsts);
                                //valids.ExceptWith(ntChild.Firsts);
                            }
                        } //if IsSet... else...
                    }
                    else  //occurCount == 1
                    //no conflict: if it is non-terminal, add it to toCheck set to check in the future
                    {
                        if (ntChild != null && !alreadyChecked.Contains(ntChild))
                        {
                            toCheck.Add(ntChild); //if nonterminal and not checked yet, add it to toCheck for further checking
                        }
                    }//if ...else...
                }//foreach lkhChild
                //Ok, we finished checking all direct children; if at least one of them has conflict,
                // then lkhInCheck (parent) must stay as a lookahead - we cannot fully expand it replacing by all children
                if (hasJumpChild)
                {
                    valids.Add(lkhInCheck);
                }
            }//while toCheck.Count > 0
            //remove conflicts
            stateData.Conflicts.Clear();
        }//method
Esempio n. 10
0
        //computes DirectFirsts, Firsts for non-terminals and productions
        private static void ComputeFirsts(GrammarData data)
        {
            //compute prod direct firsts and initialize NT.Firsts
            foreach (var nt in data.NonTerminals)
            {
                foreach (var prod in nt.Productions)
                {
                    foreach (var term in prod.RValues)
                    {
                        prod.DirectFirsts.Add(term);
                        nt.DirectFirsts.Add(term);
                        nt.Firsts.Add(term);
                        if (!term.IsSet(TermOptions.IsNullable))
                        {
                            break;                          //foreach term
                        }
                    }
                }
            }//foreach nt

            //propagate NT.Firsts
            int time   = 0;
            var done   = false;
            var newSet = new BnfTermSet();

            while (!done)
            {
                done = true;
                foreach (var nt in data.NonTerminals)
                {
                    newSet.Clear();
                    foreach (var first in nt.Firsts)
                    {
                        var ntFirst = first as NonTerminal;
                        if (ntFirst != null && ntFirst._lastChanged >= nt._lastChecked)
                        {
                            newSet.UnionWith(ntFirst.Firsts);
                        }
                    }
                    nt._lastChecked = time++;
                    var oldCount = nt.Firsts.Count;
                    nt.Firsts.UnionWith(newSet);
                    if (nt.Firsts.Count > oldCount)
                    {
                        done            = false;
                        nt._lastChanged = time;
                    }
                } //foreach nt
            }     //while

            //compute prod.Firsts
            foreach (var nt in data.NonTerminals)
            {
                foreach (var prod in nt.Productions)
                {
                    prod.Firsts.UnionWith(prod.DirectFirsts);
                    foreach (var directFirst in prod.DirectFirsts)
                    {
                        var ntDirectFirst = directFirst as NonTerminal;
                        if (ntDirectFirst != null)
                        {
                            prod.Firsts.UnionWith(ntDirectFirst.Firsts);
                        }
                    } //foreach directFirst
                }     //foreach prod
            }         //foreach nt
        }             //method
 //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);
     }
       }
       ReportAndCreateDefaultActionsForConflicts(state, srConflicts, rrConflicts);
       //Update ResolvedConflicts and Conflicts sets
       stateData.ResolvedConflicts.UnionWith(srConflicts);
       stateData.ResolvedConflicts.UnionWith(rrConflicts);
       stateData.Conflicts.ExceptWith(stateData.ResolvedConflicts);
 }