internal FunctionObject(Type t, string name, string method_name, string[] formal_parameters, JSLocalField[] fields, bool must_save_stack_locals, bool hasArgumentsObject, string text, VsaEngine engine) : base(engine.Globals.globalObject.originalFunction.originalPrototype, name, formal_parameters.Length)
 {
     base.engine = engine;
     this.formal_parameters = formal_parameters;
     this.argumentsSlotNumber = 0;
     this.body = null;
     this.method = TypeReflector.GetTypeReflectorFor(Globals.TypeRefs.ToReferenceContext(t)).GetMethod(method_name, BindingFlags.Public | BindingFlags.Static);
     this.parameterInfos = this.method.GetParameters();
     if (!Microsoft.JScript.CustomAttribute.IsDefined(this.method, typeof(JSFunctionAttribute), false))
     {
         this.isMethod = true;
     }
     else
     {
         JSFunctionAttributeEnum attributeValue = ((JSFunctionAttribute) Microsoft.JScript.CustomAttribute.GetCustomAttributes(this.method, typeof(JSFunctionAttribute), false)[0]).attributeValue;
         this.isExpandoMethod = (attributeValue & JSFunctionAttributeEnum.IsExpandoMethod) != JSFunctionAttributeEnum.None;
     }
     this.funcContext = null;
     this.own_scope = null;
     this.fields = fields;
     this.must_save_stack_locals = must_save_stack_locals;
     this.hasArgumentsObject = hasArgumentsObject;
     this.text = text;
     this.attributes = MethodAttributes.Public;
     this.globals = engine.Globals;
     this.superConstructor = null;
     this.superConstructorCall = null;
     this.enclosing_scope = this.globals.ScopeStack.Peek();
     base.noExpando = false;
     this.clsCompliance = CLSComplianceSpec.NotAttributed;
 }
 internal EnumDeclaration(Context context, IdentifierLiteral id, TypeExpression baseType, Block body, FieldAttributes attributes, CustomAttributeList customAttributes) : base(context, id, new TypeExpression(new ConstantWrapper(Typeob.Enum, null)), new TypeExpression[0], body, attributes, false, false, true, false, customAttributes)
 {
     this.baseType = (baseType != null) ? baseType : new TypeExpression(new ConstantWrapper(Typeob.Int32, null));
     base.needsEngine = false;
     base.attributes &= TypeAttributes.NestedFamORAssem;
     TypeExpression expression = new TypeExpression(new ConstantWrapper(base.classob, base.context));
     AST ast = new ConstantWrapper(-1, null);
     AST ast2 = new ConstantWrapper(1, null);
     JSMemberField[] fields = base.fields;
     for (int i = 0; i < fields.Length; i++)
     {
         FieldInfo info = fields[i];
         JSVariableField field = (JSVariableField) info;
         field.attributeFlags = FieldAttributes.Literal | FieldAttributes.Static | FieldAttributes.Public;
         field.type = expression;
         if (field.value == null)
         {
             field.value = ast = new Plus(ast.context, ast, ast2);
         }
         else
         {
             ast = (AST) field.value;
         }
         field.value = new DeclaredEnumValue(field.value, field.Name, base.classob);
     }
 }
 internal FunctionObject(string name, ParameterDeclaration[] parameter_declarations, TypeExpression return_type_expr, Block body, FunctionScope own_scope, ScriptObject enclosing_scope, Context funcContext, MethodAttributes attributes, CustomAttributeList customAttributes, bool isMethod) : base(body.Globals.globalObject.originalFunction.originalPrototype, name, parameter_declarations.Length)
 {
     this.parameter_declarations = parameter_declarations;
     int length = parameter_declarations.Length;
     this.formal_parameters = new string[length];
     for (int i = 0; i < length; i++)
     {
         this.formal_parameters[i] = parameter_declarations[i].identifier;
     }
     this.argumentsSlotNumber = 0;
     this.return_type_expr = return_type_expr;
     if (this.return_type_expr != null)
     {
         own_scope.AddReturnValueField();
     }
     this.body = body;
     this.method = null;
     this.parameterInfos = null;
     this.funcContext = funcContext;
     this.own_scope = own_scope;
     this.own_scope.owner = this;
     if ((!(enclosing_scope is ActivationObject) || !((ActivationObject) enclosing_scope).fast) && !isMethod)
     {
         this.argumentsSlotNumber = this.own_scope.GetNextSlotNumber();
         JSLocalField field = (JSLocalField) this.own_scope.AddNewField("arguments", null, FieldAttributes.PrivateScope);
         field.type = new TypeExpression(new ConstantWrapper(Typeob.Object, funcContext));
         field.isDefined = true;
         this.hasArgumentsObject = true;
     }
     else
     {
         this.hasArgumentsObject = false;
     }
     this.implementedIface = null;
     this.implementedIfaceMethod = null;
     this.isMethod = isMethod;
     this.isExpandoMethod = (customAttributes != null) && customAttributes.ContainsExpandoAttribute();
     this.isStatic = this.own_scope.isStatic = (attributes & MethodAttributes.Static) != MethodAttributes.PrivateScope;
     this.suppressIL = false;
     this.noVersionSafeAttributeSpecified = true;
     this.fields = this.own_scope.GetLocalFields();
     this.enclosing_scope = enclosing_scope;
     this.must_save_stack_locals = false;
     this.text = null;
     this.mb = null;
     this.cb = null;
     this.attributes = attributes;
     if (!this.isStatic)
     {
         this.attributes |= MethodAttributes.HideBySig;
     }
     this.globals = body.Globals;
     this.superConstructor = null;
     this.superConstructorCall = null;
     this.customAttributes = customAttributes;
     base.noExpando = false;
     this.clsCompliance = CLSComplianceSpec.NotAttributed;
     this.engineLocal = null;
     this.partiallyEvaluated = false;
 }
Exemplo n.º 4
0
 internal StaticInitializer(Context context, Block body, FunctionScope own_scope)
   : base(context) {
   this.func = new FunctionObject(null, new ParameterDeclaration[0], null, body, own_scope, Globals.ScopeStack.Peek(), context, MethodAttributes.Private|MethodAttributes.Static);
   this.func.isMethod = true;
   this.func.hasArgumentsObject = false;
   this.completion = new Completion();
 }
Exemplo n.º 5
0
		internal FunctionExpression (AST parent, string name, 
					     FormalParameterList p,
					     string return_type, Block body, Location location)
			: base (parent, location)
		{
			func_obj = new FunctionObject (name, p, return_type, body, location);
		}
 internal FunctionExpression(Context context, AST id, ParameterDeclaration[] formal_parameters, TypeExpression return_type, Block body, FunctionScope own_scope, FieldAttributes attributes)
   : base(context){
   if (attributes != (FieldAttributes)0){
     this.context.HandleError(JSError.SyntaxError);
     attributes = (FieldAttributes)0;
   }
   ScriptObject enclosingScope = Globals.ScopeStack.Peek();
   this.name = id.ToString();
   if (this.name.Length == 0)
     this.name = "anonymous "+(uniqueNumber++).ToString(CultureInfo.InvariantCulture);
   else
     this.AddNameTo(enclosingScope);
   this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, enclosingScope, this.context, MethodAttributes.Static|MethodAttributes.Public);
 }
