public static IValueProvider[] ResolveTerms(this IMathContext context, string[] terms)
        {
            if (context == null)
            {
                if (terms != null && terms.Length != 0)
                {
                    throw new InvalidOperationException("Could not resolve terms with no math context provided");
                }

                return(null);
            }

            int termsCount = terms.Length;
            var providers  = new IValueProvider[termsCount];

            for (int i = 0; i < termsCount; i++)
            {
                string         term = terms[i];
                IValueProvider provider;
                if (!context.TryGetTerm(term, out provider))
                {
                    throw new InvalidOperationException(string.Format("Unable to find value for term \"{0}\"", term));
                }
                providers[i] = provider;
            }
            return(providers);
        }
Example #2
0
        private bool IsUnaryOperator(string current, string?prev, string?next)
        {
            IMathContext context = Context;

            if (!context.TryGetUnaryOperator(current, out var op))
            {
                return(false);
            }

            if (op.Notation == OperatorNotation.Prefix)
            {
                if (prev != null && (prev == ")" ||
                                     IsNumber(prev) ||
                                     context.IsVariableOrConstant(prev) ||
                                     (context.IsUnaryOperator(prev) && !context.IsBinaryOperator(prev))))
                {
                    return(false);
                }

                return(next != null && !IsValidOperator(next[0]) && (next == "(" || char.IsLetterOrDigit(next[0])));
            }
            else if (op.Notation == OperatorNotation.Postfix)
            {
                return(prev != null && (prev == ")" || IsNumber(prev) || context.IsVariableOrConstant(prev)));
            }
            else
            {
                return(false);
            }
        }
Example #3
0
        /// <summary>
        /// Evaluates the specified math expression.
        /// </summary>
        /// <param name="expression">The expression to evaluate.</param>
        /// <param name="context">The context used for extract the tokens.</param>
        /// <returns>The result of the evaluation</returns>
        public static double Evaluate(string expression, IMathContext context)
        {
            ITokenizer tokenizer = new Tokenizer(context);

            Token[] tokens = tokenizer.GetTokens(expression);
            Token[] rpn    = InfixToRPN(tokens);
            return(Evaluate(rpn, context));
        }
        private CompiledExpression(ExpressionSyntax syntax, IMathContext context = null)
        {
            Syntax  = syntax;
            Context = context;

            Intermediate      = IntermediateExpression.Compile(syntax, context);
            calculationBuffer = new MathValue[Intermediate.DistSize];
        }
Example #5
0
        private Token[] GetTokensInternal(string[] arr)
        {
            if (arr.Length == 0)
            {
                return(Array.Empty <Token>());
            }

            List <Token> tokens  = new List <Token>(arr.Length);
            IMathContext context = Context;
            int          length  = arr.Length;

            for (int i = 0; i < length; i++)
            {
                string current = arr[i];

                if (IsNumber(current))
                {
                    tokens.Add(new Token(current, TokenType.Number));
                }
                else if (context.IsVariableOrConstant(current))
                {
                    tokens.Add(new Token(current, TokenType.VariableOrConstant));
                }
                else if (context.IsFunction(current))
                {
                    tokens.Add(new Token(current, TokenType.Function));
                }
                else if (context.IsBinaryOperator(current) || context.IsUnaryOperator(current))
                {
                    string?prev = i > 0 ? arr[i - 1] : null;
                    string?next = i < length - 1 ? arr[i + 1] : null;

                    if (IsUnaryOperator(current, prev, next))
                    {
                        tokens.Add(new Token(current, TokenType.UnaryOperator));
                    }
                    else
                    {
                        tokens.Add(new Token(current, TokenType.BinaryOperator));
                    }
                }
                else if (current == "(" || current == ")")
                {
                    tokens.Add(Token.FromParenthesis(current[0]));
                }
                else if (current == ",")
                {
                    tokens.Add(Token.Comma);
                }
                else
                {
                    tokens.Add(new Token(current, TokenType.Unknown));
                }
            }

            return(tokens.ToArray());
        }
Example #6
0
        public static IReadOnlyCollection <string> GetVariables(this string input, IMathContext context)
        {
            ITokenizer tokenzier = new Tokenizer(input);
            IParser    parser    = new Parser(tokenzier, context);

            // Populate the variables collection
            parser.Parse();

            return(parser.Variables);
        }
Example #7
0
        /// <summary>Creates a new instance of an operation info.</summary>
        /// <param name="expression">The math expression.</param>
        /// <param name="context">The math context.</param>
        /// <returns>An operation info.</returns>
        internal static OperationInfo Create(string expression, IMathContext context)
        {
            ITokenizer tokenizer = new Tokenizer(expression);
            IParser    parser    = new Parser(tokenizer, context);
            IExpressionVisitor <IExpression> optimizer = new ExpressionOptimizer(context);
            IExpression root      = parser.Parse();
            IExpression optimized = optimizer.Visit(root);

            return(new OperationInfo(optimized, expression, parser.Variables));
        }
