private AstNode CreateNode(ActionRecord reduceAction, SourceSpan sourceSpan, AstNodeList childNodes) { NonTerminal nonTeminal = reduceAction.NonTerminal; AstNode result; AstNodeArgs args = new AstNodeArgs(nonTeminal, sourceSpan, childNodes); Type defaultNodeType = _context.Compiler.Data.DefaultNodeType; Type ntNodeType = nonTeminal.NodeType ?? defaultNodeType ?? typeof(AstNode); bool isList = nonTeminal.IsSet(TermOptions.IsList); if (isList && childNodes.Count > 1 && childNodes[0].Term == nonTeminal) { result = childNodes[0]; AstNode newChild = childNodes[childNodes.Count - 1]; newChild.Parent = result; result.ChildNodes.Add(newChild); return result; } if (nonTeminal.IsSet(TermOptions.IsStarList) && childNodes.Count == 1) { childNodes = childNodes[0].ChildNodes; } if (!isList && !nonTeminal.IsSet(TermOptions.IsPunctuation) && childNodes.Count == 1) { Type childNodeType = childNodes[0].Term.NodeType ?? defaultNodeType ?? typeof(AstNode); if (childNodeType == ntNodeType || childNodeType.IsSubclassOf(ntNodeType)) return childNodes[0]; } result = null; if (ntNodeType == typeof(AstNode)) { result = new AstNode(args); } else { 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 }); } return result; }
private void ExecuteReduceAction(ActionRecord action) { ParserState oldState = _currentState; int popCnt = action.PopCount; 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); } 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); } AstNode node = CreateNode(action, newNodeSpan, childNodes); _stack.Push(node, _currentState); ActionRecord gotoAction; if (_currentState.Actions.TryGetValue(action.NonTerminal.Key, out gotoAction)) { _currentState = gotoAction.NewState; } else throw new CompilerException(string.Format("Cannot find transition for input {0}; state: {1}, popped state: {2}", action.NonTerminal, oldState, _currentState)); }