Example #1
0
        public double ExecAst(IAstNode root)
        {
            switch (root)
            {
            case AstNumberNode numberNode:
                return(numberNode.Number);

            case AstVariableNode varNode:
                if (Constants.TryGetValue(varNode.Id, out var val))
                {
                    return(val);
                }
                else if (Variables.TryGetValue(varNode.Id, out val))
                {
                    return(val);
                }
                else
                {
                    if (Setting.DebugMode)
                    {
                        Sync.Tools.IO.CurrentIO.WriteColor($"[RTPP:Expression]No Variable found (return zero). Variable name: { varNode.Id }", ConsoleColor.Yellow);
                    }
                    return(0);
                }

            case AstOpNode opNode:
                switch (opNode.Op)
                {
                case "+":
                    return(ExecAst(opNode.LNode) + ExecAst(opNode.RNode));

                case "-":
                    return(ExecAst(opNode.LNode) - ExecAst(opNode.RNode));

                case "*":
                    return(ExecAst(opNode.LNode) * ExecAst(opNode.RNode));

                case "/":
                    return(ExecAst(opNode.LNode) / ExecAst(opNode.RNode));

                case "%":
                    return(ExecAst(opNode.LNode) % ExecAst(opNode.RNode));

                case "^":
                    return(Math.Pow(ExecAst(opNode.LNode), ExecAst(opNode.RNode)));

                case ">":
                    return((ExecAst(opNode.LNode) > ExecAst(opNode.RNode)) ? 1 : 0);

                case "<":
                    return((ExecAst(opNode.LNode) < ExecAst(opNode.RNode)) ? 1 : 0);

                case ">=":
                    return((ExecAst(opNode.LNode) >= ExecAst(opNode.RNode)) ? 1 : 0);

                case "<=":
                    return((ExecAst(opNode.LNode) <= ExecAst(opNode.RNode)) ? 1 : 0);

                case "==":
                    return(IsNotZero(ExecAst(opNode.LNode) - ExecAst(opNode.RNode)) ? 0 : 1);

                case "!=":
                    return(IsNotZero(ExecAst(opNode.LNode) - ExecAst(opNode.RNode)) ? 1 : 0);

                case "!":
                    return(IsNotZero(ExecAst(opNode.LNode)) ? 0 : 1);

                case "&&":
                    return((IsNotZero(ExecAst(opNode.LNode)) && IsNotZero(ExecAst(opNode.RNode))) ? 1 : 0);

                case "||":
                    return((IsNotZero(ExecAst(opNode.LNode)) || IsNotZero(ExecAst(opNode.RNode))) ? 1 : 0);
                }
                break;

            case AstFunctionNode funcNode:
                try
                {
                    if (funcNode.Id == "set")
                    {
                        AstVariableNode varNode = funcNode.Args[0] as AstVariableNode;
                        string          varName = varNode?.Id ?? throw new ExpressionException($"The \"{funcNode.Id}()\"  first parameter is the variable name.");

                        double varVal = ExecAst(funcNode.Args[1]);
                        Variables[varName] = varVal;
                        return(0);
                    }
                    else if (funcNode.Id == "if")
                    {
                        IAstNode condNode       = funcNode.Args[0];
                        double   condNodeResult = ExecAst(condNode);
                        if (Math.Abs(condNodeResult) <= 1e-5)
                        {
                            //false_expr
                            return(ExecAst(funcNode.Args[2]));
                        }
                        else
                        {
                            //true_expr
                            return(ExecAst(funcNode.Args[1]));
                        }
                    }
                    else if (funcNode.Id == "smooth")
                    {
                        AstVariableNode varNode = funcNode.Args[0] as AstVariableNode;
                        string          varName = varNode?.Id ?? throw new ExpressionException($"The \"{funcNode.Id}()\" first parameter is the variable name.");
                        double          varVal  = ExecAst(funcNode.Args[0]);

                        return(SmoothMath.SmoothVariable(varName, varVal));
                    }
                    else
                    {
                        if (Functions.TryGetValue(funcNode.Id, out var func))
                        {
                            return(func(ComputeArgs(funcNode.Args)));
                        }
                        else
                        {
                            throw new ExpressionException($"No function found. Fucntion: {funcNode.Id}");
                        }
                    }
                }
                catch (ArgumentOutOfRangeException)
                {
                    throw new ExpressionException($"The function is missing a parameter. Fucntion: {funcNode.Id}");
                }
            }
            return(Double.NaN);
        }
        public double ExecAst(IAstNode root)
        {
            switch (root)
            {
            case AstNumberNode numberNode:
                return(numberNode.Number);

            case AstVariableNode varNode:
                if (Constants.TryGetValue(varNode.Id, out var val))
                {
                    return(val);
                }
                else if (Variables.TryGetValue(varNode.Id, out val))
                {
                    return(val);
                }
                else
                {
                    Sync.Tools.IO.CurrentIO.WriteColor($"[RTPP:Expression]No Variable found (return zero). Variable name: { varNode.Id }", ConsoleColor.Yellow);
                    return(0);
                }

            case AstOpNode opNode:
                switch (opNode.Op)
                {
                case "+":
                    return(ExecAst(opNode.LNode) + ExecAst(opNode.RNode));

                case "-":
                    return(ExecAst(opNode.LNode) - ExecAst(opNode.RNode));

                case "*":
                    return(ExecAst(opNode.LNode) * ExecAst(opNode.RNode));

                case "/":
                    return(ExecAst(opNode.LNode) / ExecAst(opNode.RNode));

                case "^":
                    return(Math.Pow(ExecAst(opNode.LNode), ExecAst(opNode.RNode)));
                }
                break;

            case AstFunctionNode funcNode:
                try
                {
                    if (funcNode.Id == "set")
                    {
                        AstVariableNode varNode = funcNode.Args[0] as AstVariableNode;
                        string          varName = varNode?.Id ?? throw new ExpressionException("The first parameter is the variable name.");

                        double varVal = ExecAst(funcNode.Args[1]);
                        Variables[varName] = varVal;
                        return(0);
                    }
                    else
                    {
                        if (Functions.TryGetValue(funcNode.Id, out var func))
                        {
                            return(func(ComputeArgs(funcNode.Args)));
                        }
                        else
                        {
                            throw new ExpressionException($"No function found. Fucntion: {funcNode.Id}");
                        }
                    }
                }
                catch (ArgumentOutOfRangeException)
                {
                    throw new ExpressionException($"The function is missing a parameter. Fucntion: {funcNode.Id}");
                }
            }
            return(Double.NaN);
        }