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 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); }
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); }
}//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); }