Beispiel #1
0
        public Production(bool isInitial, NonTerminal lvalue, BnfTermList rvalues)
        {
            LValue = lvalue;

            foreach (GrammarTerm rv in rvalues)
            {
                if (rv != Grammar.Empty)
                {
                    RValues.Add(rv);
                }
            }

            foreach (GrammarTerm term in RValues)
            {
                Terminal terminal = term as Terminal;
                if (terminal == null)
                {
                    continue;
                }
                HasTerminals = true;
                if (terminal.Category == TokenCategory.Error)
                {
                    IsError = true;
                }
            }

            for (int p = 0; p <= RValues.Count; p++)
            {
                LR0Items.Add(new LR0Item(this, p));
            }
        }
Beispiel #2
0
 public readonly LR0ItemList LR0Items = new LR0ItemList(); //LR0 items based on this production
 public Production(bool isInitial, NonTerminal lvalue, BnfTermList rvalues)
 {
     LValue = lvalue;
     //copy RValues skipping Empty pseudo-terminal
     foreach (BnfTerm rv in rvalues)
     {
         if (rv != Grammar.Empty)
         {
             RValues.Add(rv);
         }
     }
     //Calculate flags
     foreach (BnfTerm term in RValues)
     {
         Terminal terminal = term as Terminal;
         if (terminal == null)
         {
             continue;
         }
         HasTerminals = true;
         if (terminal.Category == TokenCategory.Error)
         {
             IsError = true;
         }
     }//foreach
     //Note that we add an extra LR0Item with p = RValues.Count
     for (int p = 0; p <= RValues.Count; p++)
     {
         LR0Items.Add(new LR0Item(this, p));
     }
 }//constructor
 public virtual void VerifyLanguageData()
 {
     var gd = Context.Language.GrammarData;
     //Collect all terminals and non-terminals
     var terms = new BnfTermSet();
     //SL does not understand co/contravariance, so doing merge one-by-one
     foreach (var t in gd.Terminals) terms.Add(t);
     foreach (var t in gd.NonTerminals) terms.Add(t);
     var missingList = new BnfTermList();
     foreach (var term in terms)
     {
         var terminal = term as Terminal;
         if (terminal != null && terminal.Category != TokenCategory.Content) continue; //only content terminals
         if (term.Flags.IsSet(TermFlags.NoAstNode)) continue;
         var config = term.AstConfig;
         if (config.NodeCreator != null || config.DefaultNodeCreator != null) continue;
         //We must check NodeType
         if (config.NodeType == null)
             config.NodeType = GetDefaultNodeType(term);
         if (config.NodeType == null)
             missingList.Add(term);
         else
             config.DefaultNodeCreator = CompileDefaultNodeCreator(config.NodeType);
     }
     if (missingList.Count > 0)
         // AST node type is not specified for term {0}. Either assign Term.AstConfig.NodeType, or specify default type(s) in AstBuilder.  
         Context.AddMessage(ErrorLevel.Error, SourceLocation.Empty, Resources.ErrNodeTypeNotSetOn,
             string.Join(", ", missingList));
     Context.Language.AstDataVerified = true;
 }
