public UnresolvedIdentifier(string name, Scope scope, Identifier identifier, CatchScope catchScope) { Name = name; Scope = scope; Identifier = identifier; CatchScope = catchScope; }
public CatchScope(ResolvedIdentifier identifier, Scope scope, CatchScope parent) { Identifier = identifier; Scope = scope; Parent = parent; }
public void EnterCatch(string name) { var identifier = new ResolvedIdentifier( name, null, IdentifierType.Local, true ); _resolvedIdentifiers.Add(identifier); _catchScope = new CatchScope(identifier, this, FindCatchScope()); }
public CatchClause ExitCatch(SyntaxNode statement) { var identifier = _catchScope.Identifier; _catchScope = _catchScope.Parent; return new CatchClause(identifier, statement); }
//--------------------------------------------------------------------------------------- // ParseTryStatement // // TryStatement : // 'try' Block Catch Finally // // Catch : // <empty> | 'catch' '(' Identifier ')' Block // // Finally : // <empty> | // 'finally' Block //--------------------------------------------------------------------------------------- private AstNode ParseTryStatement() { Context tryCtx = m_currentToken.Clone(); Context tryEndContext = null; Block body = null; Context idContext = null; Block handler = null; CatchScope catchScope = null; Block finally_block = null; RecoveryTokenException excInFinally = null; m_blockType.Add(BlockType.Block); try { bool catchOrFinally = false; GetNextToken(); if (JSToken.LeftCurly != m_currentToken.Token) { ReportError(JSError.NoLeftCurly); } m_noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet); try { body = ParseBlock(out tryEndContext); } catch (RecoveryTokenException exc) { if (IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exc) == -1) { // do nothing and just return the containing block, if any throw; } else { body = exc._partiallyComputedNode as Block; if (body == null) { body = new Block(exc._partiallyComputedNode.Context, this); body.Append(exc._partiallyComputedNode); } } } finally { m_noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet); } if (JSToken.Catch == m_currentToken.Token) { m_noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet); try { catchOrFinally = true; GetNextToken(); if (JSToken.LeftParenthesis != m_currentToken.Token) { ReportError(JSError.NoLeftParenthesis); } GetNextToken(); if (JSToken.Identifier != m_currentToken.Token) { string identifier = JSKeyword.CanBeIdentifier(m_currentToken.Token); if (null != identifier) { idContext = m_currentToken.Clone(); } else { ReportError(JSError.NoIdentifier); } } else { idContext = m_currentToken.Clone(); } GetNextToken(); m_noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); try { if (JSToken.RightParenthesis != m_currentToken.Token) { ReportError(JSError.NoRightParenthesis); } GetNextToken(); } catch (RecoveryTokenException exc) { if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1) { exc._partiallyComputedNode = null; // rethrow throw; } else { if (m_currentToken.Token == JSToken.RightParenthesis) { GetNextToken(); } } } finally { m_noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); } if (JSToken.LeftCurly != m_currentToken.Token) { ReportError(JSError.NoLeftCurly); } // create the catch-scope and push it onto the stack catchScope = new CatchScope(ScopeStack.Peek(), idContext, this); ScopeStack.Push(catchScope); try { // parse the block handler = ParseBlock(); } finally { // pop off the catch scope and assign it to the block ScopeStack.Pop(); } tryCtx.UpdateWith(handler.Context); } catch (RecoveryTokenException exc) { if (exc._partiallyComputedNode == null) { handler = new Block(CurrentPositionContext(), this); } else { handler = exc._partiallyComputedNode as Block; if (handler == null) { handler = new Block(exc._partiallyComputedNode.Context, this); handler.Append(exc._partiallyComputedNode); } } handler.BlockScope = catchScope; if (IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exc) == -1) { throw; } } finally { m_noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet); } } try { if (JSToken.Finally == m_currentToken.Token) { GetNextToken(); m_blockType.Add(BlockType.Finally); try { finally_block = ParseBlock(); catchOrFinally = true; } finally { m_blockType.RemoveAt(m_blockType.Count - 1); } tryCtx.UpdateWith(finally_block.Context); } } catch (RecoveryTokenException exc) { excInFinally = exc; // thrown later so we can execute code below } if (!catchOrFinally) { ReportError(JSError.NoCatch, true); finally_block = new Block(CurrentPositionContext(), this); // make a dummy empty block } } finally { m_blockType.RemoveAt(m_blockType.Count - 1); if (handler != null) { handler.BlockScope = catchScope; } } string catchVariableName = idContext == null ? null : idContext.Code; if (excInFinally != null) { excInFinally._partiallyComputedNode = new TryNode(tryCtx, this, body, catchVariableName, idContext, handler, finally_block); throw excInFinally; } return new TryNode(tryCtx, this, body, catchVariableName, idContext, handler, finally_block); }