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); }
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); } }
/// <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]; }
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()); }
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); }
/// <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)); }
/// <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); }
/// <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) }); }
/// <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>(); }
public BasicTypeChecker(IMathContext mathContext) { MathContext = mathContext; }
public static CompiledExpression Compile(ExpressionSyntax syntax, IMathContext context = null) { return(new CompiledExpression(syntax, context)); }
public DefaultMathContext() { _parentContext = null; _variableContext = new DefaultVariableContext(this); _functionContext = new DefaultFunctionContext(this); }
/// <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; }
public DefaultVariableContext(IMathContext context) { _mathContext = context; _variableDictionary = new Dictionary <string, double>(); }
/// <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; }
public void Setup() { _context = new MathContext(); }
public BasicFunctionGenerator(IMathContext mathContext) { MathContext = mathContext; }