//--------------------------------------------------------------------------------------- // ParseSwitchStatement // // SwitchStatement : // 'switch' '(' Expression ')' '{' CaseBlock '}' // // CaseBlock : // CaseList DefaultCaseClause CaseList // // CaseList : // <empty> | // CaseClause CaseList // // CaseClause : // 'case' Expression ':' OptionalStatements // // DefaultCaseClause : // <empty> | // 'default' ':' OptionalStatements //--------------------------------------------------------------------------------------- private AST ParseSwitchStatement(){ Context switchCtx = this.currentToken.Clone(); AST expr = null; ASTList cases = null; this.blockType.Add(BlockType.Switch); try{ // read switch(expr) GetNextToken(); if (JSToken.LeftParen != this.currentToken.token) ReportError(JSError.NoLeftParen); GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); try{ expr = ParseExpression(); if (JSToken.RightParen != this.currentToken.token){ ReportError(JSError.NoRightParen); } GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token){ ReportError(JSError.NoLeftCurly); } GetNextToken(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1 && IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1 ){ // give up exc._partiallyComputedNode = null; throw exc; }else{ if (exc._partiallyComputedNode == null) expr = new ConstantWrapper(true, CurrentPositionContext()); else expr = exc._partiallyComputedNode; if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) != -1){ if (exc._token == JSToken.RightParen) GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token){ ReportError(JSError.NoLeftCurly); } GetNextToken(); } } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); } // parse the switch body cases = new ASTList(this.currentToken.Clone()); bool defaultStatement = false; this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); try{ while (JSToken.RightCurly != this.currentToken.token){ SwitchCase caseClause = null; AST caseValue = null; Context caseCtx = this.currentToken.Clone(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet); try{ if (JSToken.Case == this.currentToken.token){ // get the case GetNextToken(); caseValue = ParseExpression(); }else if (JSToken.Default == this.currentToken.token){ // get the default if (defaultStatement) // we report an error but we still accept the default ReportError(JSError.DupDefault, true); else defaultStatement = true; GetNextToken(); }else{ // This is an error, there is no case or default. Assume a default was missing and keep going defaultStatement = true; ReportError(JSError.BadSwitch); } if (JSToken.Colon != this.currentToken.token) ReportError(JSError.NoColon); // read the statements inside the case or default GetNextToken(); }catch(RecoveryTokenException exc){ // right now we can only get here for the 'case' statement if (IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exc) == -1){ // ignore the current case or default exc._partiallyComputedNode = null; throw exc; }else{ caseValue = exc._partiallyComputedNode; if (exc._token == JSToken.Colon) GetNextToken(); } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet); } this.blockType.Add(BlockType.Block); try{ Block statements = new Block(this.currentToken.Clone()); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try{ while (JSToken.RightCurly != this.currentToken.token && JSToken.Case != this.currentToken.token && JSToken.Default != this.currentToken.token){ try{ statements.Append(ParseStatement()); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null){ statements.Append(exc._partiallyComputedNode); exc._partiallyComputedNode = null; } if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1) throw exc; } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1){ if (null == caseValue) caseClause = new SwitchCase(caseCtx, statements); else caseClause = new SwitchCase(caseCtx, caseValue, statements); cases.Append(caseClause); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); } if (JSToken.RightCurly == this.currentToken.token) statements.context.UpdateWith(this.currentToken); if (null == caseValue){ caseCtx.UpdateWith(statements.context); caseClause = new SwitchCase(caseCtx, statements); }else{ caseCtx.UpdateWith(statements.context); caseClause = new SwitchCase(caseCtx, caseValue, statements); } cases.Append(caseClause); }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ //save what you can a rethrow switchCtx.UpdateWith(CurrentPositionContext()); exc._partiallyComputedNode = new Switch(switchCtx, expr, cases); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } switchCtx.UpdateWith(this.currentToken); GetNextToken(); }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); } return new Switch(switchCtx, expr, cases); }
private AST ParseSwitchStatement() { Context context = this.currentToken.Clone(); AST expression = null; ASTList cases = null; this.blockType.Add(BlockType.Switch); try { this.GetNextToken(); if (JSToken.LeftParen != this.currentToken.token) { this.ReportError(JSError.NoLeftParen); } this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); try { expression = this.ParseExpression(); if (JSToken.RightParen != this.currentToken.token) { this.ReportError(JSError.NoRightParen); } this.GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } this.GetNextToken(); } catch (RecoveryTokenException exception) { if ((this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception) == -1) && (this.IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exception) == -1)) { exception._partiallyComputedNode = null; throw exception; } if (exception._partiallyComputedNode == null) { expression = new ConstantWrapper(true, this.CurrentPositionContext()); } else { expression = exception._partiallyComputedNode; } if (this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception) != -1) { if (exception._token == JSToken.RightParen) { this.GetNextToken(); } if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } this.GetNextToken(); } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); } cases = new ASTList(this.currentToken.Clone()); bool flag = false; this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); try { while (JSToken.RightCurly != this.currentToken.token) { SwitchCase elem = null; AST ast2 = null; Context context2 = this.currentToken.Clone(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet); try { if (JSToken.Case == this.currentToken.token) { this.GetNextToken(); ast2 = this.ParseExpression(); } else if (JSToken.Default == this.currentToken.token) { if (flag) { this.ReportError(JSError.DupDefault, true); } else { flag = true; } this.GetNextToken(); } else { flag = true; this.ReportError(JSError.BadSwitch); } if (JSToken.Colon != this.currentToken.token) { this.ReportError(JSError.NoColon); } this.GetNextToken(); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = null; throw exception2; } ast2 = exception2._partiallyComputedNode; if (exception2._token == JSToken.Colon) { this.GetNextToken(); } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet); } this.blockType.Add(BlockType.Block); try { Block statements = new Block(this.currentToken.Clone()); this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try { while (((JSToken.RightCurly != this.currentToken.token) && (JSToken.Case != this.currentToken.token)) && (JSToken.Default != this.currentToken.token)) { try { statements.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception3) { if (exception3._partiallyComputedNode != null) { statements.Append(exception3._partiallyComputedNode); exception3._partiallyComputedNode = null; } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception3) == -1) { throw exception3; } continue; } } } catch (RecoveryTokenException exception4) { if (this.IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exception4) == -1) { if (ast2 == null) { elem = new SwitchCase(context2, statements); } else { elem = new SwitchCase(context2, ast2, statements); } cases.Append(elem); throw exception4; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet); } if (JSToken.RightCurly == this.currentToken.token) { statements.context.UpdateWith(this.currentToken); } if (ast2 == null) { context2.UpdateWith(statements.context); elem = new SwitchCase(context2, statements); } else { context2.UpdateWith(statements.context); elem = new SwitchCase(context2, ast2, statements); } cases.Append(elem); continue; } finally { this.blockType.RemoveAt(this.blockType.Count - 1); } } } catch (RecoveryTokenException exception5) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception5) == -1) { context.UpdateWith(this.CurrentPositionContext()); exception5._partiallyComputedNode = new Switch(context, expression, cases); throw exception5; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } context.UpdateWith(this.currentToken); this.GetNextToken(); } finally { this.blockType.RemoveAt(this.blockType.Count - 1); } return new Switch(context, expression, cases); }