vassilych / cscs

CSCS: Customized Scripting in C#

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Get Function Args

bakman23 opened this issue · comments

Hello,
is it possible to get a function arg by index ?

I would like create an IF function like excel.

IFELSE( [condition] , [if true action] , [if false action] )

the problem is, if I use GetFunctionArgs all args will be interpreted and this exemple "IFELSE( 1 != 1 , 1 / 0 , "ok")" the divided by zero will be catch.

the must will be to test fisrt param, if it return 0 the second param will not be interpreted only the third
Exemple
`

        //get condition
        var arg = script.GetFunctionArgByIndex(indexParam: 0);
        var condition = Utils.GetSafeString(arg, 0);
        if (condition == "1")
        {
            arg = script.GetFunctionArgsIndex(indexParam: 1);
            string actionIfTrue = Utils.GetSafeString(arg, 0);
            return new Variable(actionIfTrue);
        }
        else
        {
            arg = script.GetFunctionArgsIndex(indexParam: 2);
            string actionIfFalse = Utils.GetSafeString(arg, 0);
            return new Variable(actionIfFalse);
        }

`
I tried to create the GetFunctionArgsIndex and it work with this IFELSE( 1 != 1 , 1 / 0 , "ok") but not with that
IFELESE ( functA(x) * functB(y) != 0 , 3 - 10 * Round( 1 / 0 ) , Ceil(0.4))

`

public static List GetFunctionArgsIndex(ParsingScript script,
char start, char end, Action outList, int indexParam )
{
List args = new List();
bool isList = script.StillValid() && script.Current == Constants.START_GROUP;

        if (!script.StillValid() || script.Current == Constants.END_STATEMENT)
        {
            return args;
        }

        ParsingScript tempScript = script.GetTempScript(script.String, script.Pointer);

        if (script.Current != start && script.TryPrev() != start &&
           (script.Current == ' ' || script.TryPrev() == ' '))
        { // Allow functions with space separated arguments
            start = ' ';
            end = Constants.END_STATEMENT;
        }

        // ScriptingEngine - body is unsed (used in Debugging) but GetBodyBetween has sideeffects			

#pragma warning disable 219
string body = Utils.GetBodyBetween(tempScript, start, end);
#pragma warning restore 219
// After the statement above tempScript.Parent will point to the last
// character belonging to the body between start and end characters.

        int index = 0;

        while (script.Pointer < tempScript.Pointer)
        {

            if (index == indexParam)
            {

                Variable item = Utils.GetItem(script, false);
                args.Add(item);
                break;
            }
            else
            {
                Parser.Split(script, Constants.NEXT_OR_END_ARRAY);
            }
            
            if (script.Pointer < tempScript.Pointer)
            {
                script.MoveForwardIf(Constants.END_GROUP);
                script.MoveForwardIf(Constants.NEXT_ARG);
            }
            else if (script.Pointer > tempScript.Pointer)
            {
                script.MoveForwardIf(Constants.NEXT_ARG);
            }
            if (script.Pointer == tempScript.Pointer - 1)
            {
                script.MoveForwardIf(Constants.END_ARG, Constants.END_GROUP);
            }
            index++;
        }

        if (script.Pointer <= tempScript.Pointer)
        {
            // Eat closing parenthesis, if there is one, but only if it closes
            // the current argument list, not one after it. 
            script.MoveForwardIf(Constants.END_ARG, end);
        }

        script.MoveForwardIf(Constants.SPACE);
        //script.MoveForwardIf(Constants.SPACE, Constants.END_STATEMENT);
        outList(isList);
        return args;
    }

`

Can you help me, please ?

Hi,

What you can do is to use Utils.GetToken() function instead of GetFunctionArgs(). Here is an example:

string funcName = Utils.GetToken(script, Constants.NEXT_OR_END_ARRAY);

This function doesn't execute the parameters, i.e. it treats them as strings. So you will get next string in the list.
Unfortunately you have to call this function multiple times if you want to extract multiple parameters.
I am going to create a convenience method to get a list of all args.

Let me know if calling GetToken() multiple times can solve the issue for you. Note that as a separation token you can also use a space if needed.

Best, Vassili