Exemple #1
0
        private Argument[] ConstructArguments(ref ASTNode node)
        {
            List <Argument> args = new List <Argument>();

            node = node.Next();

            while (node != null)
            {
                switch (node.Type)
                {
                case ASTNodeType.AND:
                case ASTNodeType.OR:
                case ASTNodeType.EQUAL:
                case ASTNodeType.NOT_EQUAL:
                case ASTNodeType.LESS_THAN:
                case ASTNodeType.LESS_THAN_OR_EQUAL:
                case ASTNodeType.GREATER_THAN:
                case ASTNodeType.GREATER_THAN_OR_EQUAL:
                    return(args.ToArray());
                }

                args.Add(new Argument(this, node));

                node = node.Next();
            }

            return(args.ToArray());
        }
Exemple #2
0
        private ASTNode EvaluateModifiers(ASTNode node, out bool quiet, out bool force, out bool not)
        {
            quiet = false;
            force = false;
            not   = false;

            while (true)
            {
                switch (node.Type)
                {
                case ASTNodeType.QUIET:
                    quiet = true;
                    break;

                case ASTNodeType.FORCE:
                    force = true;
                    break;

                case ASTNodeType.NOT:
                    not = true;
                    break;

                default:
                    return(node);
                }

                node = node.Next();
            }
        }
        private bool EvaluateBinaryExpression(ref ASTNode node)
        {
            // Evaluate the left hand side
            var lhs = EvaluateBinaryOperand(ref node);

            // Capture the operator
            var op = node.Type;

            node = node.Next();

            // Evaluate the right hand side
            var rhs = EvaluateBinaryOperand(ref node);

            return(CompareOperands(op, lhs, rhs));
        }
Exemple #4
0
        static void PrintNode(ASTNode node, int indent)
        {
            while (node != null)
            {
                if (node.Lexeme.Length > 0)
                {
                    Console.WriteLine("{0}{1} {2}", "".PadLeft(indent * 4), node.Type, node.Lexeme);
                }
                else
                {
                    Console.WriteLine("{0}{1}", "".PadLeft(indent * 4), node.Type);
                }

                var child = node.FirstChild();

                if (child != null)
                {
                    PrintNode(child, indent + 1);
                }

                node = node.Next();
            }
        }
