internal VariableDeclaration(Context context, Lookup identifier, TypeExpression type, AST initializer, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context) { if (initializer != null) this.context.UpdateWith(initializer.context); else if (type != null) this.context.UpdateWith(type.context); this.identifier = identifier; this.type = type; this.initializer = initializer; ScriptObject current_scope = (ScriptObject)Globals.ScopeStack.Peek(); while (current_scope is WithObject) //Can only happen at run time and only if there is an eval current_scope = current_scope.GetParent(); String name = this.identifier.ToString(); if (current_scope is ClassScope){ if (name == ((ClassScope)current_scope).name){ identifier.context.HandleError(JSError.CannotUseNameOfClass); name = name + " var"; } }else{ if (attributes != (FieldAttributes)0){ this.context.HandleError(JSError.NotInsideClass); attributes = FieldAttributes.Public; }else attributes |= FieldAttributes.Public; } FieldInfo field = ((IActivationObject)current_scope).GetLocalField(name); if (field != null){ if (field.IsLiteral || current_scope is ClassScope || type != null) identifier.context.HandleError(JSError.DuplicateName, true); this.type = type = null; } if (current_scope is ActivationObject) if (field == null || field is JSVariableField) this.field = ((ActivationObject)current_scope).AddFieldOrUseExistingField(this.identifier.ToString(), Missing.Value, attributes); else this.field = ((ActivationObject)current_scope).AddNewField(this.identifier.ToString(), null, attributes); else this.field = ((StackFrame)current_scope).AddNewField(this.identifier.ToString(), null, attributes|FieldAttributes.Static); this.field.type = type; this.field.customAttributes = customAttributes; this.field.originalContext = context; if (this.field is JSLocalField) // emit debug info for the local only if this block of code is in a section that has debug set ((JSLocalField)this.field).debugOn = this.identifier.context.document.debugOn; this.completion = new Completion(); }
internal Constant(Context context, Lookup identifier, TypeExpression type, AST value, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context){ this.attributes = attributes | FieldAttributes.InitOnly; this.customAttributes = customAttributes; this.completion = new Completion(); this.identifier = identifier; this.name = identifier.ToString(); this.value = value; ScriptObject current_scope = (ScriptObject)Globals.ScopeStack.Peek(); while (current_scope is WithObject) //Can only happen at run time and only if there is an eval current_scope = current_scope.GetParent(); if (current_scope is ClassScope){ if (this.name == ((ClassScope)current_scope).name){ identifier.context.HandleError(JSError.CannotUseNameOfClass); this.name = this.name + " const"; } if (attributes == 0) attributes = FieldAttributes.Public; }else{ if (attributes != 0) this.context.HandleError(JSError.NotInsideClass); attributes = FieldAttributes.Public; } FieldInfo field = ((IActivationObject)current_scope).GetLocalField(this.name); if (field != null){ identifier.context.HandleError(JSError.DuplicateName, true); this.name = this.name + " const"; } if (current_scope is ActivationObject) this.field = ((ActivationObject)current_scope).AddNewField(this.identifier.ToString(), value, attributes); else this.field = ((StackFrame)current_scope).AddNewField(this.identifier.ToString(), value, attributes|FieldAttributes.Static); this.field.type = type; this.field.customAttributes = customAttributes; this.field.originalContext = context; if (this.field is JSLocalField) // emit debug info for the local only if this block of code is in a section that has debug set ((JSLocalField)this.field).debugOn = this.identifier.context.document.debugOn; }
//--------------------------------------------------------------------------------------- // ParseEnumMember // // OptionalEnumMembers: // EnumMember ',' OptionalEnumMembers | // <empty> // // EnumMember : // Identifier | // Identifer '=' IntegerLiteral // //--------------------------------------------------------------------------------------- private AST ParseEnumMember(){ AST ast = null; Lookup memberName = null; AST memberValue = null; switch (this.currentToken.token){ case JSToken.Semicolon: GetNextToken(); return ParseEnumMember(); case JSToken.Identifier: memberName = new Lookup(this.currentToken.Clone()); Context context = this.currentToken.Clone(); GetNextToken(); if (JSToken.Assign == this.currentToken.token){ GetNextToken(); memberValue = ParseExpression(true); } if (JSToken.Comma == this.currentToken.token) GetNextToken(); else if (JSToken.RightCurly != this.currentToken.token) ReportError(JSError.NoComma, true); return new Constant(context, memberName, null, memberValue, FieldAttributes.Public, null); case JSToken.Var: // handle common error ReportError(JSError.NoVarInEnum, true); GetNextToken(); return ParseEnumMember(); default: ReportError(JSError.SyntaxError, true); SkipTokensAndThrow(); return ast; // will never be executed, but make the C# compiler happy } }
private AST ParseFunction(FieldAttributes visibilitySpec, bool inExpression, Context fncCtx, bool isMethod, bool isAbstract, bool isFinal, bool isInterface, CustomAttributeList customAttributes, Call function){ IdentifierLiteral name = null; AST interfaceName = null; ArrayList formalParameters = null; TypeExpression returnType = null; Block body = null; bool isGetter = false; bool isSetter = false; if (function == null){ GetNextToken(); if (isMethod) if (JSToken.Get == this.currentToken.token){ isGetter = true; GetNextToken(); }else if (JSToken.Set == this.currentToken.token){ isSetter = true; GetNextToken(); } // get the function name or make an anonymous function if in expression "position" if (JSToken.Identifier == this.currentToken.token){ name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); if (JSToken.AccessField == this.currentToken.token){ if (isInterface) // "function IBar.foo()" is illegal in an interface declaration ReportError(JSError.SyntaxError, true); GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ interfaceName = new Lookup(name.context); name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); while (JSToken.AccessField == this.currentToken.token){ GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ interfaceName = new Member(interfaceName.context.CombineWith(this.currentToken), interfaceName, new ConstantWrapper(name.ToString(), name.context)); name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); }else ReportError(JSError.NoIdentifier, true); } }else ReportError(JSError.NoIdentifier, true); } }else{ string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (null != identifier){ ForceReportInfo(JSError.KeywordUsedAsIdentifier, isMethod); name = new IdentifierLiteral(identifier, this.currentToken.Clone()); GetNextToken(); }else{ if (!inExpression){ identifier = this.currentToken.GetCode(); ReportError(JSError.NoIdentifier, true); GetNextToken(); }else identifier = ""; name = new IdentifierLiteral(identifier, CurrentPositionContext()); } } }else{ // function was passed in, this is an error condition name = function.GetName(); } // make a new state and save the old one ArrayList blockType = this.blockType; this.blockType = new ArrayList(16); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(16); FunctionScope fscope = new FunctionScope(Globals.ScopeStack.Peek(), isMethod); Globals.ScopeStack.Push(fscope); //Give declarations a place to go while building AST try{ formalParameters = new ArrayList(); Context paramArrayContext = null; if (function == null){ // get the formal parameters if (JSToken.LeftParen != this.currentToken.token) ReportError(JSError.NoLeftParen); GetNextToken(); // create the list of arguments and update the context while (JSToken.RightParen != this.currentToken.token){ if (paramArrayContext != null){ ReportError(JSError.ParamListNotLast, paramArrayContext, true); paramArrayContext = null; } String id = null; TypeExpression typeExpr = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); try{ if (JSToken.ParamArray == this.currentToken.token){ paramArrayContext = this.currentToken.Clone(); GetNextToken(); } if (JSToken.Identifier != this.currentToken.token && (id = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null){ if (JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.NoRightParen); break; }else if (JSToken.Comma == this.currentToken.token){ // We're missing an argument (or previous argument was malformed and // we skipped to the comma.) Keep trying to parse the argument list -- // we will skip the comma below. ReportError(JSError.SyntaxError, true); }else{ ReportError(JSError.SyntaxError, true); SkipTokensAndThrow(); } }else{ if (null == id) id = this.scanner.GetIdentifier(); else ForceReportInfo(JSError.KeywordUsedAsIdentifier); Context paramCtx = this.currentToken.Clone(); GetNextToken(); if (JSToken.Colon == this.currentToken.token){ typeExpr = ParseTypeExpression(); if (null != typeExpr) paramCtx.UpdateWith(typeExpr.context); } CustomAttributeList custAttrs = null; if (paramArrayContext != null){ custAttrs = new CustomAttributeList(paramArrayContext); custAttrs.Append(new CustomAttribute(paramArrayContext, new Lookup("...", paramArrayContext), new ASTList(null))); } formalParameters.Add(new ParameterDeclaration(paramCtx, id, typeExpr, custAttrs)); } // got an arg, it should be either a ',' or ')' if (JSToken.RightParen == this.currentToken.token) break; else if (JSToken.Comma != this.currentToken.token){ // deal with error in some "intelligent" way if (JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.NoRightParen); break; }else{ if (JSToken.Identifier == this.currentToken.token && typeExpr == null){ // it's possible that the guy was writing the type in C/C++ style (i.e. int x) ReportError(JSError.NoCommaOrTypeDefinitionError); }else ReportError(JSError.NoComma); } } GetNextToken(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet, exc) == -1) throw exc; }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); } } fncCtx.UpdateWith(this.currentToken); // if it is a getter/setter must have 0/1 arg only if (isGetter && formalParameters.Count != 0){ ReportError(JSError.BadPropertyDeclaration, true); isGetter = false; }else if (isSetter && formalParameters.Count != 1){ ReportError(JSError.BadPropertyDeclaration, true); isSetter = false; } GetNextToken(); // check the return type if (JSToken.Colon == this.currentToken.token){ if (isSetter) ReportError(JSError.SyntaxError); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try{ returnType = ParseTypeExpression(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_StartBlockNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ if (exc._partiallyComputedNode != null) returnType = (TypeExpression)exc._partiallyComputedNode; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } if (isSetter) returnType = null; } }else{ // function was passed in, this is an error condition function.GetParameters(formalParameters); } // read the function body of non-abstract functions. if (JSToken.LeftCurly != this.currentToken.token && (isAbstract || (isMethod && GuessIfAbstract()))){ if (!isAbstract){ isAbstract = true; ReportError(JSError.ShouldBeAbstract, fncCtx, true); } body = new Block(this.currentToken.Clone()); }else{ if (JSToken.LeftCurly != this.currentToken.token) ReportError(JSError.NoLeftCurly, true); else if (isAbstract) ReportError(JSError.AbstractWithBody, fncCtx, true); this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try{ // parse the block locally to get the exact end of function body = new Block(this.currentToken.Clone()); GetNextToken(); while (JSToken.RightCurly != this.currentToken.token){ try{ body.Append(ParseStatement()); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null){ body.Append(exc._partiallyComputedNode); } if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1) throw exc; } } body.context.UpdateWith(this.currentToken); fncCtx.UpdateWith(this.currentToken); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ Globals.ScopeStack.Pop(); //Pop current scope so that FunctionDeclaration sees proper scope stack try{ ParameterDeclaration[] foParameters = new ParameterDeclaration[formalParameters.Count]; formalParameters.CopyTo(foParameters); if (inExpression) exc._partiallyComputedNode = new FunctionExpression(fncCtx, name, foParameters, returnType, body, fscope, visibilitySpec); else exc._partiallyComputedNode = new FunctionDeclaration(fncCtx, interfaceName, name, foParameters, returnType, body, fscope, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); if (customAttributes != null) customAttributes.SetTarget(exc._partiallyComputedNode); }finally{ Globals.ScopeStack.Push(fscope); //Push it back so that the next finally can pop it } throw exc; } }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } GetNextToken(); } }finally{ // restore state this.blockType = blockType; this.labelTable = labelTable; Globals.ScopeStack.Pop(); } ParameterDeclaration[] fParameters = new ParameterDeclaration[formalParameters.Count]; formalParameters.CopyTo(fParameters); AST func; if (inExpression) func = new FunctionExpression(fncCtx, name, fParameters, returnType, body, fscope, visibilitySpec); else func = new FunctionDeclaration(fncCtx, interfaceName, name, fParameters, returnType, body, fscope, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); if (customAttributes != null) customAttributes.SetTarget(func); return func; }
//--------------------------------------------------------------------------------------- // ParseQualifiedIdentifier // // QualifiedIdentifier : // 'double' | 'float' | 'int' | 'long' | Scope Identifier // // Scope // <empty> | // Identifier '.' Scope // // The argument error is passed by the caller and it is used in error situation // to provide better error information. The caller knows in which context this // qualified identifier is parsed (i.e. var x : QualifiedIdentifier vs. // import QualifiedIdentifier) // On error condition this method may return null. Regardless of its return value, though, // this method will always be pointing to the next token and no error token will be set. //--------------------------------------------------------------------------------------- private AST ParseQualifiedIdentifier(JSError error){ GetNextToken(); AST qualid = null; string identifier = null; Context idContext = this.currentToken.Clone(); if (JSToken.Identifier != this.currentToken.token){ identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (null != identifier){ 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; } qualid = new Lookup(identifier, idContext); }else{ ReportError(error, true); SkipTokensAndThrow(); // this will always throw } }else{ qualid = new Lookup(this.scanner.GetIdentifier(), idContext); } GetNextToken(); if (JSToken.AccessField == this.currentToken.token) qualid = ParseScopeSequence(qualid, error); return qualid; }
//--------------------------------------------------------------------------------------- // ParseTryStatement // // TryStatement : // 'try' Block CatchList Finally // // CatchList : // <empty> | // CatchList Catch // // Catch : // 'catch' '(' Identifier Type ')' Block // // Finally : // <empty> | // 'finally' Block //--------------------------------------------------------------------------------------- private AST ParseTryStatement(){ Context tryCtx = this.currentToken.Clone(); Context tryEndContext = null; AST body = null; AST id = null; AST handler = null; AST finally_block = null; RecoveryTokenException excInFinally = null; TypeExpression type = null; this.blockType.Add(BlockType.Block); try{ bool catchOrFinally = false; bool foundCatchAll = false; GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token) ReportError(JSError.NoLeftCurly); this.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 exc; else body = exc._partiallyComputedNode; }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet); } while (JSToken.Catch == this.currentToken.token){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet); try{ if (handler != null){ body = new Try(tryCtx, body, id, type, handler, null, false, tryEndContext); id = null; type = null; handler = null; } catchOrFinally = true; GetNextToken(); if (JSToken.LeftParen != this.currentToken.token) ReportError(JSError.NoLeftParen); GetNextToken(); if (JSToken.Identifier != this.currentToken.token){ string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (null != identifier){ ForceReportInfo(JSError.KeywordUsedAsIdentifier); id = new Lookup(identifier, this.currentToken.Clone()); }else{ ReportError(JSError.NoIdentifier); id = new Lookup("##Exc##" + s_cDummyName++, CurrentPositionContext()); } }else id = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); try{ if (JSToken.Colon == this.currentToken.token) type = ParseTypeExpression(); else{ if (foundCatchAll) //no point in having another ForceReportInfo(id.context, JSError.UnreachableCatch); foundCatchAll = true; } if (JSToken.RightParen != this.currentToken.token) ReportError(JSError.NoRightParen); GetNextToken(); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; // rethrow throw exc; }else{ type = (TypeExpression)exc._partiallyComputedNode; if (this.currentToken.token == JSToken.RightParen) GetNextToken(); } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); } if (JSToken.LeftCurly != this.currentToken.token) ReportError(JSError.NoLeftCurly); handler = ParseBlock(); tryCtx.UpdateWith(handler.context); }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode == null) handler = new Block(CurrentPositionContext()); else handler = exc._partiallyComputedNode; if (IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exc) == -1){ Debug.Assert((type == null) ? exc._partiallyComputedNode == null : true); if (type != null) exc._partiallyComputedNode = new Try(tryCtx, body, id, type, handler, null, false, tryEndContext); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet); } } try{ if (JSToken.Finally == this.currentToken.token){ GetNextToken(); this.blockType.Add(BlockType.Finally); try{ finally_block = ParseBlock(); catchOrFinally = true; }finally{ this.blockType.RemoveAt(this.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()); // make a dummy empty block } }finally{ this.blockType.RemoveAt(this.blockType.Count - 1); } bool isFinallyEscaped = false; if (this.finallyEscaped > 0){ this.finallyEscaped--; isFinallyEscaped = true; } if (excInFinally != null){ excInFinally._partiallyComputedNode = new Try(tryCtx, body, id, type, handler, finally_block, isFinallyEscaped, tryEndContext); throw excInFinally; }else return new Try(tryCtx, body, id, type, handler, finally_block, isFinallyEscaped, tryEndContext); }
//--------------------------------------------------------------------------------------- // ParseIdentifierInitializer // // Does the real work of parsing a single variable declaration. // inToken is JSToken.In whenever the potential expression that initialize a variable // cannot contain an 'in', as in the for statement. inToken is JSToken.None otherwise //--------------------------------------------------------------------------------------- private AST ParseIdentifierInitializer(JSToken inToken, FieldAttributes visibility, CustomAttributeList customAttributes, JSToken kind){ Lookup id = null; TypeExpression typeExpr = null; AST assignmentExpr = null; RecoveryTokenException except = null; GetNextToken(); if (JSToken.Identifier != this.currentToken.token){ String identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (null != identifier){ ForceReportInfo(JSError.KeywordUsedAsIdentifier); id = new Lookup(identifier, this.currentToken.Clone()); }else{ // make up an identifier and keep going; life goes on... ReportError(JSError.NoIdentifier); id = new Lookup("#_Missing Identifier_#" + s_cDummyName++, CurrentPositionContext()); } }else id = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone()); GetNextToken(); Context context = id.context.Clone(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet); try{ if (JSToken.Colon == this.currentToken.token){ try{ typeExpr = ParseTypeExpression(); }catch(RecoveryTokenException exc){ typeExpr = (TypeExpression)exc._partiallyComputedNode; throw exc; }finally{ if (null != typeExpr) context.UpdateWith(typeExpr.context); } } if (JSToken.Assign == this.currentToken.token || JSToken.Equal == this.currentToken.token){ if (JSToken.Equal == this.currentToken.token) ReportError(JSError.NoEqual, true); GetNextToken(); try{ assignmentExpr = ParseExpression(true, inToken); }catch(RecoveryTokenException exc){ assignmentExpr = exc._partiallyComputedNode; throw exc; }finally{ if (null != assignmentExpr) context.UpdateWith(assignmentExpr.context); } } }catch(RecoveryTokenException exc){ // If the exception is in the vardecl no-skip set then we successfully // recovered to the end of the declaration and can just return // normally. Otherwise we re-throw after constructing the partial result. if (IndexOfToken(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet, exc) == -1) except = exc; }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet); } AST result = null; if (JSToken.Var == kind) result = new VariableDeclaration(context, id, typeExpr, assignmentExpr, visibility, customAttributes); else{ if (assignmentExpr == null) ForceReportInfo(JSError.NoEqual); result = new Constant(context, id, typeExpr, assignmentExpr, visibility, customAttributes); } if (customAttributes != null) customAttributes.SetTarget(result); if (null != except){ except._partiallyComputedNode = result; throw except; } return result; }
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); }
internal VariableDeclaration(Context context, Lookup identifier, TypeExpression type, AST initializer, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context) { if (initializer != null) { this.context.UpdateWith(initializer.context); } else if (type != null) { this.context.UpdateWith(type.context); } this.identifier = identifier; this.type = type; this.initializer = initializer; ScriptObject current_scope = (ScriptObject)Globals.ScopeStack.Peek(); while (current_scope is WithObject) //Can only happen at run time and only if there is an eval { current_scope = current_scope.GetParent(); } String name = this.identifier.ToString(); if (current_scope is ClassScope) { if (name == ((ClassScope)current_scope).name) { identifier.context.HandleError(JSError.CannotUseNameOfClass); name = name + " var"; } } else { if (attributes != (FieldAttributes)0) { this.context.HandleError(JSError.NotInsideClass); attributes = FieldAttributes.Public; } else { attributes |= FieldAttributes.Public; } } FieldInfo field = ((IActivationObject)current_scope).GetLocalField(name); if (field != null) { if (field.IsLiteral || current_scope is ClassScope || type != null) { identifier.context.HandleError(JSError.DuplicateName, true); } this.type = type = null; } if (current_scope is ActivationObject) { if (field == null || field is JSVariableField) { this.field = ((ActivationObject)current_scope).AddFieldOrUseExistingField(this.identifier.ToString(), Missing.Value, attributes); } else { this.field = ((ActivationObject)current_scope).AddNewField(this.identifier.ToString(), null, attributes); } } else { this.field = ((StackFrame)current_scope).AddNewField(this.identifier.ToString(), null, attributes | FieldAttributes.Static); } this.field.type = type; this.field.customAttributes = customAttributes; this.field.originalContext = context; if (this.field is JSLocalField) { // emit debug info for the local only if this block of code is in a section that has debug set ((JSLocalField)this.field).debugOn = this.identifier.context.document.debugOn; } this.completion = new Completion(); }
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 ParseTryStatement() { Context context = this.currentToken.Clone(); Context closingBraceContext = null; AST body = null; AST identifier = null; AST handler = null; AST ast4 = null; RecoveryTokenException exception = null; TypeExpression type = null; this.blockType.Add(BlockType.Block); try { bool flag = false; bool flag2 = false; this.GetNextToken(); if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } this.noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet); try { try { body = this.ParseBlock(out closingBraceContext); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exception2) == -1) { throw exception2; } body = exception2._partiallyComputedNode; } goto Label_02E5; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet); } Label_00A6: this.noSkipTokenSet.Add(NoSkipTokenSet.s_NoTrySkipTokenSet); try { if (handler != null) { body = new Try(context, body, identifier, type, handler, null, false, closingBraceContext); identifier = null; type = null; handler = null; } flag = true; this.GetNextToken(); if (JSToken.LeftParen != this.currentToken.token) { this.ReportError(JSError.NoLeftParen); } this.GetNextToken(); if (JSToken.Identifier != this.currentToken.token) { string name = JSKeyword.CanBeIdentifier(this.currentToken.token); if (name != null) { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier); identifier = new Lookup(name, this.currentToken.Clone()); } else { this.ReportError(JSError.NoIdentifier); identifier = new Lookup("##Exc##" + s_cDummyName++, this.CurrentPositionContext()); } } else { identifier = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone()); } this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); try { if (JSToken.Colon == this.currentToken.token) { type = this.ParseTypeExpression(); } else { if (flag2) { this.ForceReportInfo(identifier.context, JSError.UnreachableCatch); } flag2 = true; } if (JSToken.RightParen != this.currentToken.token) { this.ReportError(JSError.NoRightParen); } this.GetNextToken(); } catch (RecoveryTokenException exception3) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exception3) == -1) { exception3._partiallyComputedNode = null; throw exception3; } type = (TypeExpression) exception3._partiallyComputedNode; if (this.currentToken.token == JSToken.RightParen) { this.GetNextToken(); } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet); } if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } handler = this.ParseBlock(); context.UpdateWith(handler.context); } catch (RecoveryTokenException exception4) { if (exception4._partiallyComputedNode == null) { handler = new Block(this.CurrentPositionContext()); } else { handler = exception4._partiallyComputedNode; } if (this.IndexOfToken(NoSkipTokenSet.s_NoTrySkipTokenSet, exception4) == -1) { if (type != null) { exception4._partiallyComputedNode = new Try(context, body, identifier, type, handler, null, false, closingBraceContext); } throw exception4; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_NoTrySkipTokenSet); } Label_02E5: if (JSToken.Catch == this.currentToken.token) { goto Label_00A6; } try { if (JSToken.Finally == this.currentToken.token) { this.GetNextToken(); this.blockType.Add(BlockType.Finally); try { ast4 = this.ParseBlock(); flag = true; } finally { this.blockType.RemoveAt(this.blockType.Count - 1); } context.UpdateWith(ast4.context); } } catch (RecoveryTokenException exception5) { exception = exception5; } if (!flag) { this.ReportError(JSError.NoCatch, true); ast4 = new Block(this.CurrentPositionContext()); } } finally { this.blockType.RemoveAt(this.blockType.Count - 1); } bool finallyHasControlFlowOutOfIt = false; if (this.finallyEscaped > 0) { this.finallyEscaped--; finallyHasControlFlowOutOfIt = true; } if (exception != null) { exception._partiallyComputedNode = new Try(context, body, identifier, type, handler, ast4, finallyHasControlFlowOutOfIt, closingBraceContext); throw exception; } return new Try(context, body, identifier, type, handler, ast4, finallyHasControlFlowOutOfIt, closingBraceContext); }
private AST ParseAttributes(AST statement, bool unambiguousContext, bool isInsideClass, out bool parsedOK) { JSToken none; bool flag; bool flag2; AST ast = statement; ArrayList list = new ArrayList(); ArrayList list2 = new ArrayList(); ArrayList list3 = new ArrayList(); AST ast2 = null; ArrayList list4 = new ArrayList(); Context context = null; Context context2 = null; Context context3 = null; int num = 0; if (unambiguousContext) { num = 2; } FieldAttributes privateScope = FieldAttributes.PrivateScope; FieldAttributes family = FieldAttributes.PrivateScope; Context enumCtx = null; if (statement != null) { ast2 = statement; list4.Add(statement); list.Add(this.CurrentPositionContext()); enumCtx = statement.context.Clone(); num = 1; } else { enumCtx = this.currentToken.Clone(); } parsedOK = true; Label_0078: none = JSToken.None; 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: parsedOK = false; ast2 = new Lookup(this.currentToken); none = JSToken.None; list4.Add(ast2); this.GetNextToken(); goto Label_0A12; case JSToken.Enum: { int num8 = 0; int num9 = list3.Count; while (num8 < num9) { this.ReportError((JSError) list3[num8], (Context) list3[num8 + 1], true); num8 += 2; } enumCtx.UpdateWith(this.currentToken); if (context != null) { this.ReportError(JSError.IllegalVisibility, context, true); } if (context3 != null) { this.ReportError(JSError.IllegalVisibility, context3, true); } if (context2 != null) { this.ReportError(JSError.IllegalVisibility, context2, true); } return this.ParseEnum(privateScope, enumCtx, this.FromASTListToCustomAttributeList(list4)); } case JSToken.Interface: if (context != null) { this.ReportError(JSError.IllegalVisibility, context, true); context = null; } if (context3 != null) { this.ReportError(JSError.IllegalVisibility, context3, true); context3 = null; } if (context2 != null) { this.ReportError(JSError.IllegalVisibility, context2, true); context2 = null; } break; case JSToken.Internal: case JSToken.Abstract: case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Final: none = this.currentToken.token; goto Label_042A; case JSToken.Var: case JSToken.Const: { int num2 = 0; int num3 = list3.Count; while (num2 < num3) { this.ReportError((JSError) list3[num2], (Context) list3[num2 + 1], true); num2 += 2; } if (context != null) { this.ReportError(JSError.IllegalVisibility, context, true); } if (context3 != null) { this.ReportError(JSError.IllegalVisibility, context3, true); } enumCtx.UpdateWith(this.currentToken); return this.ParseVariableStatement(privateScope, this.FromASTListToCustomAttributeList(list4), this.currentToken.token); } case JSToken.Class: break; case JSToken.Function: { int num4 = 0; int num5 = list3.Count; while (num4 < num5) { this.ReportError((JSError) list3[num4], (Context) list3[num4 + 1], true); num4 += 2; } enumCtx.UpdateWith(this.currentToken); if (context2 != null) { if (context != null) { context2.HandleError(JSError.AbstractCannotBeStatic); context2 = null; } else if (context3 != null) { context3.HandleError(JSError.StaticIsAlreadyFinal); context3 = null; } } if (context != null) { if (context3 != null) { context3.HandleError(JSError.FinalPrecludesAbstract); context3 = null; } if (family == FieldAttributes.Private) { context.HandleError(JSError.AbstractCannotBePrivate); family = FieldAttributes.Family; } } return this.ParseFunction(privateScope, false, enumCtx, isInsideClass, context != null, context3 != null, false, this.FromASTListToCustomAttributeList(list4)); } case JSToken.Identifier: goto Label_042A; default: goto Label_047E; } int num6 = 0; int count = list3.Count; while (num6 < count) { this.ReportError((JSError) list3[num6], (Context) list3[num6 + 1], true); num6 += 2; } enumCtx.UpdateWith(this.currentToken); if ((context3 != null) && (context != null)) { context3.HandleError(JSError.FinalPrecludesAbstract); } return this.ParseClass(privateScope, context2 != null, enumCtx, context != null, context3 != null, this.FromASTListToCustomAttributeList(list4)); Label_042A: flag2 = true; statement = this.ParseUnaryExpression(out flag, ref flag2, false, none == JSToken.None); ast2 = statement; if (none != JSToken.None) { if (statement is Lookup) { goto Label_07ED; } if (num != 2) { list2.Add(this.currentToken.Clone()); } } none = JSToken.None; if (flag2) { list4.Add(statement); goto Label_0A12; } Label_047E: parsedOK = false; if (num != 2) { if ((ast != statement) || (statement == null)) { statement = ast2; int num10 = 0; int num11 = list2.Count; while (num10 < num11) { this.ForceReportInfo((Context) list2[num10], JSError.KeywordUsedAsIdentifier); num10++; } int num12 = 0; int num13 = list.Count; while (num12 < num13) { if (!this.currentToken.Equals((Context) list[num12])) { this.ReportError(JSError.NoSemicolon, (Context) list[num12], true); } num12++; } } return statement; } if (list4.Count > 0) { AST ast3 = (AST) list4[list4.Count - 1]; if (ast3 is Lookup) { if ((JSToken.Semicolon == this.currentToken.token) || (JSToken.Colon == this.currentToken.token)) { this.ReportError(JSError.BadVariableDeclaration, ast3.context.Clone()); this.SkipTokensAndThrow(); } } else if ((ast3 is Call) && ((Call) ast3).CanBeFunctionDeclaration()) { if ((JSToken.Colon == this.currentToken.token) || (JSToken.LeftCurly == this.currentToken.token)) { this.ReportError(JSError.BadFunctionDeclaration, ast3.context.Clone(), true); if (JSToken.Colon == this.currentToken.token) { this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try { this.SkipTokensAndThrow(); } catch (RecoveryTokenException) { } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } } this.errorToken = null; if (JSToken.LeftCurly == this.currentToken.token) { FunctionScope item = new FunctionScope(this.Globals.ScopeStack.Peek(), isInsideClass); this.Globals.ScopeStack.Push(item); try { this.ParseBlock(); } finally { this.Globals.ScopeStack.Pop(); } this.SkipTokensAndThrow(); } } else { this.ReportError(JSError.SyntaxError, ast3.context.Clone()); } this.SkipTokensAndThrow(); } } if ((JSToken.LeftCurly == this.currentToken.token) && isInsideClass) { int num14 = 0; int num15 = list3.Count; while (num14 < num15) { this.ReportError((JSError) list3[num14], (Context) list3[num14 + 1]); num14 += 2; } if (context2 == null) { this.ReportError(JSError.StaticMissingInStaticInit, this.CurrentPositionContext()); } string name = ((ClassScope) this.Globals.ScopeStack.Peek()).name; bool flag3 = true; foreach (object obj2 in list4) { flag3 = false; if (((context2 == null) || !(obj2 is Lookup)) || ((obj2.ToString() != name) || (((Lookup) obj2).context.StartColumn <= context2.StartColumn))) { this.ReportError(JSError.SyntaxError, ((AST) obj2).context); } } if (flag3) { this.ReportError(JSError.NoIdentifier, this.CurrentPositionContext()); } this.errorToken = null; parsedOK = true; return this.ParseStaticInitializer(enumCtx); } this.ReportError(JSError.MissingConstructForAttributes, enumCtx.CombineWith(this.currentToken)); this.SkipTokensAndThrow(); Label_07ED: switch (none) { case JSToken.Internal: family = FieldAttributes.Assembly; break; case JSToken.Abstract: if (context == null) { context = statement.context.Clone(); } else { list3.Add(JSError.SyntaxError); list3.Add(statement.context.Clone()); } goto Label_0A12; case JSToken.Public: family = FieldAttributes.Public; break; case JSToken.Static: if (!isInsideClass) { list3.Add(JSError.NotInsideClass); list3.Add(statement.context.Clone()); break; } family = FieldAttributes.Static; if (context2 == null) { context2 = statement.context.Clone(); break; } list3.Add(JSError.SyntaxError); list3.Add(statement.context.Clone()); break; case JSToken.Private: if (!isInsideClass) { list3.Add(JSError.NotInsideClass); list3.Add(statement.context.Clone()); break; } family = FieldAttributes.Private; break; case JSToken.Protected: if (!isInsideClass) { list3.Add(JSError.NotInsideClass); list3.Add(statement.context.Clone()); break; } family = FieldAttributes.Family; break; case JSToken.Final: if (context3 == null) { context3 = statement.context.Clone(); } else { list3.Add(JSError.SyntaxError); list3.Add(statement.context.Clone()); } goto Label_0A12; } if (((privateScope & FieldAttributes.FieldAccessMask) == family) && (family != FieldAttributes.PrivateScope)) { list3.Add(JSError.DupVisibility); list3.Add(statement.context.Clone()); } else if (((privateScope & FieldAttributes.FieldAccessMask) > FieldAttributes.PrivateScope) && ((family & FieldAttributes.FieldAccessMask) > FieldAttributes.PrivateScope)) { if (((family == FieldAttributes.Family) && ((privateScope & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly)) || ((family == FieldAttributes.Assembly) && ((privateScope & FieldAttributes.FieldAccessMask) == FieldAttributes.Family))) { privateScope &= ~FieldAttributes.FieldAccessMask; privateScope |= FieldAttributes.FamORAssem; } else { list3.Add(JSError.IncompatibleVisibility); list3.Add(statement.context.Clone()); } } else { privateScope |= family; enumCtx.UpdateWith(statement.context); } Label_0A12: if (num != 2) { if (this.scanner.GotEndOfLine()) { num = 0; } else { num++; list.Add(this.currentToken.Clone()); } } goto Label_0078; }
private AST ParseQualifiedIdentifier(JSError error) { this.GetNextToken(); AST qualid = null; string name = null; Context context = this.currentToken.Clone(); if (JSToken.Identifier == this.currentToken.token) { qualid = new Lookup(this.scanner.GetIdentifier(), context); } else { name = JSKeyword.CanBeIdentifier(this.currentToken.token); if (name == null) { this.ReportError(error, true); this.SkipTokensAndThrow(); } else { 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: this.ForceReportInfo(JSError.KeywordUsedAsIdentifier); break; } qualid = new Lookup(name, context); } } this.GetNextToken(); if (JSToken.AccessField == this.currentToken.token) { qualid = this.ParseScopeSequence(qualid, error); } return qualid; }
private AST ParsePackage(Context packageContext) { AST ast4; this.GetNextToken(); AST expression = null; bool flag = this.scanner.GotEndOfLine(); if (JSToken.Identifier != this.currentToken.token) { if (JSScanner.CanParseAsExpression(this.currentToken.token)) { bool flag2; this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); expression = new Lookup("package", packageContext); expression = this.MemberExpression(expression, null); expression = this.ParsePostfixExpression(expression, out flag2); expression = this.ParseExpression(expression, false, flag2, JSToken.None); return new Expression(expression.context.Clone(), expression); } if (flag) { this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); return new Lookup("package", packageContext); } if ((JSToken.Increment == this.currentToken.token) || (JSToken.Decrement == this.currentToken.token)) { bool flag3; this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); expression = new Lookup("package", packageContext); expression = this.ParsePostfixExpression(expression, out flag3); expression = this.ParseExpression(expression, false, false, JSToken.None); return new Expression(expression.context.Clone(), expression); } } else { this.errorToken = this.currentToken; expression = this.ParseQualifiedIdentifier(JSError.NoIdentifier); } Context context = null; if ((JSToken.LeftCurly != this.currentToken.token) && (expression == null)) { context = this.currentToken.Clone(); this.GetNextToken(); } if (JSToken.LeftCurly == this.currentToken.token) { if (expression == null) { if (context == null) { context = this.currentToken.Clone(); } this.ReportError(JSError.NoIdentifier, context, true); } } else if (expression == null) { this.ReportError(JSError.SyntaxError, packageContext); if (JSScanner.CanStartStatement(context.token)) { this.currentToken = context; return this.ParseStatement(); } if (JSScanner.CanStartStatement(this.currentToken.token)) { this.errorToken = null; return this.ParseStatement(); } this.ReportError(JSError.SyntaxError); this.SkipTokensAndThrow(); } else { if (flag) { bool flag4; this.ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); Block block = new Block(packageContext.Clone()); block.Append(new Lookup("package", packageContext)); expression = this.MemberExpression(expression, null); expression = this.ParsePostfixExpression(expression, out flag4); expression = this.ParseExpression(expression, false, true, JSToken.None); block.Append(new Expression(expression.context.Clone(), expression)); block.context.UpdateWith(expression.context); return block; } this.ReportError(JSError.NoLeftCurly); } PackageScope item = new PackageScope(this.Globals.ScopeStack.Peek()); this.Globals.ScopeStack.Push(item); try { string name = (expression != null) ? expression.ToString() : "anonymous package"; item.name = name; packageContext.UpdateWith(this.currentToken); ASTList classList = new ASTList(packageContext); this.GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); try { while (this.currentToken.token != JSToken.RightCurly) { AST statement = null; try { switch (this.currentToken.token) { case JSToken.Identifier: { bool flag6; bool canBeAttribute = true; statement = this.ParseUnaryExpression(out flag6, ref canBeAttribute, false); if (canBeAttribute) { bool flag8; statement = this.ParseAttributes(statement, true, false, out flag8); if (flag8 && (statement is Class)) { classList.Append(statement); continue; } } this.ReportError(JSError.OnlyClassesAllowed, statement.context.Clone(), true); this.SkipTokensAndThrow(); continue; } case JSToken.Interface: case JSToken.Class: { classList.Append(this.ParseClass(FieldAttributes.PrivateScope, false, this.currentToken.Clone(), false, false, null)); continue; } case JSToken.Enum: { classList.Append(this.ParseEnum(FieldAttributes.PrivateScope, this.currentToken.Clone(), null)); continue; } case JSToken.Import: { this.ReportError(JSError.InvalidImport, true); try { this.ParseImportStatement(); } catch (RecoveryTokenException) { } continue; } case JSToken.Package: { Context context2 = this.currentToken.Clone(); if (this.ParsePackage(context2) is Package) { this.ReportError(JSError.PackageInWrongContext, context2, true); } continue; } case JSToken.Internal: case JSToken.Abstract: case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Final: { bool flag5; statement = this.ParseAttributes(null, true, false, out flag5); if (!flag5 || !(statement is Class)) { break; } classList.Append(statement); continue; } case JSToken.Semicolon: { this.GetNextToken(); continue; } case JSToken.EndOfFile: this.EOFError(JSError.ErrEOF); throw new EndOfFile(); default: goto Label_04D9; } this.ReportError(JSError.OnlyClassesAllowed, statement.context.Clone(), true); this.SkipTokensAndThrow(); continue; Label_04D9: this.ReportError(JSError.OnlyClassesAllowed, (statement != null) ? statement.context.Clone() : this.CurrentPositionContext(), true); this.SkipTokensAndThrow(); continue; } catch (RecoveryTokenException exception) { if ((exception._partiallyComputedNode != null) && (exception._partiallyComputedNode is Class)) { classList.Append((Class) exception._partiallyComputedNode); exception._partiallyComputedNode = null; } if (this.IndexOfToken(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet, exception) == -1) { throw exception; } continue; } } } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception2) == -1) { this.ReportError(JSError.NoRightCurly, this.CurrentPositionContext()); exception2._partiallyComputedNode = new Package(name, expression, classList, packageContext); throw exception2; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } this.GetNextToken(); ast4 = new Package(name, expression, classList, packageContext); } finally { this.Globals.ScopeStack.Pop(); } return ast4; }
internal string[] ParseNamedBreakpoint(out int argNumber) { argNumber = 0; AST ast = this.ParseQualifiedIdentifier(JSError.SyntaxError); if (ast == null) { return null; } string[] strArray = new string[4]; strArray[0] = ast.ToString(); if (JSToken.LeftParen == this.currentToken.token) { string name = null; string str2 = null; AST qualid = null; strArray[1] = ""; this.GetNextToken(); while (JSToken.RightParen != this.currentToken.token) { string[] strArray2; name = null; if ((JSToken.Identifier != this.currentToken.token) && ((name = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null)) { return null; } if (name == null) { name = this.scanner.GetIdentifier(); } qualid = new Lookup(name, this.currentToken.Clone()); this.GetNextToken(); if (JSToken.AccessField == this.currentToken.token) { str2 = this.ParseScopeSequence(qualid, JSError.SyntaxError).ToString(); while (JSToken.LeftBracket == this.currentToken.token) { this.GetNextToken(); if (JSToken.RightBracket != this.currentToken.token) { return null; } str2 = str2 + "[]"; this.GetNextToken(); } } else { if (JSToken.Colon == this.currentToken.token) { this.GetNextToken(); if (JSToken.RightParen == this.currentToken.token) { return null; } continue; } str2 = qualid.ToString(); } (strArray2 = strArray)[1] = strArray2[1] + str2 + " "; argNumber++; if (JSToken.Comma == this.currentToken.token) { this.GetNextToken(); if (JSToken.RightParen == this.currentToken.token) { return null; } } } this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { this.GetNextToken(); name = null; if ((JSToken.Identifier != this.currentToken.token) && ((name = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null)) { return null; } if (name == null) { name = this.scanner.GetIdentifier(); } qualid = new Lookup(name, this.currentToken.Clone()); this.GetNextToken(); if (JSToken.AccessField == this.currentToken.token) { qualid = this.ParseScopeSequence(qualid, JSError.SyntaxError); strArray[2] = qualid.ToString(); while (JSToken.LeftBracket == this.currentToken.token) { string[] strArray3; this.GetNextToken(); if (JSToken.RightBracket != this.currentToken.token) { return null; } (strArray3 = strArray)[2] = strArray3[2] + "[]"; this.GetNextToken(); } } else { strArray[2] = qualid.ToString(); } } } if (JSToken.FirstBinaryOp == this.currentToken.token) { this.GetNextToken(); if (JSToken.IntegerLiteral != this.currentToken.token) { return null; } strArray[3] = this.currentToken.GetCode(); this.GetNextToken(); } if (this.currentToken.token != JSToken.EndOfFile) { return null; } return strArray; }
//--------------------------------------------------------------------------------------- // ParseNamedBreakpoint // // Used by the debugger to parsed a named breakpoint, that is a name of a function with // possible arguments and optionally followed by an il offset //--------------------------------------------------------------------------------------- internal String[] ParseNamedBreakpoint(out int argNumber){ argNumber = 0; // parse the function name AST function = ParseQualifiedIdentifier(JSError.SyntaxError); if (function != null){ String[] parsedFunction = new String[4]; parsedFunction[0] = function.ToString(); if (JSToken.LeftParen == this.currentToken.token){ String id = null; String typeString = null; AST qualid = null; parsedFunction[1] = ""; GetNextToken(); // parse the formal parameters while (JSToken.RightParen != this.currentToken.token){ id = null; if (JSToken.Identifier != this.currentToken.token && (id = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null){ return null; }else{ if (null == id) id = this.scanner.GetIdentifier(); qualid = new Lookup(id, this.currentToken.Clone()); GetNextToken(); if (JSToken.AccessField == this.currentToken.token){ qualid = ParseScopeSequence(qualid, JSError.SyntaxError); typeString = qualid.ToString(); while (JSToken.LeftBracket == this.currentToken.token){ GetNextToken(); if (JSToken.RightBracket != this.currentToken.token) return null; typeString += "[]"; GetNextToken(); } }else if (JSToken.Colon == this.currentToken.token){ GetNextToken(); if (JSToken.RightParen == this.currentToken.token) return null; continue; }else{ typeString = qualid.ToString(); } parsedFunction[1] += typeString + " "; } argNumber++; if (JSToken.Comma == this.currentToken.token){ GetNextToken(); if (JSToken.RightParen == this.currentToken.token) return null; } } GetNextToken(); // parse a return value if any if (JSToken.Colon == this.currentToken.token){ GetNextToken(); id = null; if (JSToken.Identifier != this.currentToken.token && (id = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null){ return null; }else{ if (null == id) id = this.scanner.GetIdentifier(); qualid = new Lookup(id, this.currentToken.Clone()); GetNextToken(); if (JSToken.AccessField == this.currentToken.token){ qualid = ParseScopeSequence(qualid, JSError.SyntaxError); parsedFunction[2] = qualid.ToString(); while (JSToken.LeftBracket == this.currentToken.token){ GetNextToken(); if (JSToken.RightBracket != this.currentToken.token) return null; parsedFunction[2] += "[]"; GetNextToken(); } }else{ parsedFunction[2] = qualid.ToString(); } } } } if (JSToken.Plus == this.currentToken.token){ GetNextToken(); if (JSToken.IntegerLiteral != this.currentToken.token) return null; parsedFunction[3] = this.currentToken.GetCode(); GetNextToken(); } if (JSToken.EndOfFile != this.currentToken.token) return null; // some extra crap return parsedFunction; } return null; }
internal bool IsExpandoAttribute() //Use only before partial evaluation has been done { Lookup id = this.ctor as Lookup; return(id != null && id.Name == "expando"); }
//--------------------------------------------------------------------------------------- // ParsePackage // // Package : // 'package' QualifiedIdentifier '{' ClassList '}' // // ClassList : // <empty> | // Class ClassList | // Attributes Class ClassList | // Attributes Enum ClassList //--------------------------------------------------------------------------------------- // Because 'package' is not a reserved word in JS5 we have to deal with an ambiguity // in the grammar. A source sequence like the following // package // x // { } // can be legally parsed in two ways: // Identifier Identifier Block or // Package // we give Package priority in this situation. // Here is how we deal with some possible cases: // 1- ** package <no line break> QualifiedIdentifier ** is parsed unambiguously as a package production regardless of what comes after Identifier // 2- ** package <no line break> NotOneOf(Operator | '[' | '.' | '(' | Identifier) '{' ** is parsed as a package production with an error // 3- ** package <line break> '{' ** is parsed as a package (anonymous) with an error // 4- ** package <line break> Not(Identifier) ** is never parsed as a package private AST ParsePackage(Context packageContext){ GetNextToken(); AST qualid = null; bool gotLineBreak = this.scanner.GotEndOfLine(); // erroneous package production if (JSToken.Identifier != this.currentToken.token){ if (JSScanner.CanParseAsExpression(this.currentToken.token)){ // it's an expression. Report a warning. package and this.currentToken can be an expression (i.e. 'package +') ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); qualid = new Lookup("package", packageContext); // get the member expression qualid = MemberExpression(qualid, null); bool isLeftHandSide; qualid = ParsePostfixExpression(qualid, out isLeftHandSide); qualid = ParseExpression(qualid, false, isLeftHandSide, JSToken.None); return new Expression(qualid.context.Clone(), qualid); }else if (!gotLineBreak){ if (JSToken.Increment == this.currentToken.token || JSToken.Decrement == this.currentToken.token){ // it's a postfix expression. Report a warning ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); bool dummy; qualid = new Lookup("package", packageContext); qualid = ParsePostfixExpression(qualid, out dummy); qualid = ParseExpression(qualid, false, false, JSToken.None); return new Expression(qualid.context.Clone(), qualid); } }else{ // it's an expression. Report a warning which, as a side effect, will make the current token be the next token fetched ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); return new Lookup("package", packageContext); } }else{ // it is an identifier, parse it as a qualified identifier this.errorToken = this.currentToken; // this will make GetNextToken() in ParseQualifiedIdentifier() return this.currentToken qualid = ParseQualifiedIdentifier(JSError.NoIdentifier); } // if we are here we have: // ** package QualifiedIdentifier ** or // ** package SomeNonSenseToken **, that is a token that does not make an expression Context nonSenseToken = null; if (JSToken.LeftCurly != this.currentToken.token && qualid == null){ // we want to peek and see whether the next token is a LeftCurly nonSenseToken = this.currentToken.Clone(); GetNextToken(); } if (JSToken.LeftCurly == this.currentToken.token){ // sounds like a package, possibly with an error. If qualid is not null is actually a good package, otherwise we treat it // as an anonymous package and keep going. if (qualid == null){ if (nonSenseToken == null) nonSenseToken = this.currentToken.Clone(); ReportError(JSError.NoIdentifier, nonSenseToken, true); } }else{ if (qualid == null){ // this is pretty screwy, let's ignore the package keyword for a start ReportError(JSError.SyntaxError, packageContext); if (JSScanner.CanStartStatement(nonSenseToken.token)){ // this is tricky we assign nonSenseToken to this.currentToken and call ParseStatement, because we know it is a statement start token. // The parser should then call GetNextToken() which will return the this.currentToken that is assigned to this.errorToken this.currentToken = nonSenseToken; return ParseStatement(); }else{ //ReportError(JSError.SyntaxError, nonSenseToken); if (JSScanner.CanStartStatement(this.currentToken.token)){ this.errorToken = null; return ParseStatement(); }else{ ReportError(JSError.SyntaxError); SkipTokensAndThrow(); } } }else{ if (gotLineBreak){ // we are here with the following: 'package' <line break> QalifiedIdentifier' however we do not have a left curly. // if the token in our hand can start an expression we go with two expressions, otherwise we accept it as a package //if (JSScanner.CanParseAsExpression(this.currentToken.token)){ ReportError(JSError.KeywordUsedAsIdentifier, packageContext.Clone(), true); Block block = new Block(packageContext.Clone()); block.Append(new Lookup("package", packageContext)); qualid = MemberExpression(qualid, null); bool isLeftHandSide; qualid = ParsePostfixExpression(qualid, out isLeftHandSide); qualid = ParseExpression(qualid, false, true, JSToken.None); block.Append(new Expression(qualid.context.Clone(), qualid)); block.context.UpdateWith(qualid.context); return block; //} } // the package production rule is entered regardless of the presence of a left curly. ReportError(JSError.NoLeftCurly); } } PackageScope pscope = new PackageScope(Globals.ScopeStack.Peek()); Globals.ScopeStack.Push(pscope); //Give declarations a place to go while building AST try{ string name = (qualid != null) ? qualid.ToString() : "anonymous package"; pscope.name = name; packageContext.UpdateWith(this.currentToken); ASTList classList = new ASTList(packageContext); GetNextToken(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); try{ while (this.currentToken.token != JSToken.RightCurly){ AST ast = null; try{ switch (this.currentToken.token){ case JSToken.Interface: case JSToken.Class: classList.Append(ParseClass((FieldAttributes)0, false, this.currentToken.Clone(), false, false, null)); break; case JSToken.Enum: classList.Append(ParseEnum((FieldAttributes)0, this.currentToken.Clone(), null)); break; case JSToken.Internal: case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Abstract: case JSToken.Final: bool parsedOK; ast = ParseAttributes(null, true, false, out parsedOK); if (parsedOK){ if (ast is Class){ classList.Append(ast); break; } } ReportError(JSError.OnlyClassesAllowed, ast.context.Clone(), true); SkipTokensAndThrow(); break; case JSToken.Identifier: bool bAssign, canBeAttribute = true; ast = ParseUnaryExpression(out bAssign, ref canBeAttribute, false); if (canBeAttribute){ bool parsed; ast = ParseAttributes(ast, true, false, out parsed); if (parsed){ if (ast is Class){ classList.Append(ast); break; } } } ReportError(JSError.OnlyClassesAllowed, ast.context.Clone(), true); SkipTokensAndThrow(); break; case JSToken.EndOfFile: EOFError(JSError.ErrEOF); throw new EndOfFile(); // abort parsing, get back to the main parse routine case JSToken.Semicolon: // ignore any spurious semicolon GetNextToken(); break; case JSToken.Import: // handle common error of using import in package ReportError(JSError.InvalidImport, true); try{ ParseImportStatement(); }catch(RecoveryTokenException){ } break; case JSToken.Package: // handle common error of using package in package Context nestedPackageContext = this.currentToken.Clone(); AST statement = ParsePackage(nestedPackageContext); if (statement is Package) ReportError(JSError.PackageInWrongContext, nestedPackageContext, true); break; default: ReportError(JSError.OnlyClassesAllowed, (ast != null) ? ast.context.Clone() : CurrentPositionContext(), true); SkipTokensAndThrow(); break; } }catch(RecoveryTokenException exc){ if (exc._partiallyComputedNode != null && exc._partiallyComputedNode is Class){ classList.Append((Class)exc._partiallyComputedNode); exc._partiallyComputedNode = null; } if (IndexOfToken(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet, exc) == -1) throw exc; } } }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){ ReportError(JSError.NoRightCurly, CurrentPositionContext()); exc._partiallyComputedNode = new Package(name, qualid, classList, packageContext); throw exc; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_PackageBodyNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } GetNextToken(); return new Package(name, qualid, classList, packageContext); }finally{ Globals.ScopeStack.Pop(); } }
internal override AST PartiallyEvaluate(){ AST id = this.identifier = (Lookup)this.identifier.PartiallyEvaluateAsReference(); if (this.type != null) this.field.type = this.type = (TypeExpression)this.type.PartiallyEvaluate(); else if (this.initializer == null && !(this.field is JSLocalField) && this.field.value is Missing){ id.context.HandleError(JSError.VariableLeftUninitialized); this.field.type = this.type = new TypeExpression(new ConstantWrapper(Typeob.Object, id.context)); } if (this.initializer != null){ if (this.field.IsStatic){ ScriptObject scope = this.Engine.ScriptObjectStackTop(); ClassScope cscope = null; while (scope != null && (cscope = scope as ClassScope) == null) scope = scope.GetParent(); if (cscope != null) cscope.inStaticInitializerCode = true; this.initializer = this.initializer.PartiallyEvaluate(); if (cscope != null) cscope.inStaticInitializerCode = false; }else this.initializer = this.initializer.PartiallyEvaluate(); id.SetPartialValue(this.initializer); } // deal with custom attributes if (this.field != null && this.field.customAttributes != null) this.field.customAttributes.PartiallyEvaluate(); return this; }
//--------------------------------------------------------------------------------------- // ParseAttributes // // Package : // Attributes 'package' QualifiedIdentifier '{' ClassList '}' // AttributesStart 'package' QualifiedIdentifier '{' ClassList '}' // // Class : // Attributes 'class' Identifier ['extends' QualifiedIdentifier] '{' ClassBody '}' // AttributesStart 'class' Identifier ['extends' QualifiedIdentifier] '{' ClassBody '}' // // FunctionDeclaration : // Attributes 'function' Identifier '(' [FormalParameterList] ')' [':' TypeExpression] '{' FunctionBody '}' // AttributesStart 'function' Identifier '(' [FormalParameterList] ')' [':' TypeExpression] '{' FunctionBody '}' // // VariableStatement : // Attributes 'var' VariableDeclarationList // AttributesStart 'var' VariableDeclarationList // // Attributes : // AttributesStart AttributesNext | // Modifier [AttributeNext] // // AttributesStart : // QualifiedIdentifier /no LineTerminator here/ | // QualifiedIdentifier Arguments /no LineTerminator here/ // // AttributesNext : // QualifiedIdentifier [AttributesNext] | // QualifiedIdentifier Arguments [AttributesNext] | // Modifier [AttributesNext] // // Modifier : // 'private' | // 'public' | // 'protected' | // 'internal' | // 'package' | //This is going away // 'static' | // 'abstract' // // // Parse the list of attributes and the statement those attributes refer to. // It comes back with one of the following: package, class, function, variable declaration. // When in error it may return other AST constructs depending on the context. // The input is a possible attribute in the form of 'QualifiedIdentifier' or a sequence // 'QualifiedIdentifier Arguments' or null when the first attribute was a Modifier. // The whole sequence may be an error in the first place, so we want to keep // things such that we can always parse the supposed list of attributes as an ast list //--------------------------------------------------------------------------------------- AST ParseAttributes(AST statement, bool unambiguousContext, bool isInsideClass, out bool parsedOK){ // used later to verify whether anything at all has been processed AST inputAST = statement; // keep two list of errors. One holds the 'missing ;' errors that would result in the token // stream being parsed as a list of expressions, the other is the list of attributes errors // that would result from the token stream being parsed as a list of attributes. We need both because // we don't know until the end which is which ArrayList semicolonErrors = new ArrayList(); // keep track of the modifiers context in case they'll have to be parsed as identifiers, we give the warning out ArrayList modifiersAsIdentifier = new ArrayList(); // this list has two elements for each error, the first (even position - 0 based) is the error type // the second is the context ArrayList attributesErrors = new ArrayList(); // keep the last ast node parsed. Used if we have to "revert" to the expression list production. // We just return the last ast processed, after all is an error condition AST lastAST = null; // keep the list of attributes ArrayList attributes = new ArrayList(); // hold the context for the 'abstract' keyword and it is used as a flag for its presence Context abstractContext = null; // hold the context for the 'static' keyword and it is used as a flag for its presence Context staticContext = null; // hold the context for the 'final' keyword and it is used as a flag for its presence Context finalContext = null; // keep the number of consecutive token no separated by end of line. Once that number // reaches 2 the token stream is parsed *only* as a sequence of attributes int TokenCountNoEOL = 0; if (unambiguousContext) TokenCountNoEOL = 2; FieldAttributes visibilitySpec = (FieldAttributes)0, currVis = (FieldAttributes)0; Context statementContext = null; // null when coming from a visibility modifier if (statement != null){ lastAST = statement; attributes.Add(statement); semicolonErrors.Add(CurrentPositionContext()); statementContext = statement.context.Clone(); TokenCountNoEOL = 1; }else{ statementContext = this.currentToken.Clone(); } parsedOK = true; while (true){ JSToken attributeToken = JSToken.None; switch (this.currentToken.token){ case JSToken.Public: case JSToken.Static: case JSToken.Private: case JSToken.Protected: case JSToken.Abstract: case JSToken.Final: case JSToken.Internal: attributeToken = this.currentToken.token; goto case JSToken.Identifier; case JSToken.Var: case JSToken.Const: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); if (abstractContext != null) ReportError(JSError.IllegalVisibility, abstractContext, true); if (finalContext != null) ReportError(JSError.IllegalVisibility, finalContext, true); statementContext.UpdateWith(this.currentToken); return ParseVariableStatement(visibilitySpec, FromASTListToCustomAttributeList(attributes), this.currentToken.token); case JSToken.Function: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); statementContext.UpdateWith(this.currentToken); if (staticContext != null) if (abstractContext != null){ staticContext.HandleError(JSError.AbstractCannotBeStatic); staticContext = null; }else if (finalContext != null){ finalContext.HandleError(JSError.StaticIsAlreadyFinal); finalContext = null; } if (abstractContext != null){ if (finalContext != null){ finalContext.HandleError(JSError.FinalPrecludesAbstract); finalContext = null; } if (currVis == FieldAttributes.Private){ abstractContext.HandleError(JSError.AbstractCannotBePrivate); currVis = FieldAttributes.Family; } } return ParseFunction(visibilitySpec, false, statementContext, isInsideClass, abstractContext != null, finalContext != null, false, FromASTListToCustomAttributeList(attributes)); case JSToken.Interface: if (abstractContext != null){ ReportError(JSError.IllegalVisibility, abstractContext, true); abstractContext = null; } if (finalContext != null){ ReportError(JSError.IllegalVisibility, finalContext, true); finalContext = null; } if (staticContext != null){ ReportError(JSError.IllegalVisibility, staticContext, true); staticContext = null; } goto case JSToken.Class; case JSToken.Class: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); statementContext.UpdateWith(this.currentToken); if (finalContext != null && abstractContext != null) finalContext.HandleError(JSError.FinalPrecludesAbstract); return ParseClass(visibilitySpec, staticContext != null, statementContext, abstractContext != null, finalContext != null, FromASTListToCustomAttributeList(attributes)); case JSToken.Enum: for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1], true); statementContext.UpdateWith(this.currentToken); if (abstractContext != null) ReportError(JSError.IllegalVisibility, abstractContext, true); if (finalContext != null) ReportError(JSError.IllegalVisibility, finalContext, true); if (staticContext != null) ReportError(JSError.IllegalVisibility, staticContext, true); return ParseEnum(visibilitySpec, statementContext, FromASTListToCustomAttributeList(attributes)); case JSToken.Void: case JSToken.Boolean: case JSToken.Byte: case JSToken.Char: case JSToken.Double: case JSToken.Float: case JSToken.Int: case JSToken.Long: case JSToken.Short: { // The user has some sequence like "public int foo()", which // is probably a C-style function declaration. Save that away, // keep parsing and see if this ends in what looks like a function // or variable declaration. parsedOK = false; lastAST = new Lookup(this.currentToken); attributeToken = JSToken.None; attributes.Add(lastAST); GetNextToken(); goto continueLoop; } case JSToken.Identifier: { bool bAssign, canBeAttribute = true; statement = ParseUnaryExpression(out bAssign, ref canBeAttribute, false, attributeToken == JSToken.None); lastAST = statement; if (attributeToken != JSToken.None){ if (statement is Lookup) break; else{ if (TokenCountNoEOL != 2) modifiersAsIdentifier.Add(this.currentToken.Clone()); } } attributeToken = JSToken.None; if (canBeAttribute){ attributes.Add(statement); goto continueLoop; }else goto default; } // the following cases are somewhat interesting because they can be determined by a user missing // the keyword 'var' or 'function', as, for instance, when coming from C/C++/C# code default: parsedOK = false; if (TokenCountNoEOL != 2){ if (inputAST != statement || statement == null){ Debug.Assert(lastAST != null); // only return the last statement statement = lastAST; // output the semicolon errors for (int i = 0, n = modifiersAsIdentifier.Count; i < n; i++) ForceReportInfo((Context)modifiersAsIdentifier[i], JSError.KeywordUsedAsIdentifier); for (int i = 0, n = semicolonErrors.Count; i < n; i++) if (!this.currentToken.Equals((Context)semicolonErrors[i])) ReportError(JSError.NoSemicolon, (Context)semicolonErrors[i], true); } return statement; }else{ if (attributes.Count > 0){ // check for possible common mistakes AST ast = (AST)attributes[attributes.Count - 1]; if (ast is Lookup){ if (JSToken.Semicolon == this.currentToken.token || JSToken.Colon == this.currentToken.token){ ReportError(JSError.BadVariableDeclaration, ast.context.Clone()); SkipTokensAndThrow(); } }else if (ast is Call && ((Call)ast).CanBeFunctionDeclaration()){ if (JSToken.Colon == this.currentToken.token || JSToken.LeftCurly == this.currentToken.token){ ReportError(JSError.BadFunctionDeclaration, ast.context.Clone(), true); if (JSToken.Colon == this.currentToken.token){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try{ SkipTokensAndThrow(); }catch(RecoveryTokenException){ }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } } this.errorToken = null; if (JSToken.LeftCurly == this.currentToken.token){ FunctionScope fscope = new FunctionScope(Globals.ScopeStack.Peek(), isInsideClass); Globals.ScopeStack.Push(fscope); try{ ParseBlock(); }finally{ Globals.ScopeStack.Pop(); } SkipTokensAndThrow(); } } else ReportError(JSError.SyntaxError, ast.context.Clone()); SkipTokensAndThrow(); } } if (JSToken.LeftCurly == this.currentToken.token){ if (isInsideClass){ // parse it like a static initializer // flush all the possible attribute errors for (int i = 0, n = attributesErrors.Count; i < n; i += 2) ReportError((JSError)attributesErrors[i], (Context)attributesErrors[i + 1]); if (staticContext == null) ReportError(JSError.StaticMissingInStaticInit, CurrentPositionContext()); String className = ((ClassScope)Globals.ScopeStack.Peek()).name; bool reportNoIdentifier = true; foreach (Object attr in attributes){ reportNoIdentifier = false; if (staticContext != null && attr is Lookup && attr.ToString() == className && ((Lookup)attr).context.StartColumn > staticContext.StartColumn) continue; ReportError(JSError.SyntaxError, ((AST)attr).context); } if (reportNoIdentifier) ReportError(JSError.NoIdentifier, CurrentPositionContext()); this.errorToken = null; // we want to go to next token regardless of whether or not we had an error // return a static initializer parsedOK = true; return ParseStaticInitializer(statementContext); } } //mark them all as errors ReportError(JSError.MissingConstructForAttributes, statementContext.CombineWith(this.currentToken)); } SkipTokensAndThrow(); break; } switch (attributeToken){ case JSToken.Public: currVis = FieldAttributes.Public; break; case JSToken.Static: if (isInsideClass){ currVis = FieldAttributes.Static; if (staticContext != null){ attributesErrors.Add(JSError.SyntaxError); attributesErrors.Add(statement.context.Clone()); }else staticContext = statement.context.Clone(); }else{ attributesErrors.Add(JSError.NotInsideClass); attributesErrors.Add(statement.context.Clone()); } break; case JSToken.Private: if (isInsideClass) currVis = FieldAttributes.Private; else{ attributesErrors.Add(JSError.NotInsideClass); attributesErrors.Add(statement.context.Clone()); } break; case JSToken.Protected: if (isInsideClass){ currVis = FieldAttributes.Family; }else{ attributesErrors.Add(JSError.NotInsideClass); attributesErrors.Add(statement.context.Clone()); } break; case JSToken.Abstract: if (abstractContext != null){ attributesErrors.Add(JSError.SyntaxError); attributesErrors.Add(statement.context.Clone()); }else abstractContext = statement.context.Clone(); goto continueLoop; case JSToken.Final: if (finalContext != null){ attributesErrors.Add(JSError.SyntaxError); attributesErrors.Add(statement.context.Clone()); }else finalContext = statement.context.Clone(); goto continueLoop; case JSToken.Internal: currVis = FieldAttributes.Assembly; break; default: break; } // come here only after a visibility Modifer if ((visibilitySpec & FieldAttributes.FieldAccessMask) == currVis && currVis != (FieldAttributes)0){ attributesErrors.Add(JSError.DupVisibility); attributesErrors.Add(statement.context.Clone()); }else if ((visibilitySpec & FieldAttributes.FieldAccessMask) > (FieldAttributes)0 && (currVis & FieldAttributes.FieldAccessMask) > (FieldAttributes)0){ if ((currVis == FieldAttributes.Family && (visibilitySpec & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly) || (currVis == FieldAttributes.Assembly && (visibilitySpec & FieldAttributes.FieldAccessMask) == FieldAttributes.Family)){ visibilitySpec &= ~FieldAttributes.FieldAccessMask; visibilitySpec |= FieldAttributes.FamORAssem; }else{ attributesErrors.Add(JSError.IncompatibleVisibility); attributesErrors.Add(statement.context.Clone()); } }else{ visibilitySpec |= currVis; statementContext.UpdateWith(statement.context); } continueLoop: if (TokenCountNoEOL != 2){ if (this.scanner.GotEndOfLine()){ TokenCountNoEOL = 0; }else{ TokenCountNoEOL++; semicolonErrors.Add(this.currentToken.Clone()); } } } }
private AST ParseFunction(FieldAttributes visibilitySpec, bool inExpression, Context fncCtx, bool isMethod, bool isAbstract, bool isFinal, bool isInterface, CustomAttributeList customAttributes, Call function) { AST ast2; if (this.demandFullTrustOnFunctionCreation) { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); } IdentifierLiteral id = null; AST rootObject = null; ArrayList parameters = null; TypeExpression expression = null; Block body = null; bool isGetter = false; bool isSetter = false; if (function == null) { this.GetNextToken(); if (isMethod) { if (JSToken.Get == this.currentToken.token) { isGetter = true; this.GetNextToken(); } else if (JSToken.Set == this.currentToken.token) { isSetter = true; this.GetNextToken(); } } if (JSToken.Identifier == this.currentToken.token) { id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); if (JSToken.AccessField == this.currentToken.token) { if (isInterface) { this.ReportError(JSError.SyntaxError, true); } this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { rootObject = new Lookup(id.context); id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); while (JSToken.AccessField == this.currentToken.token) { this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { rootObject = new Member(rootObject.context.CombineWith(this.currentToken), rootObject, new ConstantWrapper(id.ToString(), id.context)); id = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); this.GetNextToken(); } else { this.ReportError(JSError.NoIdentifier, true); } } } else { this.ReportError(JSError.NoIdentifier, true); } } } else { string identifier = JSKeyword.CanBeIdentifier(this.currentToken.token); if (identifier != null) { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier, isMethod); id = new IdentifierLiteral(identifier, this.currentToken.Clone()); this.GetNextToken(); } else { if (!inExpression) { identifier = this.currentToken.GetCode(); this.ReportError(JSError.NoIdentifier, true); this.GetNextToken(); } else { identifier = ""; } id = new IdentifierLiteral(identifier, this.CurrentPositionContext()); } } } else { id = function.GetName(); } ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); FunctionScope item = new FunctionScope(this.Globals.ScopeStack.Peek(), isMethod); this.Globals.ScopeStack.Push(item); try { parameters = new ArrayList(); Context context = null; if (function == null) { if (JSToken.LeftParen != this.currentToken.token) { this.ReportError(JSError.NoLeftParen); } this.GetNextToken(); while (JSToken.RightParen != this.currentToken.token) { if (context != null) { this.ReportError(JSError.ParamListNotLast, context, true); context = null; } string str2 = null; TypeExpression type = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); try { try { if (JSToken.ParamArray == this.currentToken.token) { context = this.currentToken.Clone(); this.GetNextToken(); } if ((JSToken.Identifier != this.currentToken.token) && ((str2 = JSKeyword.CanBeIdentifier(this.currentToken.token)) == null)) { if (JSToken.LeftCurly == this.currentToken.token) { this.ReportError(JSError.NoRightParen); break; } if (JSToken.Comma == this.currentToken.token) { this.ReportError(JSError.SyntaxError, true); } else { this.ReportError(JSError.SyntaxError, true); this.SkipTokensAndThrow(); } } else { if (str2 == null) { str2 = this.scanner.GetIdentifier(); } else { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier); } Context context2 = this.currentToken.Clone(); this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { type = this.ParseTypeExpression(); if (type != null) { context2.UpdateWith(type.context); } } CustomAttributeList list3 = null; if (context != null) { list3 = new CustomAttributeList(context); list3.Append(new Microsoft.JScript.CustomAttribute(context, new Lookup("...", context), new ASTList(null))); } parameters.Add(new ParameterDeclaration(context2, str2, type, list3)); } if (JSToken.RightParen == this.currentToken.token) { break; } if (JSToken.Comma != this.currentToken.token) { if (JSToken.LeftCurly == this.currentToken.token) { this.ReportError(JSError.NoRightParen); break; } if ((JSToken.Identifier == this.currentToken.token) && (type == null)) { this.ReportError(JSError.NoCommaOrTypeDefinitionError); } else { this.ReportError(JSError.NoComma); } } this.GetNextToken(); } catch (RecoveryTokenException exception) { if (this.IndexOfToken(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet, exception) == -1) { throw exception; } } continue; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_FunctionDeclNoSkipTokenSet); } } fncCtx.UpdateWith(this.currentToken); if (isGetter && (parameters.Count != 0)) { this.ReportError(JSError.BadPropertyDeclaration, true); isGetter = false; } else if (isSetter && (parameters.Count != 1)) { this.ReportError(JSError.BadPropertyDeclaration, true); isSetter = false; } this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { if (isSetter) { this.ReportError(JSError.SyntaxError); } this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); try { expression = this.ParseTypeExpression(); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_StartBlockNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = null; throw exception2; } if (exception2._partiallyComputedNode != null) { expression = (TypeExpression) exception2._partiallyComputedNode; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartBlockNoSkipTokenSet); } if (isSetter) { expression = null; } } } else { function.GetParameters(parameters); } if ((JSToken.LeftCurly != this.currentToken.token) && (isAbstract || (isMethod && this.GuessIfAbstract()))) { if (!isAbstract) { isAbstract = true; this.ReportError(JSError.ShouldBeAbstract, fncCtx, true); } body = new Block(this.currentToken.Clone()); } else { if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly, true); } else if (isAbstract) { this.ReportError(JSError.AbstractWithBody, fncCtx, true); } this.blockType.Add(BlockType.Block); this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet); this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); try { body = new Block(this.currentToken.Clone()); this.GetNextToken(); while (JSToken.RightCurly != this.currentToken.token) { try { body.Append(this.ParseStatement()); continue; } catch (RecoveryTokenException exception3) { if (exception3._partiallyComputedNode != null) { body.Append(exception3._partiallyComputedNode); } if (this.IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exception3) == -1) { throw exception3; } continue; } } body.context.UpdateWith(this.currentToken); fncCtx.UpdateWith(this.currentToken); } catch (RecoveryTokenException exception4) { if (this.IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exception4) == -1) { this.Globals.ScopeStack.Pop(); try { ParameterDeclaration[] declarationArray = new ParameterDeclaration[parameters.Count]; parameters.CopyTo(declarationArray); if (inExpression) { exception4._partiallyComputedNode = new FunctionExpression(fncCtx, id, declarationArray, expression, body, item, visibilitySpec); } else { exception4._partiallyComputedNode = new FunctionDeclaration(fncCtx, rootObject, id, declarationArray, expression, body, item, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); } if (customAttributes != null) { customAttributes.SetTarget(exception4._partiallyComputedNode); } } finally { this.Globals.ScopeStack.Push(item); } throw exception4; } } finally { this.blockType.RemoveAt(this.blockType.Count - 1); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet); this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet); } this.GetNextToken(); } } finally { this.blockType = blockType; this.labelTable = labelTable; this.Globals.ScopeStack.Pop(); } ParameterDeclaration[] array = new ParameterDeclaration[parameters.Count]; parameters.CopyTo(array); if (inExpression) { ast2 = new FunctionExpression(fncCtx, id, array, expression, body, item, visibilitySpec); } else { ast2 = new FunctionDeclaration(fncCtx, rootObject, id, array, expression, body, item, visibilitySpec, isMethod, isGetter, isSetter, isAbstract, isFinal, customAttributes); } if (customAttributes != null) { customAttributes.SetTarget(ast2); } return ast2; }
internal override AST PartiallyEvaluate() { AST ast = this.identifier = (Lookup) this.identifier.PartiallyEvaluateAsReference(); if (this.type != null) { this.field.type = this.type = (TypeExpression) this.type.PartiallyEvaluate(); } else if (((this.initializer == null) && !(this.field is JSLocalField)) && (this.field.value is Microsoft.JScript.Missing)) { ast.context.HandleError(JSError.VariableLeftUninitialized); this.field.type = this.type = new TypeExpression(new ConstantWrapper(Typeob.Object, ast.context)); } if (this.initializer != null) { if (this.field.IsStatic) { ScriptObject parent = base.Engine.ScriptObjectStackTop(); ClassScope scope = null; while ((parent != null) && ((scope = parent as ClassScope) == null)) { parent = parent.GetParent(); } if (scope != null) { scope.inStaticInitializerCode = true; } this.initializer = this.initializer.PartiallyEvaluate(); if (scope != null) { scope.inStaticInitializerCode = false; } } else { this.initializer = this.initializer.PartiallyEvaluate(); } ast.SetPartialValue(this.initializer); } if ((this.field != null) && (this.field.customAttributes != null)) { this.field.customAttributes.PartiallyEvaluate(); } return this; }
private AST ParseIdentifierInitializer(JSToken inToken, FieldAttributes visibility, CustomAttributeList customAttributes, JSToken kind) { Lookup identifier = null; TypeExpression type = null; AST initializer = null; RecoveryTokenException exception = null; this.GetNextToken(); if (JSToken.Identifier != this.currentToken.token) { string name = JSKeyword.CanBeIdentifier(this.currentToken.token); if (name != null) { this.ForceReportInfo(JSError.KeywordUsedAsIdentifier); identifier = new Lookup(name, this.currentToken.Clone()); } else { this.ReportError(JSError.NoIdentifier); identifier = new Lookup("#_Missing Identifier_#" + s_cDummyName++, this.CurrentPositionContext()); } } else { identifier = new Lookup(this.scanner.GetIdentifier(), this.currentToken.Clone()); } this.GetNextToken(); Context context = identifier.context.Clone(); this.noSkipTokenSet.Add(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet); try { if (JSToken.Colon == this.currentToken.token) { try { type = this.ParseTypeExpression(); } catch (RecoveryTokenException exception2) { type = (TypeExpression) exception2._partiallyComputedNode; throw exception2; } finally { if (type != null) { context.UpdateWith(type.context); } } } if ((JSToken.Assign == this.currentToken.token) || (JSToken.Equal == this.currentToken.token)) { if (JSToken.Equal == this.currentToken.token) { this.ReportError(JSError.NoEqual, true); } this.GetNextToken(); try { initializer = this.ParseExpression(true, inToken); } catch (RecoveryTokenException exception3) { initializer = exception3._partiallyComputedNode; throw exception3; } finally { if (initializer != null) { context.UpdateWith(initializer.context); } } } } catch (RecoveryTokenException exception4) { if (this.IndexOfToken(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet, exception4) == -1) { exception = exception4; } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet); } AST target = null; if (JSToken.Var == kind) { target = new VariableDeclaration(context, identifier, type, initializer, visibility, customAttributes); } else { if (initializer == null) { this.ForceReportInfo(JSError.NoEqual); } target = new Constant(context, identifier, type, initializer, visibility, customAttributes); } if (customAttributes != null) { customAttributes.SetTarget(target); } if (exception != null) { exception._partiallyComputedNode = target; throw exception; } return target; }
internal VariableDeclaration(Context context, Lookup identifier, TypeExpression type, AST initializer, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context) { if (initializer != null) { base.context.UpdateWith(initializer.context); } else if (type != null) { base.context.UpdateWith(type.context); } this.identifier = identifier; this.type = type; this.initializer = initializer; ScriptObject parent = base.Globals.ScopeStack.Peek(); while (parent is WithObject) { parent = parent.GetParent(); } string name = this.identifier.ToString(); if (parent is ClassScope) { if (name == ((ClassScope) parent).name) { identifier.context.HandleError(JSError.CannotUseNameOfClass); name = name + " var"; } } else if (attributes != FieldAttributes.PrivateScope) { base.context.HandleError(JSError.NotInsideClass); attributes = FieldAttributes.Public; } else { attributes |= FieldAttributes.Public; } FieldInfo localField = ((IActivationObject) parent).GetLocalField(name); if (localField != null) { if ((localField.IsLiteral || (parent is ClassScope)) || (type != null)) { identifier.context.HandleError(JSError.DuplicateName, true); } this.type = (TypeExpression) (type = null); } if (parent is ActivationObject) { if ((localField == null) || (localField is JSVariableField)) { this.field = ((ActivationObject) parent).AddFieldOrUseExistingField(this.identifier.ToString(), Microsoft.JScript.Missing.Value, attributes); } else { this.field = ((ActivationObject) parent).AddNewField(this.identifier.ToString(), null, attributes); } } else { this.field = ((StackFrame) parent).AddNewField(this.identifier.ToString(), null, attributes | FieldAttributes.Static); } this.field.type = type; this.field.customAttributes = customAttributes; this.field.originalContext = context; if (this.field is JSLocalField) { ((JSLocalField) this.field).debugOn = this.identifier.context.document.debugOn; } this.completion = new Completion(); }
private AST ParseEnumMember() { AST ast = null; Lookup identifier = null; AST ast2 = null; JSToken token = this.currentToken.token; if (token == JSToken.Var) { this.ReportError(JSError.NoVarInEnum, true); this.GetNextToken(); return this.ParseEnumMember(); } if (token != JSToken.Semicolon) { if (token == JSToken.Identifier) { identifier = new Lookup(this.currentToken.Clone()); Context context = this.currentToken.Clone(); this.GetNextToken(); if (JSToken.Assign == this.currentToken.token) { this.GetNextToken(); ast2 = this.ParseExpression(true); } if (JSToken.Comma == this.currentToken.token) { this.GetNextToken(); } else if (JSToken.RightCurly != this.currentToken.token) { this.ReportError(JSError.NoComma, true); } return new Constant(context, identifier, null, ast2, FieldAttributes.Public, null); } this.ReportError(JSError.SyntaxError, true); this.SkipTokensAndThrow(); return ast; } this.GetNextToken(); return this.ParseEnumMember(); }