Exemplo n.º 7
0
      //---------------------------------------------------------------------------------------
      // JSParser
      //
      // create a parser with a context. The context is the code that has to be compiled.
      // Typically used by the runtime
      //---------------------------------------------------------------------------------------
      public JSParser(Context context){
        this.sourceContext = context;
        this.currentToken = context.Clone();
        this.scanner = new JSScanner(this.currentToken);
        this.noSkipTokenSet = new NoSkipTokenSet();

        this.errorToken = null;
        this.program = null;
        this.blockType = new ArrayList(16);
        this.labelTable = new SimpleHashtable(16);
        this.finallyEscaped = 0;
        this.Globals = context.document.engine.Globals;
        this.Severity = 5;
      }
Exemplo n.º 8
0
 internal Class(Context context, AST id, TypeExpression superTypeExpression, TypeExpression[] interfaces, Block body, 
   FieldAttributes attributes, bool isAbstract, bool isFinal, bool isStatic, bool isInterface, CustomAttributeList customAttributes)
   : base(context) {
   this.name = id.ToString();
   this.superTypeExpression = superTypeExpression;
   this.interfaces = interfaces;
   this.body = body;
   this.enclosingScope = (ScriptObject)Globals.ScopeStack.Peek(1);
   this.attributes = TypeAttributes.Class|TypeAttributes.Serializable;
   this.SetAccessibility(attributes);
   if (isAbstract)
     this.attributes |= TypeAttributes.Abstract;
   this.isAbstract = isAbstract || isInterface;
   this.isAlreadyPartiallyEvaluated = false;
   if (isFinal)
     this.attributes |= TypeAttributes.Sealed;
   if (isInterface)
     this.attributes |= TypeAttributes.Interface | TypeAttributes.Abstract;
   this.isCooked = false;
   this.cookedType = null;
   this.isExpando = false;
   this.isInterface = isInterface;
   this.isStatic = isStatic;
   this.needsEngine = !isInterface;
   this.validOn = (AttributeTargets)0;
   this.allowMultiple = true;
   this.classob = (ClassScope)Globals.ScopeStack.Peek();
   this.classob.name = this.name;
   this.classob.owner = this;
   this.implicitDefaultConstructor = null;
   if (!isInterface && !(this is EnumDeclaration))
     this.SetupConstructors();
   this.EnterNameIntoEnclosingScopeAndGetOwnField(id, isStatic);
   this.fields = this.classob.GetMemberFields();
   this.superClass = null;
   this.superIR = null;
   this.superMembers = null;
   this.firstIndex = null;
   this.fieldInitializer = null;
   this.customAttributes = customAttributes;
   this.clsCompliance = CLSComplianceSpec.NotAttributed;
   this.generateCodeForExpando = false;
   this.expandoItemProp = null;
   this.getHashTableMethod = null;
   this.getItem = null;
   this.setItem = null;
 }
Exemplo n.º 9
0
 internal EnumDeclaration(Context context, IdentifierLiteral id, TypeExpression baseType, Block body, FieldAttributes attributes, CustomAttributeList customAttributes)
   : base(context, id, new TypeExpression(new ConstantWrapper(typeof(Enum), null)), new TypeExpression[0], body, attributes, false, false, true, false, customAttributes){
   this.baseType = baseType != null ? baseType : new TypeExpression(new ConstantWrapper(Typeob.Int32, null));
   this.needsEngine = false;
   this.attributes &= TypeAttributes.VisibilityMask;
   TypeExpression thisType = new TypeExpression(new ConstantWrapper(this.classob, this.context));
   AST currentValue = new ConstantWrapper(-1, null);
   AST one = new ConstantWrapper(1, null);
   foreach (FieldInfo f in this.fields){
     JSVariableField field = (JSVariableField)f;
     field.attributeFlags = FieldAttributes.Public|FieldAttributes.Static|FieldAttributes.Literal;
     field.type = thisType;
     if (field.value == null)
       field.value = currentValue = new Plus(currentValue.context, currentValue, one);
     else
       currentValue = (AST)field.value;
     field.value = new EnumWrapper(field.value, field.Name, this.classob);
   }
 }
Exemplo n.º 10
0
        internal FunctionObject(string name, FormalParameterList p, string ret_type, Block body, Location location)
        {
            this._prototype = ObjectConstructor.Ctr.ConstructObject ();
            //
            // FIXME
            // 1) Must collect the attributes given.
            // 2) Check if they are semantically correct.
            // 3) Assign those values to 'attr'.
            //
            this.attr = MethodAttributes.Public | MethodAttributes.Static;

            this.name = name;
            this.parameters = p;

            this.type_annot = ret_type;
            //
            // FIXME: Must check that return_type it's a valid type,
            // and assign that to 'return_type' field.
            //
            this.return_type = typeof (void);

            this.body = body;
            this.location = location;
        }
 internal ScriptBlock(Context context, Block statement_block) : base(context)
 {
     this.statement_block = statement_block;
     this.own_scope = (GlobalScope) base.Engine.ScriptObjectStackTop();
     this.fields = null;
 }
