コード例 #1
0
        private void term(int opSetIndex, IFLContext context)
        {
            //If this is the end of the operator set chain, get the operand already.
            if (opSetIndex == 0)
            {
                bool negate = matcher.Value == UnaryMinus;

                if (negate)
                {
                    nextToken();
                }

                factor(context);

                if (negate)
                {
                    evalStack.Push(-(double)evalStack.Pop());
                }
            }
            else
            {
                //Otherwise, execute the higher operator first.
                expression(opSetIndex - 1, context);
            }
        }
コード例 #2
0
        private int functionCall(IFLContext context)
        {
            //Count the arguments of this function.
            int argumentCount = 0;

            //See if we even need to loop through the expressions.
            bool rightParenthesisEncountered = accept(TokenType.RightParenthesis);

            while (!rightParenthesisEncountered)
            {
                //Get the expression which will be used as an argument.
                expression(context);

                //Accept a comma, in the case of another argument.
                if (accept(TokenType.Comma))
                {
                    //The token position has already advanced, there's no need to do anything.
                }
                else if (expect(TokenType.RightParenthesis))
                {
                    //Otherwise, the only other character acceptable is the right parenthesis.

                    //This statement will break out of the loop.
                    rightParenthesisEncountered = true;
                }

                argumentCount++;
            }

            return(argumentCount);
        }
コード例 #3
0
        private void callOperator(IFLContext context, string opName, object rightOperand, object leftOperand)
        {
            object result;

            if (opName == AsOperator)
            {
                result = context.TypeConvert(Convert.ToString(rightOperand), leftOperand);
            }
            else
            {
                result = context.Operate(opName, leftOperand, rightOperand);
            }

            evalStack.Push(result);
        }
コード例 #4
0
        /// <summary>
        ///     Executes the given piece of FL code.
        /// </summary>
        /// <param name="flString">FL code to execute.</param>
        /// <exception cref="GSC.FunctionLanguage.Exceptions.UnexpectedEndException">Thrown when the stream or string ends before all scopes are terminated.</exception>
        /// <exception cref="GSC.FunctionLanguage.Exceptions.UnexpectedTokenException">Thrown when a token appears where it is not expected.</exception>
        public object Execute(string flString, IFLContext context)
        {
            //Empty the evaluation stack, in case another execution call filled it up.
            evalStack.Clear();

            //Start a matcher to tokenize the string.
            matcher = Regex.Match(flString, createRegexString());
            profileCurrentMatch();
            expression(context);

            if (matcher.Success)
            {
                throw new UnexpectedTokenException(matcher.Value, matcher.Index);
            }

            return(evalStack.Pop());
        }
コード例 #5
0
        /// <summary>
        ///     Gets the value of one of the operands of an operation, or just gets the value.
        /// </summary>
        private void factor(IFLContext context)
        {
            //Identifiers/strings can be either a function call or just an argument.
            if (currentTokenType == TokenType.StringIdentifier)
            {
                bool   currentTokenIsString = isString();
                string token = advanceAndKeep();

                //It's a function call.
                if (accept(TokenType.LeftParenthesis))
                {
                    //Get all the arguments of the function call.
                    int argumentCount = functionCall(context);

                    //Execute the function within the context.
                    executeFunction(context, false, token, argumentCount);
                }
                else
                {
                    //It's not a function call, just push it onto the evaluation stack.
                    double result;

                    //If this is not explicitly a string, perhaps we can parse it as a number.
                    if (!currentTokenIsString && double.TryParse(token, out result))
                    {
                        evalStack.Push(result);
                    }
                    else
                    {
                        //We can't. Just keep it as a string.
                        evalStack.Push(token);
                    }
                }
            }
            //This is an expectation, as there should be no others.
            else if (expect(TokenType.LeftParenthesis))
            {
                //Get the expression inside the parentheses.
                expression(context);

                //Now that we have an expresssion, the next token must be a closing right parenthesis.
                expect(TokenType.RightParenthesis);
            }

            referencedCalls(context);
        }
コード例 #6
0
        private void expression(int opSetIndex, IFLContext context)
        {
            term(opSetIndex, context);

            while (compilerSettings.OperatorStack[opSetIndex].Contains(currentToken()))
            {
                string currentOp = currentToken();
                nextToken();

                term(opSetIndex, context);

                object rightOperand = evalStack.Pop();
                object leftOperand  = evalStack.Pop();

                callOperator(context, currentOp, rightOperand, leftOperand);
            }
        }
コード例 #7
0
        private void referencedCalls(IFLContext context)
        {
            //An expression can include the -> operator to reference the other within a function call.
            while (currentTokenType == TokenType.Operator && currentToken() == ObjectOperator)
            {
                nextToken();

                //Save the function name.
                string token = currentToken();

                //The next statement must be a function call.
                if (expect(TokenType.StringIdentifier) && expect(TokenType.LeftParenthesis))
                {
                    //Get all the arguments of the function call.
                    int argumentCount = functionCall(context);

                    //Call the function with this expression in the stack as the "this" object.
                    executeFunction(context, true, token, argumentCount);
                }
            }
        }
コード例 #8
0
        private void executeFunction(IFLContext context, bool getObjectReference, string functionName, int argumentCount)
        {
            object[] passedArguments = new object[argumentCount];

            //Load the arguments from the stack, in the order they were placed in.
            for (int i = passedArguments.Length - 1; i >= 0; i--)
            {
                passedArguments[i] = evalStack.Pop();
            }

            object objectReference = null;

            if (getObjectReference)
            {
                objectReference = evalStack.Pop();
            }

            //Call the function in the context.
            object returnValue = context.CallFunction(functionName, objectReference, passedArguments);

            //Push the return value back onto the stack.
            evalStack.Push(returnValue);
        }
コード例 #9
0
 private void expression(IFLContext context)
 {
     expression(compilerSettings.OperatorStack.Count - 1, context);
 }