/// <summary>
 /// Creates a new ExpressionStatement instance.  By default, this expression does not
 /// contribute to the result of an eval().
 /// </summary>
 /// <param name="expression"> The underlying expression. </param>
 public ExpressionStatement(Expression expression)
     : base(null)
 {
     if (expression == null)
         throw new ArgumentNullException("expression");
     this.Expression = expression;
 }
 /// <summary>
 /// Creates a new ExpressionStatement instance.  By default, this expression does
 /// contribute to the result of an eval().
 /// </summary>
 /// <param name="labels"> The labels that are associated with this statement. </param>
 /// <param name="expression"> The underlying expression. </param>
 public ExpressionStatement(IList<string> labels, Expression expression)
     : base(labels)
 {
     if (expression == null)
         throw new ArgumentNullException("expression");
     this.Expression = expression;
     this.ContributesToEvalResult = true;
 }
        /// <summary>
        /// Declares a variable or function in this scope.  This will be initialized with the value
        /// of the given expression.
        /// </summary>
        /// <param name="name"> The name of the variable. </param>
        /// <param name="valueAtTopOfScope"> The value of the variable at the top of the scope. </param>
        /// <param name="writable"> <c>true</c> if the variable can be modified; <c>false</c>
        /// otherwise. </param>
        /// <param name="deletable"> <c>true</c> if the variable can be deleted; <c>false</c>
        /// otherwise. </param>
        /// <returns> A reference to the variable that was declared. </returns>
        internal override DeclaredVariable DeclareVariable(string name, Expression valueAtTopOfScope = null, bool writable = true, bool deletable = false)
        {
            // Variables can be added to a declarative scope using eval().  When this happens the
            // values array needs to be resized.  That check happens here.
            if (this.values != null && this.DeclaredVariableCount >= this.Values.Length)
                Array.Resize(ref this.values, this.DeclaredVariableCount + 10);

            // Delegate to the Scope class.
            return base.DeclareVariable(name, valueAtTopOfScope, writable, deletable);
        }
Beispiel #4
0
        /// <summary>
        /// Checks the given AST is valid.
        /// </summary>
        /// <param name="root"> The root of the AST. </param>
        private void CheckASTValidity(Expression root)
        {
            // Push the root expression onto a stack.
            Stack<Expression> stack = new Stack<Expression>();
            stack.Push(root);

            while (stack.Count > 0)
            {
                // Pop the next expression from the stack.
                var expression = stack.Pop() as OperatorExpression;
                
                // Only operator expressions are checked for validity.
                if (expression == null)
                    continue;

                // Check the operator expression has the right number of operands.
                if (expression.Operator.IsValidNumberOfOperands(expression.OperandCount) == false)
                    throw new JavaScriptException(this.engine, "SyntaxError", "Wrong number of operands", this.LineNumber, this.SourcePath);

                // Check the operator expression is closed.
                if (expression.Operator.SecondaryToken != null && expression.SecondTokenEncountered == false)
                    throw new JavaScriptException(this.engine, "SyntaxError", string.Format("Missing closing token '{0}'", expression.Operator.SecondaryToken.Text), this.LineNumber, this.SourcePath);

                // Check the child nodes.
                for (int i = 0; i < expression.OperandCount; i++)
                    stack.Push(expression.GetRawOperand(i));
            }
        }
Beispiel #5
0
        /// <summary>
        /// Declares a variable or function in this scope.  This will be initialized with the value
        /// of the given expression.
        /// </summary>
        /// <param name="name"> The name of the variable. </param>
        /// <param name="valueAtTopOfScope"> The value of the variable at the top of the scope.
        /// Can be <c>null</c> to indicate the variable does not need initializing. </param>
        /// <param name="writable"> <c>true</c> if the variable can be modified; <c>false</c>
        /// otherwise.  Defaults to <c>true</c>. </param>
        /// <param name="deletable"> <c>true</c> if the variable can be deleted; <c>false</c>
        /// otherwise.  Defaults to <c>true</c>. </param>
        /// <returns> A reference to the variable that was declared. </returns>
        internal virtual DeclaredVariable DeclareVariable(string name, Expression valueAtTopOfScope = null, bool writable = true, bool deletable = false)
        {
            if (name == null)
                throw new ArgumentNullException("name");

            // If variables cannot be declared in the scope, try the parent scope instead.
            if (this.CanDeclareVariables == false)
            {
                if (this.ParentScope == null)
                    throw new InvalidOperationException("Invalid scope chain.");
                return this.ParentScope.DeclareVariable(name, valueAtTopOfScope, writable, deletable);
            }

            DeclaredVariable variable;
            this.variables.TryGetValue(name, out variable);
            if (variable == null)
            {
                // This is a local variable that has not been declared before.
                variable = new DeclaredVariable() { Scope = this, Index = this.variables.Count, Name = name, Writable = writable, Deletable = deletable };
                this.variables.Add(name, variable);
            }

            // Set the initial value, if one was provided.
            if (valueAtTopOfScope != null)
            {
                // Function expressions override literals.
                if ((valueAtTopOfScope is LiteralExpression && variable.ValueAtTopOfScope is FunctionExpression) == false)
                    variable.ValueAtTopOfScope = valueAtTopOfScope;
            }

            return variable;
        }
 /// <summary>
 /// Creates a simple variable assignment expression.
 /// </summary>
 /// <param name="scope"> The scope the variable is defined within. </param>
 /// <param name="name"> The name of the variable to set. </param>
 /// <param name="value"> The value to set the variable to. </param>
 public AssignmentExpression(Scope scope, string name, Expression value)
     : base(Operator.Assignment)
 {
     this.Push(new NameExpression(scope, name));
     this.Push(value);
 }
 /// <summary>
 /// Creates a new instance of BinaryJSExpression.
 /// </summary>
 /// <param name="operator"> The binary operator to base this expression on. </param>
 /// <param name="left"> The operand on the left side of the operator. </param>
 /// <param name="right"> The operand on the right side of the operator. </param>
 public BinaryExpression(Operator @operator, Expression left, Expression right)
     : base(@operator)
 {
     this.Push(left);
     this.Push(right);
 }
Beispiel #8
0
 /// <summary>
 /// Creates a new object scope for use inside a with statement.
 /// </summary>
 /// <param name="parentScope"> A reference to the parent scope.  Can not be <c>null</c>. </param>
 /// <param name="scopeObject"> An expression that evaluates to the object to use. </param>
 /// <returns> A new ObjectScope instance. </returns>
 internal static ObjectScope CreateWithScope(Scope parentScope, Expression scopeObject)
 {
     if (parentScope == null)
         throw new ArgumentException("With scopes must have a parent scope.");
     return new ObjectScope(parentScope) { ScopeObjectExpression = scopeObject, ProvidesImplicitThisValue = true, CanDeclareVariables = false };
 }
 /// <summary>
 /// Adds an operand.
 /// </summary>
 /// <param name="operand"> The expression representing the operand to add. </param>
 public void Push(Expression operand)
 {
     if (this.OperandCount >= this.operands.Length)
         throw new InvalidOperationException("Too many operands.");
     this.operands[this.OperandCount] = operand;
     this.OperandCount ++;
 }