Exemplo n.º 12
0
      //---------------------------------------------------------------------------------------
      // ParseForStatement
      //
      //  ForStatement :
      //    'for' '(' OptionalExpressionNoIn ';' OptionalExpression ';' OptionalExpression ')'
      //    'for' '(' 'var' VariableDeclarationListNoIn ';' OptionalExpression ';' OptionalExpression ')'
      //    'for' '(' LeftHandSideExpression 'in' Expression')'
      //    'for' '(' 'var' Identifier OptionalInitializerNoIn 'in' Expression')'
      //
      //  OptionalExpressionNoIn :
      //    <empty> |
      //    ExpressionNoIn // same as Expression but does not process 'in' as an operator
      //
      //  OptionalInitializerNoIn :
      //    <empty> |
      //    InitializerNoIn // same as initializer but does not process 'in' as an operator
      //---------------------------------------------------------------------------------------
      private AST ParseForStatement(){
        this.blockType.Add(BlockType.Loop);
        AST forNode = null;
        try{
          Context forCtx = this.currentToken.Clone();
          GetNextToken();
          if (JSToken.LeftParen != this.currentToken.token)
            ReportError(JSError.NoLeftParen);
          GetNextToken();
          bool isForIn = false, recoveryInForIn = false;
          AST lhs = null, initializer = null, condOrColl = null, increment = null;

          try{
            if (JSToken.Var == this.currentToken.token){
              isForIn = true;
              initializer = ParseIdentifierInitializer(JSToken.In, (FieldAttributes)0, null, JSToken.Var);

              // a list of variable initializers is allowed only in a for(;;)
              AST var = null;
              while (JSToken.Comma == this.currentToken.token){
                isForIn = false;
                var = ParseIdentifierInitializer(JSToken.In, (FieldAttributes)0, null, JSToken.Var);
                initializer = new Comma(initializer.context.CombineWith(var.context), initializer, var);
              }

              // if it could still be a for..in, now it's time to get the 'in'
              if (isForIn){
                if (JSToken.In == this.currentToken.token){
                  GetNextToken();
                  condOrColl = ParseExpression();
                }else
                  isForIn = false;
              }
            }else{
              if (JSToken.Semicolon != this.currentToken.token){
                bool isLHS;
                initializer = ParseUnaryExpression(out isLHS, false);
                if (isLHS && JSToken.In == this.currentToken.token){
                  isForIn = true;
                  lhs = initializer;
                  initializer = null;
                  GetNextToken();
                  this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                  try{
                    condOrColl = ParseExpression();
                  }catch(RecoveryTokenException exc){
                    if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
                      exc._partiallyComputedNode = null;
                      throw exc;
                    }else{
                      if (exc._partiallyComputedNode == null)
                        condOrColl = new ConstantWrapper(true, CurrentPositionContext()); // what could we put here?
                      else
                        condOrColl = exc._partiallyComputedNode;
                    }
                    if (exc._token == JSToken.RightParen){
                      GetNextToken();
                      recoveryInForIn = true;
                    }
                  }finally{
                    this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
                  }
                }else
                  initializer = ParseExpression(initializer, false, isLHS, JSToken.In);
              }else
                initializer = new EmptyLiteral(CurrentPositionContext());
          }
          }catch(RecoveryTokenException exc){
            // error is too early abort for
            exc._partiallyComputedNode = null;
            throw exc;
          }

          // at this point we know whether or not is a for..in
          if (isForIn){
            if (!recoveryInForIn){
              if (JSToken.RightParen != this.currentToken.token)
                ReportError(JSError.NoRightParen);
              forCtx.UpdateWith(this.currentToken);
              GetNextToken();
            }
            AST body = null;
            try{
              body = ParseStatement();
            }catch(RecoveryTokenException exc){
              if (exc._partiallyComputedNode == null)
                body = new Block(CurrentPositionContext());
              else
                body = exc._partiallyComputedNode;
              exc._partiallyComputedNode = new ForIn(forCtx, lhs, initializer, condOrColl, body);
              throw exc;
            }
            forNode = new ForIn(forCtx, lhs, initializer, condOrColl, body);
          }else{
            this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
            try{
              if (JSToken.Semicolon != this.currentToken.token){
                ReportError(JSError.NoSemicolon);
                if (JSToken.Colon == this.currentToken.token){
                  this.noSkipTokenSet.Add(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                  try{
                    SkipTokensAndThrow();
                  }catch(RecoveryTokenException exc){
                    if (JSToken.Semicolon == this.currentToken.token)
                      this.errorToken = null;
                    else
                      throw exc;
                  }finally{
                    this.noSkipTokenSet.Remove(NoSkipTokenSet.s_VariableDeclNoSkipTokenSet);
                  }
                }
              }
              GetNextToken();
              if (JSToken.Semicolon != this.currentToken.token){
                condOrColl = ParseExpression();
                if (JSToken.Semicolon != this.currentToken.token)
                  ReportError(JSError.NoSemicolon);
              }else
                condOrColl = new ConstantWrapper(true, CurrentPositionContext());
              GetNextToken();
              if (JSToken.RightParen != this.currentToken.token)
                increment = ParseExpression();
              else
                increment = new EmptyLiteral(CurrentPositionContext());
              if (JSToken.RightParen != this.currentToken.token)
                ReportError(JSError.NoRightParen);
              forCtx.UpdateWith(this.currentToken);
              GetNextToken();
            }catch(RecoveryTokenException exc){
              if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
                exc._partiallyComputedNode = null;
                throw exc;
              }else{
                // discard any partial info, just genrate empty condition and increment and keep going
                exc._partiallyComputedNode = null;
                if (condOrColl == null)
                  condOrColl = new ConstantWrapper(true, CurrentPositionContext());
                if (increment == null)
                  increment = new EmptyLiteral(CurrentPositionContext());
              }
              if (exc._token == JSToken.RightParen){
                GetNextToken();
              }
            }finally{
              this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
            }
            AST body = null;
            try{
              body = ParseStatement();
            }catch(RecoveryTokenException exc){
              if (exc._partiallyComputedNode == null)
                body = new Block(CurrentPositionContext());
              else
                body = exc._partiallyComputedNode;
              exc._partiallyComputedNode = new For(forCtx, initializer, condOrColl, increment, body);
              throw exc;
            }
            forNode = new For(forCtx, initializer, condOrColl, increment, body);
          }
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        return forNode;
      }
Exemplo n.º 13
0
      //---------------------------------------------------------------------------------------
      // ParseDoStatement
      //
      //  DoStatement:
      //    'do' Statement 'while' '(' Expression ')'
      //---------------------------------------------------------------------------------------
      private DoWhile ParseDoStatement(){
        Context doCtx = null; // this.currentToken.Clone();
        AST body = null;
        AST condition = null;
        this.blockType.Add(BlockType.Loop);
        try{
          GetNextToken();
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_DoWhileBodyNoSkipTokenSet);
          try{
            body = ParseStatement();
          }catch(RecoveryTokenException exc){
            // make up a block for the do while
            if (exc._partiallyComputedNode != null)
              body = exc._partiallyComputedNode;
            else
              body = new Block(CurrentPositionContext());
            if (IndexOfToken(NoSkipTokenSet.s_DoWhileBodyNoSkipTokenSet, exc) == -1){
              // we have to pass the exception to someone else, make as much as you can from the 'do while'
              exc._partiallyComputedNode = new DoWhile(CurrentPositionContext(),
                                                        body,
                                                        new ConstantWrapper(false, CurrentPositionContext()));
              throw exc;
            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_DoWhileBodyNoSkipTokenSet);
          }
          if (JSToken.While != this.currentToken.token){
            ReportError(JSError.NoWhile);
          }
          doCtx = this.currentToken.Clone();
          GetNextToken();
          if (JSToken.LeftParen != this.currentToken.token){
            ReportError(JSError.NoLeftParen);
          }
          GetNextToken();
          // catch here so the body of the do_while is not thrown away
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          try{
            condition = ParseExpression();
            if (JSToken.RightParen != this.currentToken.token){
              ReportError(JSError.NoRightParen);
              doCtx.UpdateWith(condition.context);
            }else
              doCtx.UpdateWith(this.currentToken);
            GetNextToken();
          }catch(RecoveryTokenException exc){
            // make up a condition
            if (exc._partiallyComputedNode != null)
              condition = exc._partiallyComputedNode;
            else
              condition = new ConstantWrapper(false, CurrentPositionContext());

            if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
              exc._partiallyComputedNode = new DoWhile(doCtx, body, condition);
              throw exc;
            }else{
              if (JSToken.RightParen == this.currentToken.token)
                GetNextToken();
            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          }
          if (JSToken.Semicolon == this.currentToken.token){
            // JScript 5 allowed statements like
            //   do{print(++x)}while(x<10) print(0)
            // even though that does not strictly follow the automatic semicolon insertion
            // rules for the required semi after the while().  For backwards compatibility
            // we should continue to support this.
            doCtx.UpdateWith(this.currentToken);
            GetNextToken();
          }
          
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        return new DoWhile(doCtx, body, condition);
      }