Exemple #5
0
        public bool ExecuteNext()
        {
            if (_statement == null)
            {
                return(false);
            }

            if (_statement.Type != ASTNodeType.STATEMENT)
            {
                throw new RunTimeError(_statement, "Invalid script");
            }

            var node = _statement.FirstChild();

            if (node == null)
            {
                throw new RunTimeError(_statement, "Invalid statement");
            }

            int depth = 0;

            switch (node.Type)
            {
            case ASTNodeType.IF:
            {
                PushScope(node);

                var expr   = node.FirstChild();
                var result = EvaluateExpression(ref expr);

                // Advance to next statement
                _statement = _statement.Next();

                // Evaluated true. Jump right into execution.
                if (result)
                {
                    break;
                }

                // The expression evaluated false, so keep advancing until
                // we hit an elseif, else, or endif statement that matches
                // and try again.
                depth = 0;

                while (_statement != null)
                {
                    node = _statement.FirstChild();

                    if (node.Type == ASTNodeType.IF)
                    {
                        depth++;
                    }
                    else if (node.Type == ASTNodeType.ELSEIF)
                    {
                        if (depth == 0)
                        {
                            expr   = node.FirstChild();
                            result = EvaluateExpression(ref expr);

                            // Evaluated true. Jump right into execution
                            if (result)
                            {
                                _statement = _statement.Next();
                                break;
                            }
                        }
                    }
                    else if (node.Type == ASTNodeType.ELSE)
                    {
                        if (depth == 0)
                        {
                            // Jump into the else clause
                            _statement = _statement.Next();
                            break;
                        }
                    }
                    else if (node.Type == ASTNodeType.ENDIF)
                    {
                        if (depth == 0)
                        {
                            break;
                        }

                        depth--;
                    }

                    _statement = _statement.Next();
                }

                if (_statement == null)
                {
                    throw new RunTimeError(node, "If with no matching endif");
                }

                break;
            }

            case ASTNodeType.ELSEIF:
                // If we hit the elseif statement during normal advancing, skip over it. The only way
                // to execute an elseif clause is to jump directly in from an if statement.
                depth = 0;

                while (_statement != null)
                {
                    node = _statement.FirstChild();

                    if (node.Type == ASTNodeType.IF)
                    {
                        depth++;
                    }
                    else if (node.Type == ASTNodeType.ENDIF)
                    {
                        if (depth == 0)
                        {
                            break;
                        }

                        depth--;
                    }

                    _statement = _statement.Next();
                }

                if (_statement == null)
                {
                    throw new RunTimeError(node, "If with no matching endif");
                }

                break;

            case ASTNodeType.ENDIF:
                PopScope();
                _statement = _statement.Next();
                break;

            case ASTNodeType.ELSE:
                // If we hit the else statement during normal advancing, skip over it. The only way
                // to execute an else clause is to jump directly in from an if statement.
                depth = 0;

                while (_statement != null)
                {
                    node = _statement.FirstChild();

                    if (node.Type == ASTNodeType.IF)
                    {
                        depth++;
                    }
                    else if (node.Type == ASTNodeType.ENDIF)
                    {
                        if (depth == 0)
                        {
                            break;
                        }

                        depth--;
                    }

                    _statement = _statement.Next();
                }

                if (_statement == null)
                {
                    throw new RunTimeError(node, "If with no matching endif");
                }

                break;

            case ASTNodeType.WHILE:
            {
                // When we first enter the loop, push a new scope
                if (_scope.StartNode != node)
                {
                    PushScope(node);
                }

                var expr   = node.FirstChild();
                var result = EvaluateExpression(ref expr);

                // Advance to next statement
                _statement = _statement.Next();

                // The expression evaluated false, so keep advancing until
                // we hit an endwhile statement.
                if (!result)
                {
                    depth = 0;

                    while (_statement != null)
                    {
                        node = _statement.FirstChild();

                        if (node.Type == ASTNodeType.WHILE)
                        {
                            depth++;
                        }
                        else if (node.Type == ASTNodeType.ENDWHILE)
                        {
                            if (depth == 0)
                            {
                                PopScope();
                                // Go one past the endwhile so the loop doesn't repeat
                                _statement = _statement.Next();
                                break;
                            }

                            depth--;
                        }

                        _statement = _statement.Next();
                    }
                }
                break;
            }

            case ASTNodeType.ENDWHILE:
                // Walk backward to the while statement
                _statement = _statement.Prev();

                depth = 0;

                while (_statement != null)
                {
                    node = _statement.FirstChild();

                    if (node.Type == ASTNodeType.ENDWHILE)
                    {
                        depth++;
                    }
                    else if (node.Type == ASTNodeType.WHILE)
                    {
                        if (depth == 0)
                        {
                            break;
                        }

                        depth--;
                    }

                    _statement = _statement.Prev();
                }

                if (_statement == null)
                {
                    throw new RunTimeError(node, "Unexpected endwhile");
                }

                break;

            case ASTNodeType.FOR:
            {
                // The iterator variable's name is the hash code of the for loop's ASTNode.
                var iterName = node.GetHashCode().ToString();

                // When we first enter the loop, push a new scope
                if (_scope.StartNode != node)
                {
                    PushScope(node);

                    // Grab the arguments
                    var max = node.FirstChild();

                    if (max.Type != ASTNodeType.INTEGER)
                    {
                        throw new RunTimeError(max, "Invalid for loop syntax");
                    }

                    // Create a dummy argument that acts as our loop variable
                    var iter = new ASTNode(ASTNodeType.INTEGER, "0", node, 0);

                    _scope.SetVar(iterName, new Argument(this, iter));
                }
                else
                {
                    // Increment the iterator argument
                    var arg = _scope.GetVar(iterName);

                    var iter = new ASTNode(ASTNodeType.INTEGER, (arg.AsUInt() + 1).ToString(), node, 0);

                    _scope.SetVar(iterName, new Argument(this, iter));
                }

                // Check loop condition
                var i = _scope.GetVar(iterName);

                // Grab the max value to iterate to
                node = node.FirstChild();
                var end = new Argument(this, node);

                if (i.AsUInt() < end.AsUInt())
                {
                    // enter the loop
                    _statement = _statement.Next();
                }
                else
                {
                    // Walk until the end of the loop
                    _statement = _statement.Next();

                    depth = 0;

                    while (_statement != null)
                    {
                        node = _statement.FirstChild();

                        if (node.Type == ASTNodeType.FOR ||
                            node.Type == ASTNodeType.FOREACH)
                        {
                            depth++;
                        }
                        else if (node.Type == ASTNodeType.ENDFOR)
                        {
                            if (depth == 0)
                            {
                                PopScope();
                                // Go one past the end so the loop doesn't repeat
                                _statement = _statement.Next();
                                break;
                            }

                            depth--;
                        }

                        _statement = _statement.Next();
                    }
                }
            }
            break;

            case ASTNodeType.FOREACH:
            {
                // foreach VAR in LIST
                // The iterator's name is the hash code of the for loop's ASTNode.
                var varName  = node.FirstChild().Lexeme;
                var listName = node.FirstChild().Next().Lexeme;
                var iterName = node.GetHashCode().ToString();

                // When we first enter the loop, push a new scope
                if (_scope.StartNode != node)
                {
                    PushScope(node);

                    // Create a dummy argument that acts as our iterator object
                    var iter = new ASTNode(ASTNodeType.INTEGER, "0", node, 0);
                    _scope.SetVar(iterName, new Argument(this, iter));

                    // Make the user-chosen variable have the value for the front of the list
                    var arg = Interpreter.GetListValue(listName, 0);

                    if (arg != null)
                    {
                        _scope.SetVar(varName, arg);
                    }
                    else
                    {
                        _scope.ClearVar(varName);
                    }
                }
                else
                {
                    // Increment the iterator argument
                    var idx  = _scope.GetVar(iterName).AsInt() + 1;
                    var iter = new ASTNode(ASTNodeType.INTEGER, idx.ToString(), node, 0);
                    _scope.SetVar(iterName, new Argument(this, iter));

                    // Update the user-chosen variable
                    var arg = Interpreter.GetListValue(listName, idx);

                    if (arg != null)
                    {
                        _scope.SetVar(varName, arg);
                    }
                    else
                    {
                        _scope.ClearVar(varName);
                    }
                }

                // Check loop condition
                var i = _scope.GetVar(varName);

                if (i != null)
                {
                    // enter the loop
                    _statement = _statement.Next();
                }
                else
                {
                    // Walk until the end of the loop
                    _statement = _statement.Next();

                    depth = 0;

                    while (_statement != null)
                    {
                        node = _statement.FirstChild();

                        if (node.Type == ASTNodeType.FOR ||
                            node.Type == ASTNodeType.FOREACH)
                        {
                            depth++;
                        }
                        else if (node.Type == ASTNodeType.ENDFOR)
                        {
                            if (depth == 0)
                            {
                                PopScope();
                                // Go one past the end so the loop doesn't repeat
                                _statement = _statement.Next();
                                break;
                            }

                            depth--;
                        }

                        _statement = _statement.Next();
                    }
                }
                break;
            }

            case ASTNodeType.ENDFOR:
                // Walk backward to the for statement
                _statement = _statement.Prev();

                while (_statement != null)
                {
                    node = _statement.FirstChild();

                    if (node.Type == ASTNodeType.FOR ||
                        node.Type == ASTNodeType.FOREACH)
                    {
                        break;
                    }

                    _statement = _statement.Prev();
                }

                if (_statement == null)
                {
                    throw new RunTimeError(node, "Unexpected endfor");
                }

                break;

            case ASTNodeType.BREAK:
                // Walk until the end of the loop
                _statement = _statement.Next();

                depth = 0;

                while (_statement != null)
                {
                    node = _statement.FirstChild();

                    if (node.Type == ASTNodeType.WHILE ||
                        node.Type == ASTNodeType.FOR ||
                        node.Type == ASTNodeType.FOREACH)
                    {
                        depth++;
                    }
                    else if (node.Type == ASTNodeType.ENDWHILE ||
                             node.Type == ASTNodeType.ENDFOR)
                    {
                        if (depth == 0)
                        {
                            PopScope();

                            // Go one past the end so the loop doesn't repeat
                            _statement = _statement.Next();
                            break;
                        }

                        depth--;
                    }

                    _statement = _statement.Next();
                }

                PopScope();
                break;

            case ASTNodeType.CONTINUE:
                // Walk backward to the loop statement
                _statement = _statement.Prev();

                depth = 0;

                while (_statement != null)
                {
                    node = _statement.FirstChild();

                    if (node.Type == ASTNodeType.ENDWHILE ||
                        node.Type == ASTNodeType.ENDFOR)
                    {
                        depth++;
                    }
                    else if (node.Type == ASTNodeType.WHILE ||
                             node.Type == ASTNodeType.FOR ||
                             node.Type == ASTNodeType.FOREACH)
                    {
                        if (depth == 0)
                        {
                            break;
                        }

                        depth--;
                    }

                    _statement = _statement.Prev();
                }

                if (_statement == null)
                {
                    throw new RunTimeError(node, "Unexpected continue");
                }
                break;

            case ASTNodeType.STOP:
                _statement = null;
                break;

            case ASTNodeType.REPLAY:
                _statement = _statement.Parent.FirstChild();
                break;

            case ASTNodeType.QUIET:
            case ASTNodeType.FORCE:
            case ASTNodeType.COMMAND:
                if (ExecuteCommand(node))
                {
                    _statement = _statement.Next();
                }

                break;
            }

            return((_statement != null) ? true : false);
        }
