public override string EvaluateFunction(FuncToken token) { switch (token.Symbol) { case ParserSymbols.Sqrt: return($"<msqrt>{token.SubTokens[0].Evaluate(this)}</msqrt>"); case ParserSymbols.Cbrt: return($"<mroot><mrow>{token.SubTokens[0].Evaluate(this)}</mrow><mn>3</mn></mroot>"); case ParserSymbols.Abs: return($"<mo>|</mo>{token.SubTokens[0].Evaluate(this)}<mo>|</mo>"); case ParserSymbols.Log10: var sbLog10 = new StringBuilder(); sbLog10.AppendFormat("<msub><mi>{0}</mi><mn>10</mn></msub>", ParserSymbols.Log); sbLog10.AppendFormat("<mo>(</mo>{0}<mo>)</mo>", evalSub(token, 0)); return(sbLog10.ToString()); case ParserSymbols.Log: var sb = new StringBuilder(); sb.AppendFormat("<msub><mi>{0}</mi>{1}</msub>", ParserSymbols.Log, evalSub(token, 0)); sb.AppendFormat("<mo>(</mo>{0}<mo>)</mo>", evalSub(token, 1)); return(sb.ToString()); case ParserSymbols.Not: return($"<mo>¬</mo>{evalSub(token, 0)}"); case ParserSymbols.Fact: return($"{evalSub(token, 0)}<mo>!</mo>"); default: return(evalFunctionHelper(token)); } }
public override BigDecimal EvaluateFunction(FuncToken token) { if (token is CallerFuncToken) { return(parser.FunctionsDict[token.Symbol].Invoke(fallback.EvaluateTokens((token).SubTokens.ToArray()))); } switch (token.Symbol) { case ParserSymbols.Negate: return(eval(token.SubTokens[0]) * -1); case ParserSymbols.Rad: return(eval(token.SubTokens[0]) * Math.PI / 180); case ParserSymbols.Deg: return(eval(token.SubTokens[0]) * 180 / Math.PI); case ParserSymbols.Floor: return(eval(token.SubTokens[0]).Floor()); case ParserSymbols.Not: return(eval(token.SubTokens[0]) == 0 ? 1 : 0); case ParserSymbols.Fact: var v = eval(token.SubTokens[0]); if (v < 0 || v % 1 != 0) { return(double.NaN); } BigDecimal fact = 1; for (int i = (int)v; i > 0; i--) { fact *= i; } return(fact); case ParserSymbols.Cond: return(eval(token.SubTokens[0]) != 0 ? eval(token.SubTokens[1]) : eval(token.SubTokens[2])); default: if (Context.Options.StrictMode) { throw new UnsupportedOperationException(token.Symbol); } double result = token.Evaluate(fallback); if (double.IsNaN(result)) { throw new ParserArithmeticException(token.Position); } else { return((BigDecimal)result); } } }
public override string EvaluateFunction(FuncToken token) { string ret = ""; foreach (TreeToken tok in token.SubTokens) { ret += tok.Evaluate(this) + " "; } return(String.Format("{0}{1}", ret, token.Symbol)); }
public override string EvaluateFunction(FuncToken token) { var sb = new StringBuilder(token.Symbol); sb.Append("("); sb.Append(String.Join( parser.Tokenizer.ArgumentSeparator.ToString(), token.SubTokens.Select(t => t.Evaluate(this)) )); sb.Append(")"); return(sb.ToString()); }
private string evalFunctionHelper(FuncToken token) { StringBuilder sb = new StringBuilder(); sb.AppendFormat("<mi>{0}</mi>", token.Symbol); sb.AppendFormat("<mfenced separators=\"{0}\">", parser.Tokenizer.ArgumentSeparator); foreach (TreeToken tok in token.SubTokens) { sb.Append($"<mrow>{tok.Evaluate(this)}</mrow>"); } sb.Append("</mfenced>"); return(sb.ToString()); }
public override double EvaluateFunction(FuncToken token) { if (token is CallerFuncToken) { return(parser.FunctionsDict[token.Symbol].Invoke(EvaluateTokens((token).SubTokens.ToArray()))); } switch (token.Symbol) { case ParserSymbols.Negate: return(eval(token.SubTokens[0]) * -1); case ParserSymbols.Sqrt: return(Math.Sqrt(eval(token.SubTokens[0]))); case ParserSymbols.Cbrt: return(Math.Pow(eval(token.SubTokens[0]), (double)1 / 3)); case ParserSymbols.Exp: return(Math.Exp(eval(token.SubTokens[0]))); case ParserSymbols.Sin: return(Math.Sin(eval(token.SubTokens[0]))); case ParserSymbols.Cos: return(Math.Cos(eval(token.SubTokens[0]))); case ParserSymbols.Tan: return(Math.Tan(eval(token.SubTokens[0]))); case ParserSymbols.Abs: return(Math.Abs(eval(token.SubTokens[0]))); case ParserSymbols.Log10: return(Math.Log10(eval(token.SubTokens[0]))); case ParserSymbols.LogE: return(Math.Log(eval(token.SubTokens[0]))); case ParserSymbols.ASin: return(Math.Asin(eval(token.SubTokens[0]))); case ParserSymbols.ACos: return(Math.Acos(eval(token.SubTokens[0]))); case ParserSymbols.ATan: return(Math.Atan(eval(token.SubTokens[0]))); case ParserSymbols.Sinh: return(Math.Sinh(eval(token.SubTokens[0]))); case ParserSymbols.Cosh: return(Math.Cosh(eval(token.SubTokens[0]))); case ParserSymbols.Tanh: return(Math.Tanh(eval(token.SubTokens[0]))); case ParserSymbols.Log: return(Math.Log(eval(token.SubTokens[1]), eval(token.SubTokens[0]))); case ParserSymbols.Rad: return(eval(token.SubTokens[0]) * Math.PI / 180); case ParserSymbols.Deg: return(eval(token.SubTokens[0]) * 180 / Math.PI); case ParserSymbols.Ceil: return(Math.Ceiling(eval(token.SubTokens[0]))); case ParserSymbols.Floor: return(Math.Floor(eval(token.SubTokens[0]))); case ParserSymbols.Round: return(Math.Round(eval(token.SubTokens[0]))); case ParserSymbols.Sign: return(Math.Sign(eval(token.SubTokens[0]))); case ParserSymbols.Trunc: return(Math.Truncate(eval(token.SubTokens[0]))); case ParserSymbols.Min: return(EvaluateTokens(token.SubTokens.ToArray()).Min()); case ParserSymbols.Max: return(EvaluateTokens(token.SubTokens.ToArray()).Max()); case ParserSymbols.Avg: return(EvaluateTokens(token.SubTokens.ToArray()).Average()); case ParserSymbols.AndFunc: return(EvaluateTokens(token.SubTokens.ToArray()) .Select(v1 => Convert.ToBoolean(v1)) .Aggregate((v1, v2) => v1 & v2) ? 1 : 0); case ParserSymbols.OrFunc: return(EvaluateTokens(token.SubTokens.ToArray()) .Select(v1 => Convert.ToBoolean(v1)) .Aggregate((v1, v2) => v1 | v2) ? 1 : 0); case ParserSymbols.XorFunc: return(EvaluateTokens(token.SubTokens.ToArray()) .Select(v1 => Convert.ToBoolean(v1)) .Aggregate((v1, v2) => v1 ^ v2) ? 1 : 0); case ParserSymbols.Not: return(!Convert.ToBoolean(eval(token.SubTokens[0])) ? 1 : 0); case ParserSymbols.Fact: double v = eval(token.SubTokens[0]); if (v < 0 || v % 1 != 0) { return(double.NaN); } double fact = 1; for (int i = (int)v; i > 0; i--) { fact *= i; } return(fact); case ParserSymbols.Cond: return(Convert.ToBoolean(eval(token.SubTokens[0])) ? eval(token.SubTokens[1]) : eval(token.SubTokens[2])); default: if (Context.Options.StrictMode) { throw new UnsupportedOperationException(token.Symbol); } return(double.NaN); } }
/// <summary> /// Evaluates a given function token. /// </summary> /// <param name="token">The token to be evaluated.</param> /// <returns>The evaluated value.</returns> public abstract T EvaluateFunction(FuncToken token);
public override Expression EvaluateFunction(FuncToken token) { if (token is CallerFuncToken) { Delegate func = parser.FunctionsDict[token.Symbol]; return(Expression.Invoke(Expression.Constant(func), EvaluateTokens((token).SubTokens.ToArray()))); } switch (token.Symbol) { case ParserSymbols.Negate: return(Expression.Negate(eval(token.SubTokens[0]))); case ParserSymbols.Sqrt: return(Expression.Power(eval(token.SubTokens[0]), Expression.Constant(0.5))); case ParserSymbols.Cbrt: return(Expression.Power(eval(token.SubTokens[0]), Expression.Constant(1 / 3.0))); case ParserSymbols.Exp: return(Expression.Power(Expression.Constant(Math.E), eval(token.SubTokens[0]))); case ParserSymbols.Sin: return(makeFuncExpr <OneFunc>(p => Math.Sin(p), eval(token.SubTokens[0]))); case ParserSymbols.Cos: return(makeFuncExpr <OneFunc>(p => Math.Cos(p), eval(token.SubTokens[0]))); case ParserSymbols.Tan: return(makeFuncExpr <OneFunc>(p => Math.Tan(p), eval(token.SubTokens[0]))); case ParserSymbols.Abs: return(makeFuncExpr <OneFunc>(p => Math.Abs(p), eval(token.SubTokens[0]))); case ParserSymbols.Log10: return(makeFuncExpr <OneFunc>(p => Math.Log10(p), eval(token.SubTokens[0]))); case ParserSymbols.LogE: return(makeFuncExpr <OneFunc>(p => Math.Log(p), eval(token.SubTokens[0]))); case ParserSymbols.ASin: return(makeFuncExpr <OneFunc>(p => Math.Asin(p), eval(token.SubTokens[0]))); case ParserSymbols.ACos: return(makeFuncExpr <OneFunc>(p => Math.Acos(p), eval(token.SubTokens[0]))); case ParserSymbols.ATan: return(makeFuncExpr <OneFunc>(p => Math.Atan(p), eval(token.SubTokens[0]))); case ParserSymbols.Sinh: return(makeFuncExpr <OneFunc>(p => Math.Sinh(p), eval(token.SubTokens[0]))); case ParserSymbols.Cosh: return(makeFuncExpr <OneFunc>(p => Math.Cosh(p), eval(token.SubTokens[0]))); case ParserSymbols.Tanh: return(makeFuncExpr <OneFunc>(p => Math.Tanh(p), eval(token.SubTokens[0]))); case ParserSymbols.Log: return(makeFuncExpr <TwoFunc>((p1, p2) => Math.Log(p1, p2), eval(token.SubTokens[1]), eval(token.SubTokens[0]))); case ParserSymbols.Rad: return(makeFuncExpr <OneFunc>(p => p * Math.PI / 180, eval(token.SubTokens[0]))); case ParserSymbols.Deg: return(makeFuncExpr <OneFunc>(p => p * 180 / Math.PI, eval(token.SubTokens[0]))); case ParserSymbols.Ceil: return(makeFuncExpr <OneFunc>(p => Math.Ceiling(p), eval(token.SubTokens[0]))); case ParserSymbols.Floor: return(makeFuncExpr <OneFunc>(p => Math.Floor(p), eval(token.SubTokens[0]))); case ParserSymbols.Round: return(makeFuncExpr <OneFunc>(p => Math.Round(p), eval(token.SubTokens[0]))); case ParserSymbols.Sign: return(makeFuncExpr <OneFunc>(p => Math.Sign(p), eval(token.SubTokens[0]))); case ParserSymbols.Trunc: return(makeFuncExpr <OneFunc>(p => Math.Truncate(p), eval(token.SubTokens[0]))); case ParserSymbols.Min: return(makeFuncExpr <ArrayFunc>( a => a.Min(), Expression.NewArrayInit(typeof(double), EvaluateTokens(token.SubTokens.ToArray())))); case ParserSymbols.Max: return(makeFuncExpr <ArrayFunc>( a => a.Max(), Expression.NewArrayInit(typeof(double), EvaluateTokens(token.SubTokens.ToArray())))); case ParserSymbols.Avg: return(makeFuncExpr <ArrayFunc>( a => a.Average(), Expression.NewArrayInit(typeof(double), EvaluateTokens(token.SubTokens.ToArray())))); case ParserSymbols.AndFunc: return(makeFuncExpr <ArrayFunc>( a => a.Select(v1 => Convert.ToBoolean(v1)).Aggregate((v1, v2) => v1 & v2) ? 1 : 0, Expression.NewArrayInit(typeof(double), EvaluateTokens(token.SubTokens.ToArray())))); case ParserSymbols.OrFunc: return(makeFuncExpr <ArrayFunc>( a => a.Select(v1 => Convert.ToBoolean(v1)).Aggregate((v1, v2) => v1 | v2) ? 1 : 0, Expression.NewArrayInit(typeof(double), EvaluateTokens(token.SubTokens.ToArray())))); case ParserSymbols.XorFunc: return(makeFuncExpr <ArrayFunc>( a => a.Select(v1 => Convert.ToBoolean(v1)).Aggregate((v1, v2) => v1 ^ v2) ? 1 : 0, Expression.NewArrayInit(typeof(double), EvaluateTokens(token.SubTokens.ToArray())))); case ParserSymbols.Not: return(Expression.Not(toBoolExpr(eval(token.SubTokens[0])))); case ParserSymbols.Fact: return(makeFuncExpr <OneFunc>(p => fact(p), eval(token.SubTokens[0]))); case ParserSymbols.Cond: return(Expression.Condition(toBoolExpr(eval(token.SubTokens[0])), eval(token.SubTokens[1]), eval(token.SubTokens[2]))); default: if (Context.Options.StrictMode) { throw new UnsupportedOperationException(token.Symbol); } return(Expression.Constant(double.NaN)); } }
/// <summary> /// Reads the arguments given to a function and puts them into a FuncParamToken. /// </summary> /// <returns>The created FuncParamToken conatining the arguments given to the function.</returns> private Token readFuncParams(FuncToken funcToken, InputStream str) { if (str.AtEnd) { throw new ParserSyntaxException("Invalid function usage.", funcToken.Position); } FuncParamToken paramtok = new FuncParamToken(str.Position); LinkedList <Token> subTokenList = new LinkedList <Token>(); int open = 0, close = 0; bool withBrackets = false; string removeVar = null; // Match the index variable if it's a VarFuncToken. if (funcToken is VarFuncToken varFuncToken) { var match = varFuncRegex.Match(str.InputString); if (match.Success) { withBrackets = true; open++; var varToken = new VarToken(match.Groups[1].ToString(), str.Position); paramtok.ParamList.Add(new LinkedList <Token>(new[] { varToken })); str.MoveForward(match.Length); if (!TokenDict.ContainsKey(varToken.Symbol)) { removeVar = varToken.Symbol; TokenDict.Add(removeVar, new Tuple <Type, int>(typeof(VarToken), 0)); } } else { throw new ParserSyntaxException("Invalid index variable definition.", str.Position); } } Token tok = funcToken; do { if (str.StartsWith(ArgumentSeparator.ToString())) { paramtok.ParamList.Add(subTokenList); subTokenList = new LinkedList <Token>(); tok = funcToken; } tok = readNextToken(subTokenList, tok, str); if (tok is LeftBracketToken) { open++; if (!withBrackets) { withBrackets = true; subTokenList.RemoveLast(); } ; } else if (tok is RightBracketToken) { close++; } if (tok is FuncToken func) { subTokenList.AddLast(tok = readFuncParams(func, str)); } }while (!str.AtEnd && (open != close)); if (open != close) { throw new ParserBracketException("Unequal number of opening and closing brackets.", str.Position); } paramtok.ParamList.Add(subTokenList); if (withBrackets) { paramtok.ParamList[paramtok.ParamList.Count - 1].RemoveLast(); } if (removeVar != null) { TokenDict.Remove(removeVar); } return(paramtok); }
public override decimal EvaluateFunction(FuncToken token) { if (token is CallerFuncToken) { return((decimal)parser.FunctionsDict[token.Symbol].Invoke(fallback.EvaluateTokens((token).SubTokens.ToArray()))); } switch (token.Symbol) { case ParserSymbols.Negate: return(eval(token.SubTokens[0]) * -1); case ParserSymbols.Rad: return(eval(token.SubTokens[0]) * (decimal)Math.PI / 180); case ParserSymbols.Deg: return(eval(token.SubTokens[0]) * 180 / (decimal)Math.PI); case ParserSymbols.Ceil: return(Math.Ceiling(eval(token.SubTokens[0]))); case ParserSymbols.Floor: return(Math.Floor(eval(token.SubTokens[0]))); case ParserSymbols.Round: return(Math.Round(eval(token.SubTokens[0]))); case ParserSymbols.Sign: return(Math.Sign(eval(token.SubTokens[0]))); case ParserSymbols.Trunc: return(Math.Truncate(eval(token.SubTokens[0]))); case ParserSymbols.Min: return(EvaluateTokens(token.SubTokens.ToArray()).Min()); case ParserSymbols.Max: return(EvaluateTokens(token.SubTokens.ToArray()).Max()); case ParserSymbols.Avg: return(EvaluateTokens(token.SubTokens.ToArray()).Average()); case ParserSymbols.AndFunc: return(EvaluateTokens(token.SubTokens.ToArray()) .Select(v1 => Convert.ToBoolean(v1)) .Aggregate((v1, v2) => v1 & v2) ? 1 : 0); case ParserSymbols.OrFunc: return(EvaluateTokens(token.SubTokens.ToArray()) .Select(v1 => Convert.ToBoolean(v1)) .Aggregate((v1, v2) => v1 | v2) ? 1 : 0); case ParserSymbols.XorFunc: return(EvaluateTokens(token.SubTokens.ToArray()) .Select(v1 => Convert.ToBoolean(v1)) .Aggregate((v1, v2) => v1 ^ v2) ? 1 : 0); case ParserSymbols.Not: return(!Convert.ToBoolean(eval(token.SubTokens[0])) ? 1 : 0); case ParserSymbols.Fact: decimal v = eval(token.SubTokens[0]); if (v < 0 || v % 1 != 0) { throw new ParserArithmeticException(token.Position); } decimal fact = 1; for (int i = (int)v; i > 0; i--) { fact *= i; } return(fact); case ParserSymbols.Cond: return(Convert.ToBoolean(eval(token.SubTokens[0])) ? eval(token.SubTokens[1]) : eval(token.SubTokens[2])); default: if (Context.Options.StrictMode) { throw new UnsupportedOperationException(token.Symbol); } double result = token.Evaluate(fallback); if (double.IsNaN(result)) { throw new ParserArithmeticException(token.Position); } else { return((decimal)result); } } }