public AstNodeArgs(BnfTerm term, CompilerContext context, SourceSpan span, AstNodeList childNodes) { Context = context; Term = term; Span = span; ChildNodes = childNodes; }
private void ExecuteReduceAction(ActionRecord action) { ParserState oldState = _currentState; int popCnt = action.PopCount; //Get new node's child nodes - these are nodes being popped from the stack AstNodeList childNodes = new AstNodeList(); for (int i = 0; i < action.PopCount; i++) { AstNode child = Stack[Stack.Count - popCnt + i].Node; if (!child.Term.IsSet(TermOptions.IsPunctuation)) childNodes.Add(child); } //recover state, location and pop the stack SourceSpan newNodeSpan; if (popCnt == 0) { newNodeSpan = new SourceSpan(_currentToken.Location, 0); } else { SourceLocation firstPopLoc = Stack[Stack.Count - popCnt].Node.Location; int lastPopEndPos = Stack[Stack.Count - 1].Node.Span.EndPos; newNodeSpan = new SourceSpan(firstPopLoc, lastPopEndPos - firstPopLoc.Position); _currentState = Stack[Stack.Count - popCnt].State; Stack.Pop(popCnt); } //Create new node AstNode node = CreateNode(action, newNodeSpan, childNodes); // Push node/current state into the stack Stack.Push(node, _currentState); //switch to new state ActionRecord gotoAction; if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction)) { _currentState = gotoAction.NewState; } else //should never happen throw new CompilerException( string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}", action.NonTerminal, oldState, _currentState)); }
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; }
// Override this method in language grammar if you want a custom node creation mechanism. public virtual AstNode CreateNode(CompilerContext context, ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes) { return null; }
// Override this method in language grammar if you want a custom node creation mechanism. public virtual AstNode CreateNode(CompilerContext context, ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes) { return(null); }