Example #8
0
        /// <summary>Create an instance of a <see cref="Calculator"/> which has it's own operators and variables.</summary>
        /// <param name="context">The math context.</param>
        /// <param name="variables">A collection of variables.</param>
        public Calculator(IMathContext context, IVariablesCollection?variables = default)
        {
            context.EnsureNotNull(nameof(context));

            _mathContext = context;
            _evaluator   = new ExpressionEvaluator(_mathContext, this);

            this["PI"] = Math.PI;
            this["E"]  = Math.E;

            variables?.CopyTo(this);
        }
Example #9
0
        /// <summary>Initializez a new instance of an expression optimizer.</summary>
        /// <param name="mathContext">The math context used to evaluate expressions.</param>
        public ExpressionOptimizer(IMathContext mathContext)
        {
            mathContext.EnsureNotNull(nameof(mathContext));
            _context = mathContext;

            _expressionOptimizers = new Dictionary <ExpressionType, Func <IExpression, IExpression> >
            {
                [ExpressionType.BinaryExpression]   = OptimizeBinaryExpression,
                [ExpressionType.UnaryExpression]    = EvaluateUnaryExpression,
                [ExpressionType.ConstantExpression] = OptimizeConstantExpression,
                [ExpressionType.GroupingExpression] = OptimizeGroupingExpression,
                [ExpressionType.VariableExpression] = SkipExpressionOptimization,
                [ExpressionType.ValueExpression]    = SkipExpressionOptimization
            };
        }
        /// <summary>
        /// <para>Compiles a new <see cref="IntermediateExpression"/> from a source <see cref="ExpressionSyntax"/>.</para>
        /// </summary>
        /// <param name="syntax">The parsed string that describes an expression to compile.</param>
        /// <param name="context">The compilation context.</param>
        /// <returns></returns>
        public static IntermediateExpression Compile(ExpressionSyntax syntax, IMathContext context = null)
        {
            var buffer = CompilerBuffers.New();

            CompileSpan(buffer, syntax, 0, syntax.Tokens.Length);

            return(new IntermediateExpression()
            {
                Operations = buffer.Operations.ToArray(),
                Static = buffer.Src.ToArray(),
                DistSize = buffer.Dist.Count,
                Import = context.ResolveTerms(syntax.Terms),
                actions = new IntermediateOperationActions(context)
            });
        }
Example #11
0
        /// <summary>Initializez a new instance of an expression evaluator.</summary>
        /// <param name="context">The math context.</param>
        /// <param name="variables">The variables collection.</param>
        public ExpressionEvaluator(IMathContext context, IVariablesCollection variables)
        {
            context.EnsureNotNull(nameof(context));
            variables.EnsureNotNull(nameof(variables));

            _variables = variables;
            _context   = context;

            _expressionEvaluators = new Dictionary <ExpressionType, Func <IExpression, ValueExpression> >
            {
                [ExpressionType.BinaryExpression]   = EvaluateBinaryExpression,
                [ExpressionType.UnaryExpression]    = EvaluateUnaryExpression,
                [ExpressionType.ConstantExpression] = EvaluateConstantExpression,
                [ExpressionType.GroupingExpression] = EvaluateGroupingExpression,
                [ExpressionType.VariableExpression] = EvaluateVariableExpression
            };
        }
 public static CompiledExpression Compile(string expression, IMathContext context = null)
 {
     return(new CompiledExpression(new ExpressionSyntax(expression), context));
 }
 public DefaultFunctionContext(IMathContext context)
 {
     _mathContext        = context;
     _functionDictionary = new Dictionary <string, IFunction>();
 }
Example #14
0
 public BasicTypeChecker(IMathContext mathContext)
 {
     MathContext = mathContext;
 }
 public static CompiledExpression Compile(ExpressionSyntax syntax, IMathContext context = null)
 {
     return(new CompiledExpression(syntax, context));
 }
Example #16
0
 public DefaultMathContext()
 {
     _parentContext   = null;
     _variableContext = new DefaultVariableContext(this);
     _functionContext = new DefaultFunctionContext(this);
 }
Example #17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Tokenizer"/> class.
 /// </summary>
 /// <param name="context">The context to use within this tokenizer.</param>
 public Tokenizer(IMathContext context)
 {
     Context = context;
 }
 public IntermediateOperationActions(IMathContext context)
 {
     this.context = context;
 }
Example #19
0
 public DefaultVariableContext(IMathContext context)
 {
     _mathContext        = context;
     _variableDictionary = new Dictionary <string, double>();
 }
Example #20
0
 /// <summary>Initializes a new instance of a parser.</summary>
 /// <param name="tokenizer">The tokenizer.</param>
 /// <param name="mathContext">The math context.</param>
 public Parser(ITokenizer tokenizer, IMathContext mathContext)
 {
     _tokenzier   = tokenizer;
     _mathContext = mathContext;
 }
Example #21
0
 public void Setup()
 {
     _context = new MathContext();
 }
Example #22
0
 public BasicFunctionGenerator(IMathContext mathContext)
 {
     MathContext = mathContext;
 }