Exemple #6
0
        private bool EvaluateBinaryExpression(ref ASTNode node)
        {
            // Evaluate the left hand side
            var lhs = EvaluateBinaryOperand(ref node);

            // Capture the operator
            var op = node.Type;

            node = node.Next();

            // Evaluate the right hand side
            var rhs = EvaluateBinaryOperand(ref node);

            if (lhs.GetType() != rhs.GetType())
            {
                // Different types. Try to convert one to match the other.

                // Special case for rhs doubles because we don't want to lose precision.
                if (rhs is double)
                {
                    double tmp = (double)lhs;
                    lhs = tmp;
                }
                else
                {
                    var tmp = Convert.ChangeType(rhs, lhs.GetType());
                    rhs = (IComparable)tmp;
                }
            }

            try
            {
                // Evaluate the whole expression
                switch (op)
                {
                case ASTNodeType.EQUAL:
                    return(lhs.CompareTo(rhs) == 0);

                case ASTNodeType.NOT_EQUAL:
                    return(lhs.CompareTo(rhs) != 0);

                case ASTNodeType.LESS_THAN:
                    return(lhs.CompareTo(rhs) < 0);

                case ASTNodeType.LESS_THAN_OR_EQUAL:
                    return(lhs.CompareTo(rhs) <= 0);

                case ASTNodeType.GREATER_THAN:
                    return(lhs.CompareTo(rhs) > 0);

                case ASTNodeType.GREATER_THAN_OR_EQUAL:
                    return(lhs.CompareTo(rhs) >= 0);
                }
            }
            catch (ArgumentException e)
            {
                throw new RunTimeError(node, e.Message);
            }

            throw new RunTimeError(node, "Unknown operator in expression");
        }
 public void Advance()
 {
     Interpreter.ClearTimeout();
     _statement = _statement.Next();
 }