Exemplo n.º 14
0
      //---------------------------------------------------------------------------------------
      // ParseWhileStatement
      //
      //  WhileStatement :
      //    'while' '(' Expression ')' Statement
      //---------------------------------------------------------------------------------------
      private While ParseWhileStatement(){
        Context whileCtx = this.currentToken.Clone();
        AST condition = null;
        AST body = null;
        this.blockType.Add(BlockType.Loop);
        try{
        GetNextToken();
        if (JSToken.LeftParen != this.currentToken.token){
          ReportError(JSError.NoLeftParen);
        }
        GetNextToken();
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          try{
          condition = ParseExpression();
          if (JSToken.RightParen != this.currentToken.token){
            ReportError(JSError.NoRightParen);
            whileCtx.UpdateWith(condition.context);
          }else
            whileCtx.UpdateWith(this.currentToken);

          GetNextToken();
          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
              // abort the while there is really no much to do here
              exc._partiallyComputedNode = null;
              throw exc;
            }else{
              // make up a condition
              if (exc._partiallyComputedNode != null)
                condition = exc._partiallyComputedNode;
              else
                condition = new ConstantWrapper(false, CurrentPositionContext());

              if (JSToken.RightParen == this.currentToken.token)
                GetNextToken();
            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          }

          try{
            body = ParseStatement();
          }catch(RecoveryTokenException exc){
            if (exc._partiallyComputedNode != null)
              body = exc._partiallyComputedNode;
            else
              body = new Block(CurrentPositionContext());

            exc._partiallyComputedNode = new While(whileCtx, condition, body);
            throw exc;
          }

        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

      return new While(whileCtx, condition, body);
      }
Exemplo n.º 15
0
      //---------------------------------------------------------------------------------------
      // ParseStatement
      //
      //  OptionalStatement:
      //    Statement |
      //    <empty>
      //
      //  Statement :
      //    Block |
      //  VariableStatement |
      //  EmptyStatement |
      //  ExpressionStatement |
      //  IfStatement |
      //  IterationStatement |
      //  ContinueStatement |
      //  BreakStatement |
      //  ReturnStatement |
      //  WithStatement |
      //  LabeledStatement |
      //  SwitchStatement |
      //  ThrowStatement |
      //  TryStatement |
      //  QualifiedDeclaration |
      //  Class |
      //  FunctionDeclaration
      //
      // IterationStatement :
      //    'for' '(' ForLoopControl ')' |                  ===> ForStatement
      //    'do' Statement 'while' '(' Expression ')' |     ===> DoStatement
      //    'while' '(' Expression ')' Statement            ===> WhileStatement
      //
      //---------------------------------------------------------------------------------------

      // ParseStatement deals with the end of statement issue (EOL vs ';') so if any of the
      // ParseXXX routine does it as well, it should return directly from the switch statement
      // without any further execution in the ParseStatement
      private AST ParseStatement(){
        AST statement = null;
        String id = null;

        switch (this.currentToken.token){
          case JSToken.EndOfFile:
            EOFError(JSError.ErrEOF);
            throw new EndOfFile(); // abort parsing, get back to the main parse routine
          case JSToken.Debugger:
            statement = new DebugBreak(this.currentToken.Clone());
            GetNextToken();
            break;
          case JSToken.Semicolon:
            // make an empty statement
            statement = new Block(this.currentToken.Clone());
            GetNextToken();
            return statement;
          case JSToken.RightCurly:
            ReportError(JSError.SyntaxError);
            SkipTokensAndThrow();
            break;
          case JSToken.LeftCurly:
            return ParseBlock();
          case JSToken.Var:
          case JSToken.Const:
            return ParseVariableStatement((FieldAttributes)0, null, this.currentToken.token);
          case JSToken.If:
            return ParseIfStatement();
          case JSToken.For:
            return ParseForStatement();
          case JSToken.Do:
            return ParseDoStatement();
          case JSToken.While:
            return ParseWhileStatement();
          case JSToken.Continue:
            statement = ParseContinueStatement();
            if (null == statement)
              return new Block(CurrentPositionContext());
            else
              return statement;
          case JSToken.Break:
            statement = ParseBreakStatement();
            if (null == statement)
              return new Block(CurrentPositionContext());
            else
              return statement;
          case JSToken.Return:
            statement = ParseReturnStatement();
            if (null == statement)
              return new Block(CurrentPositionContext());
            else
              return statement;
          case JSToken.With:
            return ParseWithStatement();
          case JSToken.Switch:
            return ParseSwitchStatement();
          case JSToken.Super:
          case JSToken.This:
            Context superCtx = this.currentToken.Clone();
            if (JSToken.LeftParen == this.scanner.PeekToken())
              statement = ParseConstructorCall(superCtx);
            else
              goto default;
            break;
          case JSToken.Throw:
            statement = ParseThrowStatement();
            if (statement == null)
              return new Block(CurrentPositionContext());
            else
              break;
          case JSToken.Try:
            return ParseTryStatement();
          case JSToken.Internal:
          case JSToken.Public:
          case JSToken.Static:
          case JSToken.Private:
          case JSToken.Protected:
          case JSToken.Abstract:
          case JSToken.Final:
            bool parsedOK;
            statement = ParseAttributes(null, false, false, out parsedOK);
            if (!parsedOK){
              statement = ParseExpression(statement, false, true, JSToken.None);
              statement = new Expression(statement.context.Clone(), statement);
              break;
            }else
              return statement;
          case JSToken.Package:
            Context packageContext = this.currentToken.Clone();
            statement = ParsePackage(packageContext);
            if (statement is Package){
              // handle common error of using import in function
              ReportError(JSError.PackageInWrongContext, packageContext, true);
              // make an empty statement
              statement = new Block(packageContext);
            }
            break;                      
          case JSToken.Interface:
          case JSToken.Class:
            return ParseClass((FieldAttributes)0, false, this.currentToken.Clone(), false, false, null);
          case JSToken.Enum:
            return ParseEnum((FieldAttributes)0, this.currentToken.Clone(), null);
          case JSToken.Function:
            return ParseFunction((FieldAttributes)0, false, this.currentToken.Clone(), false, false, false, false, null); //Parse a function as a statement
          case JSToken.Else:
            ReportError(JSError.InvalidElse);
            SkipTokensAndThrow();
            break;
          case JSToken.Import:
            // handle common error of using import in function
            ReportError(JSError.InvalidImport, true);
            // make an empty statement
            statement = new Block(this.currentToken.Clone());
            try{
              ParseImportStatement();
            }catch(RecoveryTokenException){
            }
            break;                      
          default:
            this.noSkipTokenSet.Add(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet);
            bool exprError = false;
            try{
              bool bAssign, canBeAttribute = true;
              statement = ParseUnaryExpression(out bAssign, ref canBeAttribute, false);
              if (canBeAttribute){
                // look for labels
                if (statement is Lookup){
                  if (JSToken.Colon == this.currentToken.token){
                    // can be a label
                    id = statement.ToString();
                    if (null != this.labelTable[id]){
                      // there is already a label with that name. Ignore the current label
                      ReportError(JSError.BadLabel, statement.context.Clone(), true);
                      id = null;
                      GetNextToken(); // skip over ':'
                      return new Block(CurrentPositionContext());
                    }else{
                      GetNextToken();
                      this.labelTable[id] = this.blockType.Count;
                      if (JSToken.EndOfFile != this.currentToken.token)
                        statement = ParseStatement();
                      else
                        statement = new Block(CurrentPositionContext());
                      this.labelTable.Remove(id);
                      return statement;
                    }
                  }
                }
                // look for custom attributes
                if (JSToken.Semicolon != this.currentToken.token && !this.scanner.GotEndOfLine()){
                  bool parsed;
                  statement = ParseAttributes(statement, false, false, out parsed);
                  if (parsed)
                    return statement;
                }
              }
              statement = ParseExpression(statement, false, bAssign, JSToken.None);
              statement = new Expression(statement.context.Clone(), statement);
            }catch(RecoveryTokenException exc){
              if (exc._partiallyComputedNode != null)
                statement = exc._partiallyComputedNode;

              if (statement == null){
                this.noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet);
                exprError = true;
                SkipTokensAndThrow();
              }

              if (IndexOfToken(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet, exc) == -1){
                exc._partiallyComputedNode = statement;
                throw exc;
              }
            }finally{
              if (!exprError)
                this.noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfStatementNoSkipTokenSet);
            }
            break;
        }

        if (JSToken.Semicolon == this.currentToken.token){
          statement.context.UpdateWith(this.currentToken);
          GetNextToken();
        }else if (!this.scanner.GotEndOfLine() && JSToken.RightCurly != this.currentToken.token && JSToken.EndOfFile != this.currentToken.token)
          ReportError(JSError.NoSemicolon, true);

        return statement;
      }
