示例#1
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
示例#2
0
 public BnfExpression MakePlusRule(NonTerminal listNonTerminal, BnfTerm delimiter, BnfTerm listMember)
 {
     listNonTerminal.SetOption(TermOptions.IsList);
     if (delimiter == null)
     {
         listNonTerminal.Rule = listMember | listNonTerminal + listMember;
     }
     else
     {
         listNonTerminal.Rule = listMember | listNonTerminal + delimiter + listMember;
     }
     return(listNonTerminal.Rule);
 }
示例#3
0
        public BnfExpression MakeStarRule(NonTerminal listNonTerminal, BnfTerm delimiter, BnfTerm listMember)
        {
            if (delimiter == null)
            {
                //it is much simpler case
                listNonTerminal.SetOption(TermOptions.IsList);
                listNonTerminal.Rule = Empty | listNonTerminal + listMember;
                return(listNonTerminal.Rule);
            }
            NonTerminal tmp = new NonTerminal(listMember.Name + "+");

            MakePlusRule(tmp, delimiter, listMember);
            listNonTerminal.Rule = Empty | tmp;
            listNonTerminal.SetOption(TermOptions.IsStarList);
            return(listNonTerminal.Rule);
        }
示例#4
0
        }//method

        private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes)
        {
            NonTerminal nt = reduceAction.NonTerminal;
            AstNode     result;

            AstNodeArgs args = new AstNodeArgs(nt, _context, sourceSpan, childNodes);

            result = nt.InvokeNodeCreator(args);
            if (result != null)
            {
                return(result);
            }

            Type defaultNodeType = _context.Compiler.Grammar.DefaultNodeType;
            Type ntNodeType      = nt.NodeType ?? defaultNodeType ?? typeof(AstNode);

            // Check if NonTerminal is a list
            // List nodes are produced by .Plus() or .Star() methods of BnfElement
            // In this case, we have a left-recursive list formation production:
            //     ntList -> ntList + delim? + ntElem
            //  We check if we have already created the list node for ntList (in the first child);
            //  if yes, we use this child as a result directly, without creating new list node.
            //  The other incoming child - the last one - is a new list member;
            // we simply add it to child list of the result ntList node. Optional "delim" node is simply thrown away.
            bool isList = nt.IsSet(TermOptions.IsList);

            if (isList && childNodes.Count > 1 && childNodes[0].Term == nt)
            {
                result = childNodes[0];
                AstNode newChild = childNodes[childNodes.Count - 1];
                newChild.Parent = result;
                result.ChildNodes.Add(newChild);
                return(result);
            }
            //Check for StarList produced by MakeStarList; in this case the production is:  ntList -> Empty | Elem+
            // where Elem+ is non-empty list of elements. The child list we are actually interested in is one-level lower
            if (nt.IsSet(TermOptions.IsStarList) && childNodes.Count == 1)
            {
                childNodes = childNodes[0].ChildNodes;
            }
            // Check for "node-bubbling" case. For identity productions like
            //   A -> B
            // the child node B is usually a subclass of node A,
            // so child node B can be used directly in place of the A. So we simply return child node as a result.
            // TODO: probably need a grammar option to enable/disable this behavior explicitly
            if (!isList && !nt.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1)
            {
                Type childNodeType = childNodes[0].Term.NodeType ?? defaultNodeType ?? typeof(AstNode);
                if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType))
                {
                    return(childNodes[0]);
                }
            }
            // Try using Grammar's CreateNode method
            result = Data.Grammar.CreateNode(_context, reduceAction, sourceSpan, childNodes);
            if (result == null)
            {
                //Finally create node directly. For perf reasons we try using "new" for AstNode type (faster), and
                // activator for all custom types (slower)
                if (ntNodeType == typeof(AstNode))
                {
                    result = new AstNode(args);
                }
                else
#if PocketPC || SILVERLIGHT
                {
                    ConstructorInfo ctor = ntNodeType.GetConstructor(new Type[] { typeof(AstNodeArgs) });
                    if (ctor == null)
                    {
                        throw new Exception("Failed to located constructor: " + ntNodeType.ToString() + "(AstNodeArgs args)");
                    }
                    result = (AstNode)ctor.Invoke(new object[] { args });
                }
#else
                {
                    result = (AstNode)Activator.CreateInstance(ntNodeType, args);
                }
#endif
            }
            if (result != null)
            {
                nt.OnNodeCreated(result);
            }
            return(result);
        }