Beispiel #4
0
        public virtual void VerifyLanguageData()
        {
            var gd = Context.Language.GrammarData;
            //Collect all terminals and non-terminals
            var terms = new BnfTermSet();

            //SL does not understand co/contravariance, so doing merge one-by-one
            foreach (var t in gd.Terminals)
            {
                terms.Add(t);
            }
            foreach (var t in gd.NonTerminals)
            {
                terms.Add(t);
            }
            var missingList = new BnfTermList();

            foreach (var term in terms)
            {
                var terminal = term as Terminal;
                if (terminal != null && terminal.Category != TokenCategory.Content)
                {
                    continue;                                                         //only content terminals
                }
                if (term.Flags.IsSet(TermFlags.NoAstNode))
                {
                    continue;
                }
                var config = term.AstConfig;
                if (config.NodeCreator != null || config.DefaultNodeCreator != null)
                {
                    continue;
                }
                //We must check NodeType
                if (config.NodeType == null)
                {
                    config.NodeType = GetDefaultNodeType(term);
                }
                if (config.NodeType == null)
                {
                    missingList.Add(term);
                }
                else
                {
                    config.DefaultNodeCreator = CompileDefaultNodeCreator(config.NodeType);
                }
            }
            if (missingList.Count > 0)
            {
                // AST node type is not specified for term {0}. Either assign Term.AstConfig.NodeType, or specify default type(s) in AstBuilder.
                Context.AddMessage(ErrorLevel.Error, SourceLocation.Empty, Resources.ErrNodeTypeNotSetOn, missingList.ToString());
            }
            Context.Language.AstDataVerified = true;
        }
        private Production CreateProduction(NonTerminal lvalue, BnfTermList operands)
        {
            Production prod = new Production(lvalue);

            //create RValues list skipping Empty terminal and collecting grammar hints
            foreach (BnfTerm operand in operands)
            {
                if (operand == Grammar.Empty)
                {
                    continue;
                }
                //Collect hints as we go - they will be added to the next non-hint element
                GrammarHint hint = operand as GrammarHint;
                if (hint != null)
                {
                    hint.Position = prod.RValues.Count;
                    prod.Hints.Add(hint);
                    continue;
                }
                //Check if it is a Terminal or Error element
                Terminal t = operand as Terminal;
                if (t != null)
                {
                    prod.Flags |= ProductionFlags.HasTerminals;
                    if (t.Category == TokenCategory.Error)
                    {
                        prod.Flags |= ProductionFlags.IsError;
                    }
                }
                //Add the operand info and LR0 Item
                _itemID++;
                LR0Item item = new LR0Item(prod, prod.RValues.Count, _itemID);
                prod.LR0Items.Add(item);
                prod.RValues.Add(operand);
            }//foreach operand
            //set the flags
            if (lvalue == Data.AugmentedRoot)
            {
                prod.Flags |= ProductionFlags.IsInitial;
            }
            if (prod.RValues.Count == 0)
            {
                prod.Flags |= ProductionFlags.IsEmpty;
            }
            //Add final LRItem
            _itemID++;
            prod.LR0Items.Add(new LR0Item(prod, prod.RValues.Count, _itemID));
            return(prod);
        }
Beispiel #6
0
        //TODO: This needs more work. Currently it reports all individual symbols most of the time, in a message like
        //  "Syntax error, expected: + - < > = ..."; the better method is to group operator symbols under one alias "operator".
        // The reason is that code picks expected key list at current(!) state only,
        // slightly tweaking it for non-terminals, without exploring Reduce roots
        // It is quite difficult to discover grouping non-terminals like "operator" in current structure.
        // One possible solution would be to introduce "ExtendedLookaheads" in ParserState which would include
        // all NonTerminals that might follow the current position. This list would be calculated at start up,
        // in addition to normal lookaheads.
        #endregion
        private StringList GetCurrentExpectedSymbols()
        {
            BnfTermList inputElements = new BnfTermList();
            StringSet   inputKeys     = new StringSet();

            inputKeys.AddRange(_currentState.Actions.Keys);
            //First check all NonTerminals
            foreach (NonTerminal nt in Data.NonTerminals)
            {
                if (!inputKeys.Contains(nt.Key))
                {
                    continue;
                }
                //nt is one of our available inputs; check if it has an alias. If not, don't add it to element list;
                // and we have already all its "Firsts" keys in the list.
                // If yes, add nt to element list and remove
                // all its "fists" symbols from the list. These removed symbols will be represented by single nt alias.
                if (string.IsNullOrEmpty(nt.DisplayName))
                {
                    inputKeys.Remove(nt.Key);
                }
                else
                {
                    inputElements.Add(nt);
                    foreach (string first in nt.Firsts)
                    {
                        inputKeys.Remove(first);
                    }
                }
            }
            //Now terminals
            foreach (Terminal term in Data.Terminals)
            {
                if (inputKeys.Contains(term.Key))
                {
                    inputElements.Add(term);
                }
            }
            StringList result = new StringList();

            foreach (BnfTerm term in inputElements)
            {
                result.Add(string.IsNullOrEmpty(term.DisplayName)? term.Name : term.DisplayName);
            }
            result.Sort();
            return(result);
        }