Exemplo n.º 16
0
        private void ParseAst(JS.AST ast, string sp)
        {
            if (ast == null)
            {
                return;
            }
            if (CheckWorker())
            {
                return;
            }

            //_logView.LogStr("JSM->" + sp + ast.ToString() + "\t\t" + ast.GetType().Name);

            if (ast is JS.FunctionDeclaration)
            {
                JS.Function func = ast as JS.Function;
                ParseAstList(func.func_obj.body.elems, sp + "  ");
            }
            else if (ast is JS.Assign)
            {
                JS.Assign ass = ast as JS.Assign;

                ParseAst(ass.left, sp + "l ");
                ParseAst(ass.right, sp + "r ");
            }
            else if (ast is JS.Binary)
            {
                JS.Binary bin = ast as JS.Binary;

                string[] parts = bin.ToString().Split('.');
                if (parts.Length > 1)
                {
                    if (parts[parts.Length - 2] == "This")
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        //dup
                        // If we have a method of this name in this file/class
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Create an edge.
                            // A definite functional assignment link.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Aqua);
                        }
                        else
                        {
                            // It's a call to a method outside this class/file.
                            //
                            //_logView.LogStr("skipped assign ref -->" + _methodNodeId + " --------> " + calledId);
                            //
                        }
                    }
                    else if (parts[parts.Length - 2] == "self")
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        //dup
                        // If we have a method of this name in this file/class
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Get the graph node that we're linking to.
                            //Node calledNode = _addedNodes[calledId];

                            // Create an edge.
                            // A definite functional assignment link.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Aqua);
                        }
                        else
                        {
                            // It's a call to a method outside this class/file.
                            _logView.LogStr("skipped assign ref -->" + _methodNodeId + " --------> " + calledId);
                        }
                    }
                }
            }
            else if (ast is JS.Expression)
            {
                JS.Expression expr = ast as JS.Expression;
                ParseAstList(expr.exprs, sp + "  ");
            }
            else if (ast is JS.FunctionExpression)
            {
                JS.FunctionExpression expr = ast as JS.FunctionExpression;
                ParseAstList(expr.func_obj.body.elems, sp + "  ");
            }
            else if (ast is JS.For)
            {
                JS.For fr = ast as JS.For;
                ParseAst(fr.stms, sp + "  ");
            }
            else if (ast is JS.If)
            {
                JS.If iff = ast as JS.If;
                ParseAst(iff.false_stm, sp + "f  ");
                ParseAst(iff.true_stm, sp + "t  ");
            }
            else if (ast is JS.Block)
            {
                JS.Block block = ast as JS.Block;
                ParseAstList(block.elems, sp + "  ");
            }
            else if (ast is JS.VariableStatement)
            {
                JS.VariableStatement var = ast as JS.VariableStatement;
                //var.
                ParseAstList(var.var_decls, sp + "  ");
            }
            else if (ast is JS.Return)
            {
                JS.Return ret = ast as JS.Return;

                ParseAst(ret.expression, sp + "  ");
            }
            else if (ast is JS.VariableDeclaration)
            {
                JS.VariableDeclaration var = ast as JS.VariableDeclaration;

                Microsoft.JScript.New newval = var.val as Microsoft.JScript.New;

                if (newval != null && newval.exp != null)
                {
                    //_logView.LogStr("new:" + newval.exp.ToString());
                    string[] parts = newval.exp.ToString().Split('.');
                    if (parts.Length > 0)
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        // If we have a method of this name in this file/class, then
                        // we have a possible constructor link.
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Create an edge.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Green);
                        }
                    }
                }
                else
                {
                    if (var.val != null)
                    {
                        string   valStr = var.val.ToString();
                        string[] parts  = valStr.Split('.');

                        if (parts.Length > 1 && parts[0] == "self")
                        {
                            // dup..

                            string calledId = parts[parts.Length - 1] + "()";

                            // If we have a method of this name in this file/class, then
                            // we have a possible constructor link.
                            if (_addedNodes.ContainsKey(calledId))
                            {
                                // Create an edge.
                                AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Green);
                            }
                        }
                    }
                }

                //ParseAstList(var.var_decls, sp + "  ");
            }
            else if (ast is JS.Call)
            {
                JS.Call  call     = ast as JS.Call;
                string[] parts    = call.ToString().Split(' ');
                string[] bits     = parts[0].Split('.');
                string   calledId = bits[bits.Length - 1] + "()";

                bool methodInThisClass = true;
                if (bits.Length > 1)
                {
                    if ((bits[bits.Length - 2] != "This") &&
                        (bits[bits.Length - 2] != "self"))
                    {
                        methodInThisClass = false;
                    }
                }

                // If we have a method of this name in this file/class
                if (_addedNodes.ContainsKey(calledId))
                {
                    // Create an edge.
                    if (methodInThisClass)
                    {
                        // A definite link.
                        AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Black);
                    }
                    else
                    {
                        // A tentative link.
                        AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Gray);
                    }
                }
                else
                {
                    // It's a call to a method outside this class/file.
                    //
                    //_logView.LogStr("skipped -------->" + _methodNodeId + " --------> " + parts[0]);
                    //
                }
            }
        }
Exemplo n.º 17
0
        Block ParseFunctionBody(AST parent)
        {
            ++nesting_of_function;
            Block pn = new Block (parent, new Location (ts.SourceName, ts.LineNumber));

            try {
                int tt;
                while ((tt = ts.PeekToken ()) > Token.EOF && tt != Token.RC) {
                    AST n;
                    if (tt == Token.FUNCTION) {
                        ts.GetToken ();
                        n = Function (parent, FunctionType.Statement);
                    } else
                        n = Statement (parent);
                    pn.Add (n);
                }
            } catch (ParserException) {
                ok = false;
            } finally {
                --nesting_of_function;
            }
            return pn;
        }
