Example #1
0
File: Node.cs Project: TienLg/BetS
        /// <summary>
        /// Creates a Node containing the specified Operator and argument.
        /// This will automatically mark this Node as a TYPE_EXPRESSION
        /// </summary>
        /// <param name="_operator">the string representing an operator</param>
        /// <param name="_arg1">the argument to the specified operator</param>
        internal Node(Operator op, Node arg1)
        {
            this.arg1 = arg1;
            this.op = op;
            this.args = 1;

            this.type = NodeType.Expression;
        }
Example #2
0
        /// <summary>
        /// Parses an infix String expression and creates a parse tree of Node's.
        /// </summary>
        /// <remarks>
        /// This is the heart of the parser, it takes a normal infix expression and creates
        /// a tree datastructure we can easily recurse when evaluating.
        /// </remarks>
        /// <param name="exp">the infix string expression to process</param>
        /// <returns>A tree datastructure of Node objects representing the expression</returns>
        private Node ParseInfix(string exp)
        {
            int i, ma, len;
            string farg, sarg, fop;
            Node tree = null;

            farg = sarg = fop = "";
            ma = i = 0;

            len = exp.Length;

            if (len == 0)
            {
                throw new ParserException("Wrong number of arguments to operator");
            }
            else if (exp[0] == '(' && ((ma = match(exp, 0)) == (len - 1)))
            {
                return (ParseInfix(exp.Substring(1, ma - 1)));
            }
            else if (isVariable(exp))
            {
                // If built in constant put in value otherwise the variable
                if (constants.ContainsKey(exp)) return new Node((double)constants[exp]);
                else return new Node(exp);
            }
            else if (isConstant(exp))
            {
                try
                {
                    return (new Node(Double.Parse(exp, NumberStyles.Any, culture)));
                }
                catch (FormatException)
                {
                    throw new ParserException("Syntax error-> " + exp + " (not using regional decimal separator?)");
                }
            }

            while (i < len)
            {
                if ((fop = getOp(exp, i)) == null)
                {
                    farg = arg(null, exp, i);
                    fop = getOp(exp, i + farg.Length);

                    if (fop == null) throw new Exception("Missing operator");

                    if (isTwoArgOp(fop))
                    {
                        sarg = arg(fop, exp, i + farg.Length + fop.Length);
                        if (sarg.Equals("")) throw new Exception("Wrong number of arguments to operator " + fop);
                        tree = new Node(operators[fop], ParseInfix(farg), ParseInfix(sarg));
                        i += farg.Length + fop.Length + sarg.Length;
                    }
                    else
                    {
                        if (farg.Equals("")) throw new Exception("Wrong number of arguments to operator " + fop);
                        tree = new Node(operators[fop], ParseInfix(farg));
                        i += farg.Length + fop.Length;
                    }
                }
                else
                {
                    if (isTwoArgOp(fop))
                    {
                        farg = arg(fop, exp, i + fop.Length);
                        if (farg.Equals("")) throw new Exception("Wrong number of arguments to operator " + fop);
                        if (tree == null)
                        {
                            if (fop.Equals("+") || fop.Equals("-"))
                            {
                                tree = new Node(0D);
                            }
                            else throw new Exception("Wrong number of arguments to operator " + fop);
                        }
                        tree = new Node(operators[fop], tree, ParseInfix(farg));
                        i += farg.Length + fop.Length;
                    }
                    else
                    {
                        farg = arg(fop, exp, i + fop.Length);
                        if (farg.Equals("")) throw new Exception("Wrong number of arguments to operator " + fop);
                        tree = new Node(operators[fop], ParseInfix(farg));
                        i += farg.Length + fop.Length;
                    }
                }
            }

            return tree;
        }
Example #3
0
        /// <summary>
        /// Retrieves the value associated with the variable in the node
        /// </summary>
        /// <param name="node">node of type NodeType.Variable</param>
        /// <returns>value associated with variable</returns>
        private Value GetValue(Node node)
        {
            Value value;

            if (node.Value != null
                && node.Value.Type != ValueType.Invalid)
            {
                // Value already in node
                value = node.Value;
            }
            else
            {
                if (!htbl.TryGetValue(node.Variable, out value))
                {
                    throw new ParserException("No value associated with " + node.Variable);
                }

                // Save value reference in the node for next time
                node.Value = value;
            }

            return value;
        }
Example #4
0
        /// <summary>
        /// Traverses and evaluates the datastructure
        /// </summary>
        /// <param name="tree">tree as a structure of Node(s)</param>
        /// <returns>resulting double value</returns>
        internal double EvalTree(Node tree)
        {
            string tmp;

            if (tree.Type == NodeType.Value)
            {
                return (tree.Value.ToDouble());
            }
            else if (tree.Type == NodeType.Variable)
            {
                // get value associated with variable
                Value value = GetValue(tree);

                if (value.Type == ValueType.String
                    && cachedExpressions.ContainsKey(value.ToString(culture))) // cached expression
                {
                    return EvalExpression(cachedExpressions[value.ToString(culture)]);
                }
                else if (value.Type == ValueType.Constant) // constant value
                {
                    return value.ToDouble(culture);
                }
                else
                {
                    // apparently a nested expression, parse and cache
                    htbl[tree.Variable] = new StringValue() { Value = value.ToString(culture) };

                    tmp = value.ToString(culture);
                    Expression expression = treeParser.Parse(tmp);

                    cachedExpressions.Add(tmp, expression);

                    return EvalExpression(expression);
                }
            }

            return tree.Operator.Eval(this, tree.FirstArgument, tree.SecondArgument);
        }