예제 #1
0
        ParseTreeNode FunctionCall()
        {
            FunctionParseTreeNode node = new FunctionParseTreeNode();

            if (!tokens.HasNext())
            {
                throw new Exception("Synax error: Expecting function identifieri at token " + tokens.Position);
            }

            node.Token = tokens.Forward();

            if (!tokens.HasNext() || tokens.PeekForward().TokenType != TokenIdentifier.TokenType.LeftParenthesis)
            {
                throw new Exception("Synax error: Expecting function identifieri at token " + tokens.Position);
            }

            tokens.Forward();

            bool expect = false;

            while (tokens.HasNext())
            {
                if (tokens.PeekForward().TokenType == TokenIdentifier.TokenType.RightParenthesis)
                {
                    tokens.Forward();
                    return(node);
                }

                if (expect && tokens.PeekForward().TokenType == TokenIdentifier.TokenType.ParamSeparator)
                {
                    tokens.Forward();
                    expect = false;
                }
                else
                {
                    node.Parameters.Add(Expr());
                    expect = true;
                }
            }

            throw new Exception("Syntax error: Expecting function end ')' at token " + tokens.Position);
        }
예제 #2
0
        private double Evaluate(ParseTreeNode node)
        {
            if (node is LeftOperatorNode)
            {
                // left operators
                if (node.Token.TokenType == TokenIdentifier.TokenType.MinusOperator)
                {
                    // minus
                    return(-Evaluate(((LeftOperatorNode)node).Next));
                }
                else if (node.Token.TokenType == TokenIdentifier.TokenType.NegationOperator)
                {
                    // negation
                    return(~(long)Evaluate(((LeftOperatorNode)node).Next));
                }
                else
                {
                    // factorial
                    double value    = Evaluate(((LeftOperatorNode)node).Next);
                    double newValue = 1;
                    while (value > 1)
                    {
                        newValue *= value--;
                    }
                    return(newValue);
                }
            }
            else if (node is FunctionParseTreeNode)
            {
                // we have a function
                FunctionParseTreeNode n = (FunctionParseTreeNode)node;
                string name             = ((IdentifierToken)n.Token).Identifier;
                if (functions.ContainsKey(name))
                {
                    if (n.Parameters.Count < functions[name].MinArgs)
                    {
                        throw new Exception("The function needs at least " + functions[name].MinArgs + " argument(s).");
                    }

                    double[] parValues = new double[n.Parameters.Count];
                    for (int i = 0; i < n.Parameters.Count; i++)
                    {
                        parValues[i] = Evaluate(n.Parameters[i]);
                    }

                    return(functions[name].FunctionCallback(parValues));
                }
                else
                {
                    throw new Exception("The function '" + name + "' does not exist.");
                }
            }
            else
            {
                if (node.Left != null)
                {
                    // we have an operator
                    double first  = Evaluate(node.Left);
                    double second = Evaluate(node.Right);

                    switch (node.Token.TokenType)
                    {
                    case TokenIdentifier.TokenType.MinusOperator: return(first - second);

                    case TokenIdentifier.TokenType.PlussOperator: return(first + second);

                    case TokenIdentifier.TokenType.MultiplicationOperator: return(first * second);

                    case TokenIdentifier.TokenType.DivisionOperator: return(first / second);

                    case TokenIdentifier.TokenType.ModuloOperator: return(first % second);

                    case TokenIdentifier.TokenType.AndOperator: return((int)first & (int)second);

                    case TokenIdentifier.TokenType.XorOperator: return((int)first ^ (int)second);

                    case TokenIdentifier.TokenType.OrOperator: return((int)first | (int)second);

                    case TokenIdentifier.TokenType.ShiftLeftOperator: return((int)first << (int)second);

                    case TokenIdentifier.TokenType.ShiftRightOperator: return((int)first >> (int)second);

                    case TokenIdentifier.TokenType.PowerOperator: return(Math.Pow(first, int.Parse(second.ToString())));
                    }
                }
                else if (node.Token.TokenType == TokenIdentifier.TokenType.Identifier)
                {
                    // we have a variable name
                    string name = ((IdentifierToken)node.Token).Identifier;
                    if (variables.ContainsKey(name))
                    {
                        return(variables[name]);
                    }
                    else
                    {
                        throw new Exception("There exists no variables with the name '" + name + "'.");
                    }
                }

                return(((NumberToken)node.Token).Value);
            }
        }