Exemplo n.º 18
0
      internal FunctionDeclaration(Context context, AST ifaceId, IdentifierLiteral id, ParameterDeclaration[] formal_parameters, TypeExpression return_type, 
                                   Block body, FunctionScope own_scope, FieldAttributes attributes, 
                                   bool isMethod, bool isGetter, bool isSetter, bool isAbstract, bool isFinal, CustomAttributeList customAttributes)
        : base(context) {
        MethodAttributes methodAttributes = (MethodAttributes)0;
        if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public)
          methodAttributes = MethodAttributes.Public;
        else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private)
          methodAttributes = MethodAttributes.Private;
        else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly)
          methodAttributes = MethodAttributes.Assembly;
        else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family)
          methodAttributes = MethodAttributes.Family;
        else if ((attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem)
          methodAttributes = MethodAttributes.FamORAssem;
        else
          methodAttributes = MethodAttributes.Public;

        if ((attributes & FieldAttributes.Static) != 0 || !isMethod)
          methodAttributes |= MethodAttributes.Static;
        else
          methodAttributes |= MethodAttributes.Virtual | MethodAttributes.NewSlot;
        
        if (isAbstract)
          methodAttributes |= MethodAttributes.Abstract;
        if (isFinal)
          methodAttributes |= MethodAttributes.Final;
        
        this.name = id.ToString();
        this.isMethod = isMethod;
        if (ifaceId != null){
          if (isMethod){
            this.ifaceId = new TypeExpression(ifaceId);
            methodAttributes &= ~MethodAttributes.MemberAccessMask;
            methodAttributes |= MethodAttributes.Private|MethodAttributes.Final;
          }else{
            this.declaringObject = new Member(ifaceId.context, ifaceId, id);
            this.name = this.declaringObject.ToString();
          }
        }
        ScriptObject enclosingScope = Globals.ScopeStack.Peek();
        if (attributes == 0 && !isAbstract && !isFinal){
          if (enclosingScope is ClassScope)
            attributes |= FieldAttributes.Public;
        }else{
          if (!(enclosingScope is ClassScope)){
            this.context.HandleError(JSError.NotInsideClass);
            attributes = (FieldAttributes)0;
            methodAttributes = MethodAttributes.Public;
          }
        }
        if (enclosingScope is ActivationObject){
          this.inFastScope = ((ActivationObject)enclosingScope).fast;
          // if later on originalName != this.name this is a property getter/setter
          String originalName = this.name; 
          // mangle the name 
          if (isGetter){
            methodAttributes |= MethodAttributes.SpecialName;
            this.name = "get_" + this.name;
            if (return_type == null)
              return_type = new TypeExpression(new ConstantWrapper(Typeob.Object, context));
          }else if (isSetter){
            methodAttributes |= MethodAttributes.SpecialName;
            this.name = "set_" + this.name;
            return_type = new TypeExpression(new ConstantWrapper(Typeob.Void, context));
          }
          attributes &= FieldAttributes.FieldAccessMask;
          // create the function object
          this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, enclosingScope, this.context, 
                                         methodAttributes, customAttributes, this.isMethod);
          if (this.declaringObject != null) return;
          // check whether the function name (possibly mangled) is in use already
          String fieldName = this.name;
          if (this.ifaceId != null) fieldName = ifaceId.ToString()+"."+fieldName;
          JSVariableField localField = (JSVariableField)((ActivationObject)enclosingScope).name_table[fieldName];
          if (localField != null && (!(localField is JSMemberField) || !(((JSMemberField)localField).value is FunctionObject) || this.func.isExpandoMethod)){
            if (originalName != this.name)
              localField.originalContext.HandleError(JSError.ClashWithProperty);
            else{
              id.context.HandleError(JSError.DuplicateName, this.func.isExpandoMethod);
              if (localField.value is FunctionObject)
                ((FunctionObject)localField.value).suppressIL = true;
            }
          }
          // create or update the proper field
          if (this.isMethod){
            if (!(localField is JSMemberField) || !(((JSMemberField)localField).value is FunctionObject) || originalName != this.name){
              this.field = ((ActivationObject)enclosingScope).AddNewField(fieldName, this.func, attributes|FieldAttributes.Literal);
              if (originalName == this.name) // if it is a property do not assign the type
                ((JSVariableField)this.field).type = new TypeExpression(new ConstantWrapper(Typeob.FunctionWrapper, this.context));
            }else
              this.field = ((JSMemberField)localField).AddOverload(this.func, attributes|FieldAttributes.Literal);
          }else if (enclosingScope is FunctionScope){
            if (this.inFastScope) attributes |= FieldAttributes.Literal;
            this.field = ((FunctionScope)enclosingScope).AddNewField(this.name, attributes, this.func);
            if (this.field is JSLocalField){
              JSLocalField locField = (JSLocalField)this.field;
              if (this.inFastScope){
                locField.type = new TypeExpression(new ConstantWrapper(Typeob.ScriptFunction, this.context));
                locField.attributeFlags |= FieldAttributes.Literal;
              }
              locField.debugOn = this.context.document.debugOn;
              locField.isDefined = true;
            }
          }else if (this.inFastScope){
            this.field = ((ActivationObject)enclosingScope).AddNewField(this.name, this.func, attributes|FieldAttributes.Literal);
            ((JSVariableField)this.field).type = new TypeExpression(new ConstantWrapper(Typeob.ScriptFunction, this.context));
            //Do not use typeof(Closure) for the field, since that has the arguments and callee properties, which are not
            //accessible in fast mode
          }else //enclosingScope is GlobalObject
            this.field = ((ActivationObject)enclosingScope).AddNewField(this.name, this.func, attributes|FieldAttributes.Static);
          ((JSVariableField)this.field).originalContext = context;
          
          // if it is a property create/update the PropertyInfo and assign the getter/setter
          if (originalName != this.name){
            String propertyFieldName = originalName;
            if (this.ifaceId != null) propertyFieldName = ifaceId.ToString()+"."+originalName;
            FieldInfo prop = (FieldInfo)((ClassScope)enclosingScope).name_table[propertyFieldName];
            if (prop != null){
              // check whether a property was defined already
              if (prop.IsLiteral){
                Object val = ((JSVariableField)prop).value;
                if (val is JSProperty)
                  this.enclosingProperty = (JSProperty)val;
              }
              if (this.enclosingProperty == null)
                id.context.HandleError(JSError.DuplicateName, true); // the matching name was not a property
            }
            if (this.enclosingProperty == null){
              this.enclosingProperty = new JSProperty(originalName);
              prop = ((ActivationObject)enclosingScope).AddNewField(propertyFieldName, this.enclosingProperty, attributes|FieldAttributes.Literal);
              ((JSMemberField)prop).originalContext = this.context;
            }else{
              if ((isGetter && this.enclosingProperty.getter != null) || (isSetter && this.enclosingProperty.setter != null))
                id.context.HandleError(JSError.DuplicateName, true); // duplicated setter or getter
            }
            if (isGetter)
              this.enclosingProperty.getter = new JSFieldMethod(this.field, enclosingScope);
            else
              this.enclosingProperty.setter = new JSFieldMethod(this.field, enclosingScope);
          }
        }else{ //Might get here if function declaration is inside of an eval.
          this.inFastScope = false;
          this.func = new FunctionObject(this.name, formal_parameters, return_type, body, own_scope, enclosingScope, this.context, MethodAttributes.Public, null, false);
          this.field = ((StackFrame)enclosingScope).AddNewField(this.name, new Closure(this.func), attributes|FieldAttributes.Static);
        }
      }
