public AstNode Parse(CompilerContext context, IEnumerable <TokenAst> tokenStream) { _context = context; Reset(); _input = tokenStream.GetEnumerator(); NextToken(); while (true) { if (_currentState == Data.FinalState) { AstNode result = _stack[0].Node; _stack.Reset(); return(result); } if (_currentToken.Terminal.Category == TokenCategory.Error) { ReportScannerError(); return(null); } ActionRecord action = GetCurrentAction(); if (action == null) { ReportParserError(); return(null); } //TODO: perform conflict resolving //if (action.HasConflict()) switch (action.ActionType) { case ParserActionType.Operator: if (GetActionTypeForOperation(_currentToken) == ParserActionType.Shift) { goto case ParserActionType.Shift; } else { goto case ParserActionType.Reduce; } case ParserActionType.Shift: ExecuteShiftAction(action); break; case ParserActionType.Reduce: ExecuteReduceAction(action); break; } } }
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)); } }
private ActionRecord GetCurrentAction() { ActionRecord action = null; if (_currentToken.MatchByValue) { if (_currentState.Actions.TryGetValue(_currentToken.Text, out action)) { return(action); } } if (_currentToken.MatchByType && _currentState.Actions.TryGetValue(_currentToken.Terminal.Key, out action)) { return(action); } return(null); }
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)); }
private void ExecuteShiftAction(ActionRecord action) { _stack.Push(_currentToken, _currentState); _currentState = action.NewState; NextToken(); }