Beispiel #7
0
 private static void CheckWrapTailHints(GrammarData data, NonTerminal nonTerminal, BnfTermList operands)
 {
     //WrapTail hint doesn't make sense in last position, so we start with Count-2
       for (int i = operands.Count - 2; i >= 0; i--) {
     var hint = operands[i] as GrammarHint;
     if (hint == null || hint.HintType != HintType.WrapTail) continue;
     //we have WrapTail hint; wrap all operands after this into new non-terminal
     var wrapNt = new NonTerminal(nonTerminal.Name + "_tail" + nonTerminal._tailCount++);
     wrapNt.SetOption(TermOptions.IsTransient);
     wrapNt.Rule = new BnfExpression();
     for (int j = i + 1; j < operands.Count; j++) {
       wrapNt.Rule.Data[0].Add(operands[j]);
     }
     operands.RemoveRange(i, operands.Count - i);
     operands.Add(wrapNt);
     data.AllTerms.Add(wrapNt);
     data.NonTerminals.Add(wrapNt);
       }//for i
 }
        private Production CreateProduction(NonTerminal lvalue, BnfTermList operands)
        {
            Production      prod  = new Production(lvalue);
            GrammarHintList hints = null;

            //create RValues list skipping Empty terminal and collecting grammar hints
            foreach (BnfTerm operand in operands)
            {
                if (operand == _grammar.Empty)
                {
                    continue;
                }
                //Collect hints as we go - they will be added to the next non-hint element
                GrammarHint hint = operand as GrammarHint;
                if (hint != null)
                {
                    if (hints == null)
                    {
                        hints = new GrammarHintList();
                    }
                    hints.Add(hint);
                    continue;
                }
                //Add the operand and create LR0 Item
                prod.RValues.Add(operand);
                prod.LR0Items.Add(new LR0Item(_lastItemId++, prod, prod.RValues.Count - 1, hints));
                hints = null;
            }//foreach operand
            //set the flags
            if (prod.RValues.Count == 0)
            {
                prod.Flags |= ProductionFlags.IsEmpty;
            }
            //Add final LRItem
            ComputeProductionFlags(prod);
            prod.LR0Items.Add(new LR0Item(_lastItemId++, prod, prod.RValues.Count, hints));
            return(prod);
        }
Beispiel #9
0
        private void ProcessUnparseHints(BnfExpression rule)
        {
            if (rule != null)
            {
                for (int childBnfTermListIndex = 0; childBnfTermListIndex < rule.Data.Count; childBnfTermListIndex++)
                {
                    BnfTermList bnfTermList = rule.Data[childBnfTermListIndex];

                    try
                    {
                        UnparseHint unparseHint = (UnparseHint)bnfTermList.SingleOrDefault(bnfTerm => bnfTerm is UnparseHint);
                        childBnfTermListIndexToUnparseHint.Add(childBnfTermListIndex, unparseHint);
                    }
                    catch (InvalidOperationException)
                    {
                        GrammarHelper.ThrowGrammarErrorException(
                            GrammarErrorLevel.Error,
                            "NonTerminal '{0}' has more than one UnparseHint on its {1}. childrenlist. Only one UnparseHint is allowed per childrenlist.", this, childBnfTermListIndex + 1
                            );
                    }
                }
            }
        }
Beispiel #10
0
 public override string ToString()
 {
     if (_toString != null)
     {
         return(_toString);
     }
     try {
         string[] pipeArr = new string[Data.Count];
         for (int i = 0; i < Data.Count; i++)
         {
             BnfTermList seq    = Data[i];
             string[]    seqArr = new string[seq.Count];
             for (int j = 0; j < seq.Count; j++)
             {
                 seqArr[j] = seq[j].ToString();
             }
             pipeArr[i] = String.Join("+", seqArr);
         }
         _toString = String.Join("|", pipeArr);
         return(_toString);
     } catch (Exception e) {
         return("(error: " + e.Message + ")");
     }
 }
Beispiel #11
0
 private StringList GetCurrentExpectedSymbols()
 {
     BnfTermList inputElements = new BnfTermList();
       StringSet inputKeys = new StringSet();
       inputKeys.AddRange(_currentState.Actions.Keys);
       //First check all NonTerminals
       foreach (NonTerminal nt in Data.NonTerminals) {
     if (!inputKeys.Contains(nt.Key)) continue;
     //nt is one of our available inputs; check if it has an alias. If not, don't add it to element list;
     // and we have already all its "Firsts" keys in the list.
     // If yes, add nt to element list and remove
     // all its "fists" symbols from the list. These removed symbols will be represented by single nt alias.
     if (string.IsNullOrEmpty(nt.DisplayName))
       inputKeys.Remove(nt.Key);
     else {
       inputElements.Add(nt);
       foreach(string first in nt.Firsts)
     inputKeys.Remove(first);
     }
       }
       //Now terminals
       foreach (Terminal term in Data.Terminals) {
     if (inputKeys.Contains(term.Key))
       inputElements.Add(term);
       }
       StringList result = new StringList();
       foreach(BnfTerm term in inputElements)
     result.Add(string.IsNullOrEmpty(term.DisplayName)? term.Name : term.DisplayName);
       result.Sort();
       return result;
 }