Exemplo n.º 19
0
      //---------------------------------------------------------------------------------------
      // ParseVariableStatement
      //
      //  VariableStatement :
      //    ('var' | 'const') VariableDeclarationList
      //
      //  VariableDeclarationList :
      //    VariableDeclaration |
      //    VariableDeclaration ',' VariableDeclarationList
      //
      //  VariableDeclaration :
      //    Identifier Type Initializer
      //
      //  Type :
      //    <empty> |
      //    ':' TypeExpression
      //
      //  Initializer :
      //    <empty> |
      //    '=' AssignmentExpression
      //---------------------------------------------------------------------------------------
      private AST ParseVariableStatement(FieldAttributes visibility, CustomAttributeList customAttributes, JSToken kind){
        Block varList = new Block(this.currentToken.Clone());
        bool single = true;
        AST vdecl = null;

        for (;;){
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_EndOfLineToken);
          try{
            vdecl = ParseIdentifierInitializer(JSToken.None, visibility, customAttributes, kind);
          }catch(RecoveryTokenException exc){
            // an exception is passing by, possibly bringing some info, save the info if any
            if (exc._partiallyComputedNode != null){
              if (!single){
                varList.Append(exc._partiallyComputedNode);
                varList.context.UpdateWith(exc._partiallyComputedNode.context);
                exc._partiallyComputedNode = varList;
              }
            }
            if (IndexOfToken(NoSkipTokenSet.s_EndOfLineToken, exc) == -1)
              throw exc;
            else{
              if (single)
                vdecl = exc._partiallyComputedNode;
            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_EndOfLineToken);
          }

          if (JSToken.Semicolon == this.currentToken.token || JSToken.RightCurly == this.currentToken.token){
            if (JSToken.Semicolon == this.currentToken.token){
              vdecl.context.UpdateWith(this.currentToken);
              GetNextToken();
            }
            break;
          }else if (JSToken.Comma == this.currentToken.token){
            single = false;
            varList.Append(vdecl);
            continue;
          }else if (this.scanner.GotEndOfLine()){
            break;
          }else{
            // assume the variable statement was terminated and move on
            ReportError(JSError.NoSemicolon, true);
            break;
          }
        }

        if (single)
          return vdecl;
        else{
          varList.Append(vdecl);
          varList.context.UpdateWith(vdecl.context);
          return varList;
        }
      }
Exemplo n.º 20
0
      //---------------------------------------------------------------------------------------
      // 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);
      }
Exemplo n.º 21
0
      //---------------------------------------------------------------------------------------
      // ParseStaticInitializer
      //
      //  StaticInitializer :
      //    '{' FunctionBody '}'
      //---------------------------------------------------------------------------------------
      private AST ParseStaticInitializer(Context initContext){
        Block body = null;
        FunctionScope scope = new FunctionScope(Globals.ScopeStack.Peek());
        scope.isStatic = true;

        // 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);

        this.blockType.Add(BlockType.Block);
        this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
        this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
        try{
          Globals.ScopeStack.Push(scope); //Give declarations a place to go while building AST
          // 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;
            }
          }
        }catch(RecoveryTokenException exc){
          if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){
            exc._partiallyComputedNode = new StaticInitializer(initContext, body, scope);
            throw exc;
          }
        }finally{
          this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
          this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          this.blockType = blockType;
          this.labelTable = labelTable;
          Globals.ScopeStack.Pop();
        }
        body.context.UpdateWith(this.currentToken);
        initContext.UpdateWith(this.currentToken);

        GetNextToken();
        return new StaticInitializer(initContext, body, scope);
      }
Exemplo n.º 22
0
      //---------------------------------------------------------------------------------------
      // 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();
        }
      }
Exemplo n.º 23
0
      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;

      }
Exemplo n.º 24
0
Arquivo: ast.cs Projeto: nickchal/pash
		internal void Init (Block body, FormalParameterList p)
		{
			func_obj.body = body;
			func_obj.parameters = p;
		}
 internal FunctionObject(string name, ParameterDeclaration[] parameter_declarations, TypeExpression return_type_expr, Block body, FunctionScope own_scope, ScriptObject enclosing_scope, Context funcContext, MethodAttributes attributes) : this(name, parameter_declarations, return_type_expr, body, own_scope, enclosing_scope, funcContext, attributes, null, false)
 {
 }
Exemplo n.º 26
0
 AST Statements(AST parent)
 {
     int tt;
     Block pn = new Block (parent, new Location (ts.SourceName, ts.LineNumber));
     while ((tt = ts.PeekToken ()) > Token.EOF && tt != Token.RC)
         pn.Add (Statement (pn));
     return pn;
 }
Exemplo n.º 27
0
      //---------------------------------------------------------------------------------------
      // ParseSwitchStatement
      //
      //  SwitchStatement :
      //    'switch' '(' Expression ')' '{' CaseBlock '}'
      //
      //  CaseBlock :
      //    CaseList DefaultCaseClause CaseList
      //
      //  CaseList :
      //    <empty> |
      //    CaseClause CaseList
      //
      //  CaseClause :
      //    'case' Expression ':' OptionalStatements
      //
      //  DefaultCaseClause :
      //    <empty> |
      //    'default' ':' OptionalStatements
      //---------------------------------------------------------------------------------------
      private AST ParseSwitchStatement(){
        Context switchCtx = this.currentToken.Clone();
        AST expr = null;
        ASTList cases = null;
        this.blockType.Add(BlockType.Switch);
        try{
          // read switch(expr)
        GetNextToken();
        if (JSToken.LeftParen != this.currentToken.token)
            ReportError(JSError.NoLeftParen);
        GetNextToken();
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
          try{
            expr = ParseExpression();

          if (JSToken.RightParen != this.currentToken.token){
              ReportError(JSError.NoRightParen);
            }

          GetNextToken();
          if (JSToken.LeftCurly != this.currentToken.token){
              ReportError(JSError.NoLeftCurly);
            }
            GetNextToken();

          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1
                  && IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1 ){
              // give up
              exc._partiallyComputedNode = null;
              throw exc;
            }else{
              if (exc._partiallyComputedNode == null)
                expr = new ConstantWrapper(true, CurrentPositionContext());
              else
                expr = exc._partiallyComputedNode;

              if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) != -1){
                if (exc._token == JSToken.RightParen)
                  GetNextToken();

                if (JSToken.LeftCurly != this.currentToken.token){
                  ReportError(JSError.NoLeftCurly);
                }
                GetNextToken();
              }

            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          }

          // parse the switch body
          cases = new ASTList(this.currentToken.Clone());
        bool defaultStatement = false;
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          try{
            while (JSToken.RightCurly != this.currentToken.token){
              SwitchCase caseClause = null;
              AST caseValue = null;
              Context caseCtx = this.currentToken.Clone();
              this.noSkipTokenSet.Add(NoSkipTokenSet.s_CaseNoSkipTokenSet);
              try{
                if (JSToken.Case == this.currentToken.token){
                  // get the case
                  GetNextToken();
                  caseValue = ParseExpression();
                }else if (JSToken.Default == this.currentToken.token){
                  // get the default
                  if (defaultStatement)
                    // we report an error but we still accept the default
                    ReportError(JSError.DupDefault, true);
                  else
                    defaultStatement = true;
                  GetNextToken();
                }else{
                  // This is an error, there is no case or default. Assume a default was missing and keep going
                  defaultStatement = true;
                  ReportError(JSError.BadSwitch);
                }
                if (JSToken.Colon != this.currentToken.token)
                  ReportError(JSError.NoColon);

                // read the statements inside the case or default
                GetNextToken();
              }catch(RecoveryTokenException exc){
                // right now we can only get here for the 'case' statement
                if (IndexOfToken(NoSkipTokenSet.s_CaseNoSkipTokenSet, exc) == -1){
                  // ignore the current case or default
                  exc._partiallyComputedNode = null;
                  throw exc;
                }else{
                  caseValue = exc._partiallyComputedNode;

                  if (exc._token == JSToken.Colon)
                    GetNextToken();
                }
              }finally{
                this.noSkipTokenSet.Remove(NoSkipTokenSet.s_CaseNoSkipTokenSet);
              }

              this.blockType.Add(BlockType.Block);
              try{
                Block statements = new Block(this.currentToken.Clone());
                this.noSkipTokenSet.Add(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                try{
                  while (JSToken.RightCurly != this.currentToken.token && JSToken.Case != this.currentToken.token && JSToken.Default != this.currentToken.token){
                    try{
                      statements.Append(ParseStatement());
                    }catch(RecoveryTokenException exc){
                      if (exc._partiallyComputedNode != null){
                        statements.Append(exc._partiallyComputedNode);
                        exc._partiallyComputedNode = null;
                      }
                      if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1)
                        throw exc;
                    }
                  }
                }catch(RecoveryTokenException exc){
                  if (IndexOfToken(NoSkipTokenSet.s_SwitchNoSkipTokenSet, exc) == -1){
                    if (null == caseValue)
                      caseClause = new SwitchCase(caseCtx, statements);
                    else
                      caseClause = new SwitchCase(caseCtx, caseValue, statements);
                    cases.Append(caseClause);

                    throw exc;
                  }
                }finally{
                  this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
                  this.noSkipTokenSet.Remove(NoSkipTokenSet.s_SwitchNoSkipTokenSet);
                }
                if (JSToken.RightCurly == this.currentToken.token)
                  statements.context.UpdateWith(this.currentToken);
                if (null == caseValue){
                  caseCtx.UpdateWith(statements.context);
                  caseClause = new SwitchCase(caseCtx, statements);
                }else{
                  caseCtx.UpdateWith(statements.context);
                  caseClause = new SwitchCase(caseCtx, caseValue, statements);
                }
                cases.Append(caseClause);
              }finally{
                this.blockType.RemoveAt(this.blockType.Count - 1);
              }
            }
          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){
              //save what you can a rethrow
              switchCtx.UpdateWith(CurrentPositionContext());
              exc._partiallyComputedNode = new Switch(switchCtx, expr, cases);
              throw exc;
            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          }
          switchCtx.UpdateWith(this.currentToken);
          GetNextToken();
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        return new Switch(switchCtx, expr, cases);
      }
