/// <summary> /// Creates an <see cref="IEnumerable{Token}" /> containing infix tokens from partitioning the specified term. /// </summary> /// <param name="term">The term to partition into infix tokens.</param> /// <returns><see cref="IEnumerable{Token}" /> containing the created infix tokens.</returns> public static IEnumerable <Token> CalculateInfixTokens(string term) { var infixTokens = new List <Token>(); term = SWhitespace.Replace(term, string.Empty).ToLowerInvariant(); var i = 0; while (i < term.Length) { var current = term[i]; if (char.IsLetter(current) || CharEx.IsMathematicOperator(current) || CharEx.IsBracket(current)) // Functions/Operators/Constants { if ((current == '+' || current == '-') && (i == 0 || infixTokens.Last().Type == TokenType.Bracket && ((Token <string>)infixTokens.Last()).Value == "(")) // Must be a sign and handled differently. { if (current == '-') { var sb = new StringBuilder(term) { [term.IndexOf(current)] = '!' }; term = sb.ToString(); } else { term.Remove(term.IndexOf(current), 1); } // Remove the '+' as it is redundant and disturbs our calculations } infixTokens.Add(ReadStringToken(term, ref i)); } else if (char.IsDigit(current)) // Numbers { infixTokens.Add(ReadNumberToken(term, ref i)); } else { throw new ParserException($"Char {current} cannot be interpreted as a valid token."); } } return(infixTokens); }
/// <summary> /// Reads a bracket, constant, operator or function token in the input string starting at the specified index. /// </summary> /// <param name="input">The input string.</param> /// <param name="index">The index to start at.</param> /// <returns>The <see cref="Token" /> that has been read.</returns> public static Token <string> ReadStringToken(string input, ref int index) { TokenType newType; var endIndex = index; while (endIndex < input.Length && (char.IsLetter(input, endIndex) || CharEx.IsMathematicOperator(input[endIndex]) || CharEx.IsBracket(input[endIndex]))) { endIndex++; var currentString = input.Substring(index, endIndex - index); if (_functionActions.ContainsKey(currentString) || _operatorActions.ContainsKey(currentString) || _constantActions.ContainsKey(currentString) || currentString.IsBracket() ) // Last two conditions to parse e.g. "* sin(5)" correctly: As soon as the current token has finished, we should stop reading. { break; // This indicates that it has been found in the dictionary, so that is already it. } } var stringToken = input.Substring(index, endIndex - index); if (_functionActions.ContainsKey(stringToken)) { newType = TokenType.Function; } else if (_operatorActions.ContainsKey(stringToken)) { newType = TokenType.Operator; } else if (stringToken.IsBracket()) { newType = TokenType.Bracket; } else if (_constantActions.ContainsKey(stringToken)) { newType = TokenType.Constant; } else { throw new ParserException( $"Invalid token: {stringToken} is not a valid function/operator, bracket or number equivalent."); } index = endIndex; return(new Token <string>(stringToken, newType)); }
/// <summary> /// Reads a bracket, operator or function token in the input string starting at the specified index. /// </summary> /// <param name="input">The input string.</param> /// <param name="index">The index to start at.</param> /// <returns>The <see cref="Token" /> that has been read.</returns> public static Token <string> ReadStringToken(string input, ref int index) { TokenType newType; int endIndex = index; while (endIndex < input.Length && (char.IsLetter(input, endIndex) || CharEx.IsMathematicOperator(input[endIndex]) || CharEx.IsBracket(input[endIndex]))) { endIndex++; string currentString = input.Substring(index, endIndex - index); if (_functionActions.ContainsKey(currentString) || _operatorActions.ContainsKey(currentString) || currentString.IsBracket()) // Last two conditions to parse e.g. "* sin(5)" correctly { break; } } string stringToken = input.Substring(index, endIndex - index); if (_functionActions.ContainsKey(stringToken)) { newType = TokenType.Function; } else if (_operatorActions.ContainsKey(stringToken)) { newType = TokenType.Operator; } else if (stringToken.IsBracket()) { newType = TokenType.Bracket; } else { throw new ParserException( $"Invalid token: {stringToken} is not a valid function/operator, bracket or number equivalent."); } index = endIndex; return(new Token <string>(stringToken, newType)); }