private AST ParseLeftHandSideExpression(bool isMinus, ref bool canBeAttribute, bool warnForKeyword){ AST ast = null; bool isFunction = false; ArrayList newContexts = null; // new expression while (JSToken.New == this.currentToken.token){ if (null == newContexts) newContexts = new ArrayList(4); newContexts.Add(this.currentToken.Clone()); GetNextToken(); } JSToken token = this.currentToken.token; switch (token){ // primary expression case JSToken.Identifier: ast = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone()); break; case JSToken.This: canBeAttribute = false; ast = new ThisLiteral(this.currentToken.Clone(), false); break; case JSToken.Super: canBeAttribute = false; ast = new ThisLiteral(this.currentToken.Clone(), true); break; case JSToken.StringLiteral: canBeAttribute = false; ast = new ConstantWrapper(this.scanner.GetStringLiteral(), this.currentToken.Clone()); break; case JSToken.IntegerLiteral: {canBeAttribute = false; String number = this.currentToken.GetCode(); Object n = Convert.LiteralToNumber(number, this.currentToken); if (n == null) n = 0; ast = new ConstantWrapper(n, this.currentToken.Clone()); ((ConstantWrapper)ast).isNumericLiteral = true; break;} case JSToken.NumericLiteral: {canBeAttribute = false; String number = (isMinus) ? "-" + this.currentToken.GetCode() : this.currentToken.GetCode(); double d = Convert.ToNumber(number, false, false, Missing.Value); ast = new ConstantWrapper(d, this.currentToken.Clone()); ((ConstantWrapper)ast).isNumericLiteral = true; break;} case JSToken.True: canBeAttribute = false; ast = new ConstantWrapper(true, this.currentToken.Clone()); break; case JSToken.False: canBeAttribute = false; ast = new ConstantWrapper(false, this.currentToken.Clone()); break; case JSToken.Null: canBeAttribute = false; ast = new NullLiteral(this.currentToken.Clone()); break; case JSToken.PreProcessorConstant: canBeAttribute = false; ast = new ConstantWrapper(this.scanner.GetPreProcessorValue(), this.currentToken.Clone()); break; case JSToken.Divide: canBeAttribute = false; // could it be a regexp? String source = this.scanner.ScanRegExp(); if (source != null){ bool badRegExp = false; try { new Regex(source, RegexOptions.ECMAScript); } catch (System.ArgumentException) { // Replace the invalid source with the trivial regular expression. source = ""; badRegExp = true; } String flags = this.scanner.ScanRegExpFlags(); if (flags == null) ast = new RegExpLiteral(source, null, this.currentToken.Clone()); else try{ ast = new RegExpLiteral(source, flags, this.currentToken.Clone()); }catch (JScriptException){ // The flags are invalid, so use null instead. ast = new RegExpLiteral(source, null, this.currentToken.Clone()); badRegExp = true; } if (badRegExp){ ReportError(JSError.RegExpSyntax, true); } break; } goto default; // expression case JSToken.LeftParen: canBeAttribute = false; GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_ParenExpressionNoSkipToken); try{ ast = ParseExpression(); if (JSToken.RightParen != this.currentToken.token) ReportError(JSError.NoRightParen); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_ParenExpressionNoSkipToken, exc) == -1) throw exc; else ast = exc._partiallyComputedNode; }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ParenExpressionNoSkipToken); } if (ast == null) //this can only happen when catching the exception and nothing was sent up by the caller SkipTokensAndThrow(); break; // array initializer case JSToken.LeftBracket: canBeAttribute = false; Context listCtx = this.currentToken.Clone(); ASTList list = new ASTList(this.currentToken.Clone()); GetNextToken(); if (this.currentToken.token == JSToken.Identifier && this.scanner.PeekToken() == JSToken.Colon){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_BracketToken); try{ if (this.currentToken.GetCode() == "assembly"){ GetNextToken(); GetNextToken(); return new AssemblyCustomAttributeList(this.ParseCustomAttributeList()); }else{ ReportError(JSError.ExpectedAssembly); SkipTokensAndThrow(); } }catch(RecoveryTokenException exc){ exc._partiallyComputedNode = new Block(listCtx); return exc._partiallyComputedNode; }finally{ if (this.currentToken.token == JSToken.RightBracket){ this.errorToken = null; GetNextToken(); } this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BracketToken); } } while (JSToken.RightBracket != this.currentToken.token){ if (JSToken.Comma != this.currentToken.token){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet); try{ list.Append(ParseExpression(true)); if (JSToken.Comma != this.currentToken.token){ if (JSToken.RightBracket != this.currentToken.token) ReportError(JSError.NoRightBracket); break; } }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null) list.Append(exc._partiallyComputedNode); if (IndexOfToken(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet, exc) == -1){ listCtx.UpdateWith(CurrentPositionContext()); exc._partiallyComputedNode = new ArrayLiteral(listCtx, list); throw exc; }else{ if (JSToken.RightBracket == this.currentToken.token) break; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet); } }else{ list.Append(new ConstantWrapper(Missing.Value, this.currentToken.Clone())); } GetNextToken(); } listCtx.UpdateWith(this.currentToken); ast = new ArrayLiteral(listCtx, list); break; // object initializer case JSToken.LeftCurly: canBeAttribute = false; Context objCtx = this.currentToken.Clone(); GetNextToken(); ASTList fields = new ASTList(this.currentToken.Clone()); if (JSToken.RightCurly != this.currentToken.token){ for (;;){ AST field = null; AST value = null; if (JSToken.Identifier == this.currentToken.token) field = new ConstantWrapper(this.scanner.GetIdentifier(), this.currentToken.Clone()); else if (JSToken.StringLiteral == this.currentToken.token) field = new ConstantWrapper(this.scanner.GetStringLiteral(), this.currentToken.Clone()); else if (JSToken.IntegerLiteral == this.currentToken.token || JSToken.NumericLiteral == this.currentToken.token ){ String numberString = this.currentToken.GetCode(); double dValue = Convert.ToNumber(numberString, true, true, Missing.Value); field = new ConstantWrapper(dValue, this.currentToken.Clone()); ((ConstantWrapper)field).isNumericLiteral = true; }else{ ReportError(JSError.NoMemberIdentifier); field = new IdentifierLiteral("_#Missing_Field#_" + s_cDummyName++, CurrentPositionContext()); } ASTList pair = new ASTList(field.context.Clone()); GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet); try{ // get the value if (JSToken.Colon != this.currentToken.token){ ReportError(JSError.NoColon, true); value = ParseExpression(true); }else{ GetNextToken(); value = ParseExpression(true); } // put the pair into the list of fields pair.Append(field); pair.Append(value); fields.Append(pair); if (JSToken.RightCurly == this.currentToken.token) break; else{ if (JSToken.Comma == this.currentToken.token) GetNextToken(); else{ if (this.scanner.GotEndOfLine()){ ReportError(JSError.NoRightCurly); }else ReportError(JSError.NoComma, true); SkipTokensAndThrow(); } } }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null){ // the problem was in ParseExpression trying to determine value value = exc._partiallyComputedNode; pair.Append(field); pair.Append(value); fields.Append(pair); } if (IndexOfToken(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = new ObjectLiteral(objCtx, fields); throw exc; }else{ if (JSToken.Comma == this.currentToken.token) GetNextToken(); if (JSToken.RightCurly == this.currentToken.token) break; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet); } } } fields.context.UpdateWith(this.currentToken); objCtx.UpdateWith(this.currentToken); ast = new ObjectLiteral(objCtx, fields); break; // function expression case JSToken.Function: canBeAttribute = false; ast = ParseFunction((FieldAttributes)0, true, this.currentToken.Clone(), false, false, false, false, null); isFunction = true; break; default: string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (null != identifier){ if (warnForKeyword){ switch (this.currentToken.token){ case JSToken.Boolean : case JSToken.Byte : case JSToken.Char : case JSToken.Double : case JSToken.Float : case JSToken.Int : case JSToken.Long : case JSToken.Short : case JSToken.Void : break; default: ForceReportInfo(JSError.KeywordUsedAsIdentifier); break; } } canBeAttribute = false; ast = new Lookup(identifier, this.currentToken.Clone()); }else if (this.currentToken.token == JSToken.BitwiseAnd){ //& expr used outside of a parameter list ReportError(JSError.WrongUseOfAddressOf); this.errorToken = null; GetNextToken(); return this.ParseLeftHandSideExpression(isMinus, ref canBeAttribute, warnForKeyword); }else{ ReportError(JSError.ExpressionExpected); SkipTokensAndThrow(); } break; } // can be a CallExpression, that is, followed by '.' or '(' or '[' if (!isFunction) GetNextToken(); return MemberExpression(ast, newContexts, ref canBeAttribute); }
private AST ParseLeftHandSideExpression(bool isMinus, ref bool canBeAttribute, bool warnForKeyword) { AST expression = null; Context context; ASTList list2; Context context2; ASTList list3; string str6; bool flag = false; ArrayList newContexts = null; while (JSToken.New == this.currentToken.token) { if (newContexts == null) { newContexts = new ArrayList(4); } newContexts.Add(this.currentToken.Clone()); this.GetNextToken(); } JSToken token = this.currentToken.token; if (token <= JSToken.Divide) { switch (token) { case JSToken.Function: canBeAttribute = false; expression = this.ParseFunction(FieldAttributes.PrivateScope, true, this.currentToken.Clone(), false, false, false, false, null); flag = true; goto Label_0956; case JSToken.LeftCurly: { AST ast2; canBeAttribute = false; context2 = this.currentToken.Clone(); this.GetNextToken(); list3 = new ASTList(this.currentToken.Clone()); if (JSToken.RightCurly == this.currentToken.token) { goto Label_0830; } Label_05C9: ast2 = null; AST elem = null; if (JSToken.Identifier == this.currentToken.token) { ast2 = new ConstantWrapper(this.scanner.GetIdentifier(), this.currentToken.Clone()); } else if (JSToken.StringLiteral == this.currentToken.token) { ast2 = new ConstantWrapper(this.scanner.GetStringLiteral(), this.currentToken.Clone()); } else if ((JSToken.IntegerLiteral == this.currentToken.token) || (JSToken.NumericLiteral == this.currentToken.token)) { ast2 = new ConstantWrapper(Microsoft.JScript.Convert.ToNumber(this.currentToken.GetCode(), true, true, Microsoft.JScript.Missing.Value), this.currentToken.Clone()); ((ConstantWrapper) ast2).isNumericLiteral = true; } else { this.ReportError(JSError.NoMemberIdentifier); ast2 = new IdentifierLiteral("_#Missing_Field#_" + s_cDummyName++, this.CurrentPositionContext()); } ASTList list4 = new ASTList(ast2.context.Clone()); this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet); try { try { if (JSToken.Colon != this.currentToken.token) { this.ReportError(JSError.NoColon, true); elem = this.ParseExpression(true); } else { this.GetNextToken(); elem = this.ParseExpression(true); } list4.Append(ast2); list4.Append(elem); list3.Append(list4); if (JSToken.RightCurly == this.currentToken.token) { goto Label_0830; } if (JSToken.Comma == this.currentToken.token) { this.GetNextToken(); } else { if (this.scanner.GotEndOfLine()) { this.ReportError(JSError.NoRightCurly); } else { this.ReportError(JSError.NoComma, true); } this.SkipTokensAndThrow(); } } catch (RecoveryTokenException exception4) { if (exception4._partiallyComputedNode != null) { elem = exception4._partiallyComputedNode; list4.Append(ast2); list4.Append(elem); list3.Append(list4); } if (this.IndexOfToken(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet, exception4) == -1) { exception4._partiallyComputedNode = new ObjectLiteral(context2, list3); throw exception4; } if (JSToken.Comma == this.currentToken.token) { this.GetNextToken(); } if (JSToken.RightCurly == this.currentToken.token) { goto Label_0830; } } goto Label_05C9; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ObjectInitNoSkipTokenSet); } goto Label_0830; } case JSToken.Null: canBeAttribute = false; expression = new NullLiteral(this.currentToken.Clone()); goto Label_0956; case JSToken.True: canBeAttribute = false; expression = new ConstantWrapper(true, this.currentToken.Clone()); goto Label_0956; case JSToken.False: canBeAttribute = false; expression = new ConstantWrapper(false, this.currentToken.Clone()); goto Label_0956; case JSToken.This: canBeAttribute = false; expression = new ThisLiteral(this.currentToken.Clone(), false); goto Label_0956; case JSToken.Identifier: expression = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone()); goto Label_0956; case JSToken.StringLiteral: canBeAttribute = false; expression = new ConstantWrapper(this.scanner.GetStringLiteral(), this.currentToken.Clone()); goto Label_0956; case JSToken.IntegerLiteral: { canBeAttribute = false; object obj2 = Microsoft.JScript.Convert.LiteralToNumber(this.currentToken.GetCode(), this.currentToken); if (obj2 == null) { obj2 = 0; } expression = new ConstantWrapper(obj2, this.currentToken.Clone()); ((ConstantWrapper) expression).isNumericLiteral = true; goto Label_0956; } case JSToken.NumericLiteral: { canBeAttribute = false; string str = isMinus ? ("-" + this.currentToken.GetCode()) : this.currentToken.GetCode(); expression = new ConstantWrapper(Microsoft.JScript.Convert.ToNumber(str, false, false, Microsoft.JScript.Missing.Value), this.currentToken.Clone()); ((ConstantWrapper) expression).isNumericLiteral = true; goto Label_0956; } case JSToken.LeftParen: canBeAttribute = false; this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_ParenExpressionNoSkipToken); try { expression = this.ParseExpression(); if (JSToken.RightParen != this.currentToken.token) { this.ReportError(JSError.NoRightParen); } } catch (RecoveryTokenException exception) { if (this.IndexOfToken(NoSkipTokenSet.s_ParenExpressionNoSkipToken, exception) == -1) { throw exception; } expression = exception._partiallyComputedNode; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ParenExpressionNoSkipToken); } if (expression == null) { this.SkipTokensAndThrow(); } goto Label_0956; case JSToken.LeftBracket: canBeAttribute = false; context = this.currentToken.Clone(); list2 = new ASTList(this.currentToken.Clone()); this.GetNextToken(); if ((this.currentToken.token != JSToken.Identifier) || (this.scanner.PeekToken() != JSToken.Colon)) { goto Label_0561; } this.noSkipTokenSet.Add(NoSkipTokenSet.s_BracketToken); try { try { if (this.currentToken.GetCode() == "assembly") { this.GetNextToken(); this.GetNextToken(); return new AssemblyCustomAttributeList(this.ParseCustomAttributeList()); } this.ReportError(JSError.ExpectedAssembly); this.SkipTokensAndThrow(); } catch (RecoveryTokenException exception2) { exception2._partiallyComputedNode = new Block(context); return exception2._partiallyComputedNode; } goto Label_0561; } finally { if (this.currentToken.token == JSToken.RightBracket) { this.errorToken = null; this.GetNextToken(); } this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BracketToken); } goto Label_046D; case JSToken.Divide: { canBeAttribute = false; string pattern = this.scanner.ScanRegExp(); if (pattern == null) { break; } bool flag2 = false; try { new Regex(pattern, RegexOptions.ECMAScript); } catch (ArgumentException) { pattern = ""; flag2 = true; } string flags = this.scanner.ScanRegExpFlags(); if (flags == null) { expression = new RegExpLiteral(pattern, null, this.currentToken.Clone()); } else { try { expression = new RegExpLiteral(pattern, flags, this.currentToken.Clone()); } catch (JScriptException) { expression = new RegExpLiteral(pattern, null, this.currentToken.Clone()); flag2 = true; } } if (flag2) { this.ReportError(JSError.RegExpSyntax, true); } goto Label_0956; } } goto Label_0881; } if (token != JSToken.Super) { if (token == JSToken.PreProcessorConstant) { canBeAttribute = false; expression = new ConstantWrapper(this.scanner.GetPreProcessorValue(), this.currentToken.Clone()); goto Label_0956; } goto Label_0881; } canBeAttribute = false; expression = new ThisLiteral(this.currentToken.Clone(), true); goto Label_0956; Label_046D: if (JSToken.Comma != this.currentToken.token) { this.noSkipTokenSet.Add(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet); try { list2.Append(this.ParseExpression(true)); if (JSToken.Comma != this.currentToken.token) { if (JSToken.RightBracket != this.currentToken.token) { this.ReportError(JSError.NoRightBracket); } goto Label_0573; } } catch (RecoveryTokenException exception3) { if (exception3._partiallyComputedNode != null) { list2.Append(exception3._partiallyComputedNode); } if (this.IndexOfToken(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet, exception3) == -1) { context.UpdateWith(this.CurrentPositionContext()); exception3._partiallyComputedNode = new ArrayLiteral(context, list2); throw exception3; } if (JSToken.RightBracket == this.currentToken.token) { goto Label_0573; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ArrayInitNoSkipTokenSet); } } else { list2.Append(new ConstantWrapper(Microsoft.JScript.Missing.Value, this.currentToken.Clone())); } this.GetNextToken(); Label_0561: if (JSToken.RightBracket != this.currentToken.token) { goto Label_046D; } Label_0573: context.UpdateWith(this.currentToken); expression = new ArrayLiteral(context, list2); goto Label_0956; Label_0830: list3.context.UpdateWith(this.currentToken); context2.UpdateWith(this.currentToken); expression = new ObjectLiteral(context2, list3); goto Label_0956; Label_0881: str6 = JSKeyword.CanBeIdentifier(this.currentToken.token); if (str6 == null) { if (this.currentToken.token == JSToken.BitwiseAnd) { this.ReportError(JSError.WrongUseOfAddressOf); this.errorToken = null; this.GetNextToken(); return this.ParseLeftHandSideExpression(isMinus, ref canBeAttribute, warnForKeyword); } this.ReportError(JSError.ExpressionExpected); this.SkipTokensAndThrow(); goto Label_0956; } if (warnForKeyword) { switch (this.currentToken.token) { case JSToken.Boolean: case JSToken.Byte: case JSToken.Char: case JSToken.Double: case JSToken.Float: case JSToken.Int: case JSToken.Long: case JSToken.Short: case JSToken.Void: goto Label_08FC; } this.ForceReportInfo(JSError.KeywordUsedAsIdentifier); } Label_08FC: canBeAttribute = false; expression = new Lookup(str6, this.currentToken.Clone()); Label_0956: if (!flag) { this.GetNextToken(); } return this.MemberExpression(expression, newContexts, ref canBeAttribute); }