Exemplo n.º 28
0
 internal DeleteInfo(int index, Block block)
 {
     this.index = index;
     this.block = block;
 }
Exemplo n.º 29
0
      //---------------------------------------------------------------------------------------
      // ParseWithStatement
      //
      //  WithStatement :
      //    'with' '(' Expression ')' Statement
      //---------------------------------------------------------------------------------------
      private With ParseWithStatement(){
        Context withCtx = this.currentToken.Clone();
        AST obj = null;
        AST block = null;
        this.blockType.Add(BlockType.Block);
        try{
          GetNextToken();
          if (JSToken.LeftParen != this.currentToken.token)
            ReportError(JSError.NoLeftParen);
          GetNextToken();
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          try{
            obj = ParseExpression();
            if (JSToken.RightParen != this.currentToken.token){
              withCtx.UpdateWith(obj.context);
              ReportError(JSError.NoRightParen);
            }else
              withCtx.UpdateWith(this.currentToken);
            GetNextToken();
          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet, exc) == -1){
              // give up
              exc._partiallyComputedNode = null;
              throw exc;
            }else{
              if (exc._partiallyComputedNode == null)
                obj = new ConstantWrapper(true, CurrentPositionContext());
              else
                obj = exc._partiallyComputedNode;
              withCtx.UpdateWith(obj.context);

              if (exc._token == JSToken.RightParen)
                GetNextToken();
            }
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockConditionNoSkipTokenSet);
          }

          try{
            block = ParseStatement();
          }catch(RecoveryTokenException exc){
            if (exc._partiallyComputedNode == null)
              block = new Block(CurrentPositionContext());
            else
              block = exc._partiallyComputedNode;
            exc._partiallyComputedNode = new With(withCtx, obj, block);
          }
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        return new With(withCtx, obj, block);
      }
Exemplo n.º 30
0
      Block ParseBlock(out Context closingBraceContext){
        closingBraceContext = null;
        this.blockType.Add(BlockType.Block);
        Block codeBlock = new Block(this.currentToken.Clone());
        GetNextToken();

        this.noSkipTokenSet.Add(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
        this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
        try{
          try{
            while (JSToken.RightCurly != this.currentToken.token){
              try{
                codeBlock.Append(ParseStatement());
              }catch(RecoveryTokenException exc){
                if (exc._partiallyComputedNode != null)
                  codeBlock.Append(exc._partiallyComputedNode);
                if (IndexOfToken(NoSkipTokenSet.s_StartStatementNoSkipTokenSet, exc) == -1)
                  throw exc;
              }
            }
          }catch(RecoveryTokenException exc){
            if (IndexOfToken(NoSkipTokenSet.s_BlockNoSkipTokenSet, exc) == -1){
              exc._partiallyComputedNode = codeBlock;
              throw exc;
            }
          }
        }finally{
          this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          this.noSkipTokenSet.Remove(NoSkipTokenSet.s_StartStatementNoSkipTokenSet);
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        closingBraceContext = this.currentToken.Clone();
        // update the block context
        codeBlock.context.UpdateWith(this.currentToken);
        GetNextToken();
        return codeBlock;
      }
Exemplo n.º 31
0
      //---------------------------------------------------------------------------------------
      // ParseClassBody
      //
      //  ClassBody :
      //    '{' OptionalClassMembers '}'
      //---------------------------------------------------------------------------------------
      Block ParseClassBody(bool isEnum, bool isInterface){
        this.blockType.Add(BlockType.Block);
        Block codeBlock = new Block(this.currentToken.Clone());
        try{
          GetNextToken();
          this.noSkipTokenSet.Add(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          JSToken[] noSkip = null;
          if (isEnum)
            noSkip = NoSkipTokenSet.s_EnumBodyNoSkipTokenSet;
          else if (isInterface)
            noSkip = NoSkipTokenSet.s_InterfaceBodyNoSkipTokenSet;
          else
            noSkip = NoSkipTokenSet.s_ClassBodyNoSkipTokenSet;
          try{
            while (JSToken.RightCurly != this.currentToken.token){
              if (JSToken.EndOfFile == this.currentToken.token){
                ReportError(JSError.NoRightCurly, true);
                SkipTokensAndThrow();
              }
              this.noSkipTokenSet.Add(noSkip);
              try{
                AST classMember = isEnum ? ParseEnumMember() : ParseClassMember(isInterface);
                if (classMember != null)
                  codeBlock.Append(classMember);
              }catch(RecoveryTokenException exc){
                if (exc._partiallyComputedNode != null)
                  codeBlock.Append(exc._partiallyComputedNode);
                if (IndexOfToken(noSkip, exc) == -1){
                  exc._partiallyComputedNode = null;
                  throw exc;
                }
              }finally{
                this.noSkipTokenSet.Remove(noSkip);
              }
            }

          }catch(RecoveryTokenException exc){
            exc._partiallyComputedNode = codeBlock;
            throw exc;
          }finally{
            this.noSkipTokenSet.Remove(NoSkipTokenSet.s_BlockNoSkipTokenSet);
          }
          codeBlock.context.UpdateWith(this.currentToken);
          GetNextToken();
        }finally{
          this.blockType.RemoveAt(this.blockType.Count - 1);
        }

        return codeBlock;
      }