Beispiel #12
0
 private Production CreateProduction(NonTerminal lvalue, BnfTermList operands)
 {
     Production prod = new Production(lvalue);
       GrammarHintList hints = null;
       //create RValues list skipping Empty terminal and collecting grammar hints
       foreach (BnfTerm operand in operands) {
     if (operand ==  _grammar.Empty)
       continue;
     //Collect hints as we go - they will be added to the next non-hint element
     GrammarHint hint = operand as GrammarHint;
     if (hint != null) {
       if (hints == null) hints = new GrammarHintList();
       hints.Add(hint);
       continue;
     }
     //Add the operand and create LR0 Item
     prod.RValues.Add(operand);
     prod.LR0Items.Add(new LR0Item(_lastItemId++, prod, prod.RValues.Count - 1, hints));
     hints = null;
       }//foreach operand
       //set the flags
       if (prod.RValues.Count == 0)
     prod.Flags |= ProductionFlags.IsEmpty;
       //Add final LRItem
       ComputeProductionFlags(prod);
       prod.LR0Items.Add(new LR0Item(_lastItemId++, prod, prod.RValues.Count, hints));
       return prod;
 }
Beispiel #13
0
 private Production CreateProduction(NonTerminal lvalue, BnfTermList operands)
 {
     Production prod = new Production(lvalue);
       GrammarHintList hints = null;
       //create RValues list skipping Empty terminal and collecting grammar hints
       foreach (BnfTerm operand in operands) {
     if (operand == Grammar.CurrentGrammar.Empty)
       continue;
     //Collect hints as we go - they will be added to the next non-hint element
     GrammarHint hint = operand as GrammarHint;
     if (hint != null) {
       if (hints == null) hints = new GrammarHintList();
       hints.Add(hint);
       continue;
     }
     //Check if it is a Terminal or Error element
     Terminal t = operand as Terminal;
     if (t != null) {
       prod.Flags |= ProductionFlags.HasTerminals;
       if (t.Category == TokenCategory.Error) prod.Flags |= ProductionFlags.IsError;
     }
     //Add the operand info and LR0 Item
     LR0Item item = new LR0Item(_lastItemId++, prod, prod.RValues.Count, hints);
     prod.LR0Items.Add(item);
     prod.RValues.Add(operand);
     hints = null;
       }//foreach operand
       //set the flags
       if (prod.RValues.Count == 0)
     prod.Flags |= ProductionFlags.IsEmpty;
       //Add final LRItem
       prod.LR0Items.Add(new LR0Item(_lastItemId++, prod, prod.RValues.Count, hints));
       return prod;
 }
Beispiel #14
0
    public Production(bool isInitial, NonTerminal lvalue, BnfTermList rvalues)
    {
      LValue = lvalue;
      
      foreach (GrammarTerm rv in rvalues)
        if (rv != Grammar.Empty)
          RValues.Add(rv);

      foreach (GrammarTerm term in RValues)
      {
        Terminal terminal = term as Terminal;
        if (terminal == null) continue;
        HasTerminals = true;
        if (terminal.Category == TokenCategory.Error) IsError = true;
      }

      for (int p = 0; p <= RValues.Count; p++)
        LR0Items.Add(new LR0Item(this, p));
    }
Beispiel #15
0
 private static void CheckWrapTailHints(GrammarData data, NonTerminal nonTerminal, BnfTermList operands)
 {
     //WrapTail hint doesn't make sense in last position, so we start with Count-2
     for (int i = operands.Count - 2; i >= 0; i--)
     {
         var hint = operands[i] as GrammarHint;
         if (hint == null || hint.HintType != HintType.WrapTail)
         {
             continue;
         }
         //we have WrapTail hint; wrap all operands after this into new non-terminal
         var wrapNt = new NonTerminal(nonTerminal.Name + "_tail" + nonTerminal._tailCount++);
         wrapNt.SetOption(TermOptions.IsTransient);
         wrapNt.Rule = new BnfExpression();
         for (int j = i + 1; j < operands.Count; j++)
         {
             wrapNt.Rule.Data[0].Add(operands[j]);
         }
         operands.RemoveRange(i, operands.Count - i);
         operands.Add(wrapNt);
         data.AllTerms.Add(wrapNt);
         data.NonTerminals.Add(wrapNt);
     }//for i
 }