private void ValidateNumberFormatter(INumberBoxNumberFormatter value) { if (value is null) { throw new ArgumentNullException(nameof(value)); } }
public static double?Compute(string expr, INumberBoxNumberFormatter numberParser) { // Tokenize the input string var tokens = GetTokens(expr, numberParser); if (tokens.Count > 0) { // Rearrange to postfix notation var postfixTokens = ConvertInfixToPostfix(tokens); if (postfixTokens.Count > 0) { // Compute expression return(ComputePostfixExpression(postfixTokens)); } } return(null); }
static (double, int) GetNextNumber(string input, INumberBoxNumberFormatter numberParser) { // Attempt to parse anything before an operator or space as a number Regex regex = new Regex("^-?([^-+/*\\(\\)\\^\\s]+)"); Match match = regex.Match(input); if (match.Success) { // Might be a number var matchLength = match.Value.Length; var parsedNum = numberParser.ParseDouble(input.Substring(0, matchLength)); if (parsedNum.HasValue) { // Parsing was successful return(parsedNum.Value, matchLength); } } return(double.NaN, 0); }
static IList <MathToken> GetTokens(string input, INumberBoxNumberFormatter numberParser) { var tokens = new List <MathToken>(); bool expectNumber = true; while (input.Length > 0) { // Skip spaces var nextChar = input[0]; if (nextChar != ' ') { if (expectNumber) { if (nextChar == '(') { // Open parens are also acceptable, but don't change the next expected token type. tokens.Add(new MathToken(MathTokenType.Parenthesis, nextChar)); } else { var(value, charLength) = GetNextNumber(input, numberParser); if (charLength > 0) { tokens.Add(new MathToken(MathTokenType.Numeric, value)); input = input.SafeSubstring(charLength - 1); // advance the end of the token expectNumber = false; // next token should be an operator } else { // Error case -- next token is not a number return(s_emptyTokens); } } } else { if (c_numberBoxOperators.IndexOf(nextChar) >= 0) { tokens.Add(new MathToken(MathTokenType.Operator, nextChar)); expectNumber = true; // next token should be a number } else if (nextChar == ')') { // Closed parens are also acceptable, but don't change the next expected token type. tokens.Add(new MathToken(MathTokenType.Parenthesis, nextChar)); } else { // Error case -- could not evaluate part of the expression return(s_emptyTokens); } } } input = input.SafeSubstring(1); } return(tokens); }