//--------------------------------------------------------------------------------------- // 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; }
//--------------------------------------------------------------------------------------- // ParseEnum // // Enum : // 'enum' identifier [':' baseType] EnumBody (in the guise of ClassBody with a param) // //--------------------------------------------------------------------------------------- private AST ParseEnum(FieldAttributes visibilitySpec, Context enumCtx, CustomAttributeList customAttributes){ IdentifierLiteral name = null; AST baseId = null; TypeExpression baseType = null; Block body = null; GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); }else{ ReportError(JSError.NoIdentifier); if (JSToken.Colon != this.currentToken.token && JSToken.LeftCurly != this.currentToken.token) SkipTokensAndThrow(); // what the is this? name = new IdentifierLiteral("##Missing Enum Name##" + s_cDummyName++, CurrentPositionContext()); } GetNextToken(); if (JSToken.Colon == this.currentToken.token){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_EnumBaseTypeNoSkipTokenSet); try{ baseId = ParseQualifiedIdentifier(JSError.NeedType); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ baseId = exc._partiallyComputedNode; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_EnumBaseTypeNoSkipTokenSet); } } if (baseId != null) baseType = new TypeExpression(baseId); if (JSToken.LeftCurly != this.currentToken.token) ReportError(JSError.NoLeftCurly); // 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); Globals.ScopeStack.Push(new ClassScope(name, ((IActivationObject)Globals.ScopeStack.Peek()).GetGlobalScope())); //Give declarations a place to go while building AST try{ body = ParseClassBody(true, false); enumCtx.UpdateWith(body.context); EnumDeclaration result = new EnumDeclaration(enumCtx, name, baseType, body, visibilitySpec, customAttributes); if (customAttributes != null) customAttributes.SetTarget(result); return result; }catch(RecoveryTokenException exc){ enumCtx.UpdateWith(exc._partiallyComputedNode.context); exc._partiallyComputedNode = new EnumDeclaration(enumCtx, name, baseType, (Block)exc._partiallyComputedNode, visibilitySpec, customAttributes); if (customAttributes != null) customAttributes.SetTarget(exc._partiallyComputedNode); throw exc; }finally{ Globals.ScopeStack.Pop(); this.blockType = blockType; this.labelTable = labelTable; } }
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; }
//--------------------------------------------------------------------------------------- // ParseClass // // Class : // 'class' identifier OptionalExtends ClassBody // // Extends : // 'extends' QualifiedIdentifier // //--------------------------------------------------------------------------------------- private AST ParseClass(FieldAttributes visibilitySpec, bool isStatic, Context classCtx, bool isAbstract, bool isFinal, CustomAttributeList customAttributes){ AST name = null; AST baseId = null; TypeExpression baseType = null; Block body = null; ArrayList interfaces = new ArrayList(); bool isInterface = JSToken.Interface == this.currentToken.token; GetNextToken(); if (JSToken.Identifier == this.currentToken.token){ name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); }else{ ReportError(JSError.NoIdentifier); if (JSToken.Extends != this.currentToken.token && JSToken.Implements != this.currentToken.token && JSToken.LeftCurly != this.currentToken.token) SkipTokensAndThrow(); // what the is this? name = new IdentifierLiteral("##Missing Class Name##" + s_cDummyName++, CurrentPositionContext()); } GetNextToken(); if (JSToken.Extends == this.currentToken.token || JSToken.Implements == this.currentToken.token){ if (isInterface && JSToken.Extends == this.currentToken.token) this.currentToken.token = JSToken.Implements; if (JSToken.Extends == this.currentToken.token){ this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); try{ baseId = ParseQualifiedIdentifier(JSError.NeedType); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ baseId = exc._partiallyComputedNode; } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); } } if (JSToken.Implements == this.currentToken.token){ do{ AST typeId = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); try{ typeId = ParseQualifiedIdentifier(JSError.NeedType); interfaces.Add(new TypeExpression(typeId)); }catch(RecoveryTokenException exc){ if (IndexOfToken(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet, exc) == -1){ exc._partiallyComputedNode = null; throw exc; }else{ if (exc._partiallyComputedNode != null) interfaces.Add(new TypeExpression(exc._partiallyComputedNode)); } }finally{ this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); } }while (JSToken.Comma == this.currentToken.token); } } if (baseId != null) baseType = new TypeExpression(baseId); if (JSToken.LeftCurly != this.currentToken.token){ ReportError(JSError.NoLeftCurly); } // 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); Globals.ScopeStack.Push(new ClassScope(name, ((IActivationObject)Globals.ScopeStack.Peek()).GetGlobalScope())); //Give declarations a place to go while building AST TypeExpression[] ifaces; try{ body = ParseClassBody(false, isInterface); classCtx.UpdateWith(body.context); ifaces = new TypeExpression[interfaces.Count]; interfaces.CopyTo(ifaces); Class result = new Class(classCtx, name, baseType, ifaces, body, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) customAttributes.SetTarget(result); return result; }catch(RecoveryTokenException exc){ classCtx.UpdateWith(exc._partiallyComputedNode.context); ifaces = new TypeExpression[interfaces.Count]; interfaces.CopyTo(ifaces); exc._partiallyComputedNode = new Class(classCtx, name, baseType, ifaces, (Block)exc._partiallyComputedNode, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) customAttributes.SetTarget(exc._partiallyComputedNode); throw exc; }finally{ Globals.ScopeStack.Pop(); this.blockType = blockType; this.labelTable = labelTable; } }
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; }
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; }
private AST ParseEnum(FieldAttributes visibilitySpec, Context enumCtx, CustomAttributeList customAttributes) { IdentifierLiteral name = null; AST ast = null; TypeExpression baseType = null; Block body = null; AST ast2; this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); } else { this.ReportError(JSError.NoIdentifier); if ((JSToken.Colon != this.currentToken.token) && (JSToken.LeftCurly != this.currentToken.token)) { this.SkipTokensAndThrow(); } name = new IdentifierLiteral("##Missing Enum Name##" + s_cDummyName++, this.CurrentPositionContext()); } this.GetNextToken(); if (JSToken.Colon == this.currentToken.token) { this.noSkipTokenSet.Add(NoSkipTokenSet.s_EnumBaseTypeNoSkipTokenSet); try { ast = this.ParseQualifiedIdentifier(JSError.NeedType); } catch (RecoveryTokenException exception) { if (this.IndexOfToken(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet, exception) == -1) { exception._partiallyComputedNode = null; throw exception; } ast = exception._partiallyComputedNode; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_EnumBaseTypeNoSkipTokenSet); } } if (ast != null) { baseType = new TypeExpression(ast); } if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); this.Globals.ScopeStack.Push(new ClassScope(name, ((IActivationObject) this.Globals.ScopeStack.Peek()).GetGlobalScope())); try { body = this.ParseClassBody(true, false); enumCtx.UpdateWith(body.context); EnumDeclaration target = new EnumDeclaration(enumCtx, name, baseType, body, visibilitySpec, customAttributes); if (customAttributes != null) { customAttributes.SetTarget(target); } ast2 = target; } catch (RecoveryTokenException exception2) { enumCtx.UpdateWith(exception2._partiallyComputedNode.context); exception2._partiallyComputedNode = new EnumDeclaration(enumCtx, name, baseType, (Block) exception2._partiallyComputedNode, visibilitySpec, customAttributes); if (customAttributes != null) { customAttributes.SetTarget(exception2._partiallyComputedNode); } throw exception2; } finally { this.Globals.ScopeStack.Pop(); this.blockType = blockType; this.labelTable = labelTable; } return ast2; }
private AST ParseClass(FieldAttributes visibilitySpec, bool isStatic, Context classCtx, bool isAbstract, bool isFinal, CustomAttributeList customAttributes) { AST name = null; AST ast2 = null; TypeExpression superTypeExpression = null; Block body = null; TypeExpression[] expressionArray; AST ast4; ArrayList list = new ArrayList(); bool isInterface = JSToken.Interface == this.currentToken.token; this.GetNextToken(); if (JSToken.Identifier == this.currentToken.token) { name = new IdentifierLiteral(this.scanner.GetIdentifier(), this.currentToken.Clone()); } else { this.ReportError(JSError.NoIdentifier); if (((JSToken.Extends != this.currentToken.token) && (JSToken.Implements != this.currentToken.token)) && (JSToken.LeftCurly != this.currentToken.token)) { this.SkipTokensAndThrow(); } name = new IdentifierLiteral("##Missing Class Name##" + s_cDummyName++, this.CurrentPositionContext()); } this.GetNextToken(); if ((JSToken.Extends == this.currentToken.token) || (JSToken.Implements == this.currentToken.token)) { if (isInterface && (JSToken.Extends == this.currentToken.token)) { this.currentToken.token = JSToken.Implements; } if (JSToken.Extends == this.currentToken.token) { this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); try { ast2 = this.ParseQualifiedIdentifier(JSError.NeedType); } catch (RecoveryTokenException exception) { if (this.IndexOfToken(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet, exception) == -1) { exception._partiallyComputedNode = null; throw exception; } ast2 = exception._partiallyComputedNode; } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassExtendsNoSkipTokenSet); } } if (JSToken.Implements == this.currentToken.token) { do { AST expression = null; this.noSkipTokenSet.Add(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); try { expression = this.ParseQualifiedIdentifier(JSError.NeedType); list.Add(new TypeExpression(expression)); } catch (RecoveryTokenException exception2) { if (this.IndexOfToken(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet, exception2) == -1) { exception2._partiallyComputedNode = null; throw exception2; } if (exception2._partiallyComputedNode != null) { list.Add(new TypeExpression(exception2._partiallyComputedNode)); } } finally { this.noSkipTokenSet.Remove(NoSkipTokenSet.s_ClassImplementsNoSkipTokenSet); } } while (JSToken.Comma == this.currentToken.token); } } if (ast2 != null) { superTypeExpression = new TypeExpression(ast2); } if (JSToken.LeftCurly != this.currentToken.token) { this.ReportError(JSError.NoLeftCurly); } ArrayList blockType = this.blockType; this.blockType = new ArrayList(0x10); SimpleHashtable labelTable = this.labelTable; this.labelTable = new SimpleHashtable(0x10); this.Globals.ScopeStack.Push(new ClassScope(name, ((IActivationObject) this.Globals.ScopeStack.Peek()).GetGlobalScope())); try { body = this.ParseClassBody(false, isInterface); classCtx.UpdateWith(body.context); expressionArray = new TypeExpression[list.Count]; list.CopyTo(expressionArray); Class target = new Class(classCtx, name, superTypeExpression, expressionArray, body, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) { customAttributes.SetTarget(target); } ast4 = target; } catch (RecoveryTokenException exception3) { classCtx.UpdateWith(exception3._partiallyComputedNode.context); expressionArray = new TypeExpression[list.Count]; list.CopyTo(expressionArray); exception3._partiallyComputedNode = new Class(classCtx, name, superTypeExpression, expressionArray, (Block) exception3._partiallyComputedNode, visibilitySpec, isAbstract, isFinal, isStatic, isInterface, customAttributes); if (customAttributes != null) { customAttributes.SetTarget(exception3._partiallyComputedNode); } throw exception3; } finally { this.Globals.ScopeStack.Pop(); this.blockType = blockType; this.labelTable = labelTable; } return ast4; }