public static bool VerifySymbol(string symbol) { // Cannot contain certain reserverd characters. Or whitespace. foreach (char c in symbol) { if (CalcToken.IsOperatorChar(c) || char.IsWhiteSpace(c)) { return(false); } switch (c) { case '(': case ')': case '.': case ',': return(false); } } // It also can't be empty or start with a digit. if (symbol.Length > 0 && !char.IsDigit(symbol[0])) { return(true); } return(false); }
public TokenExpression Tokenize(string expr) { exprList = new List <CalcToken>(); tmpToken = new List <char>(); // Set initial values of control and housekeeping variables. TokenTypes allowedTokens = TokenTypes.ExprBegin; decimalPoint = false; numberStart = -1; symbolStart = -1; depthMeter = new Stack <bool>(); // Look-behind 1 character for double char ops. char prevc = '\0'; for (int i = 0; i < expr.Length; i++) { char c = expr[i]; // ---------------------- // ----- [1] Number ----- // ---------------------- if (char.IsDigit(c)) { if (allowedTokens.HasFlag(TokenTypes.Number)) { AddDigitToNum(c, i); // Set the allowed tokens for the next character. allowedTokens = TokenTypes.Number | TokenTypes.ExprEnd; } else { return(new TokenExpression("Unexpected number: " + c, i)); } } else if (c == '.') { if (allowedTokens.HasFlag(TokenTypes.Number)) { if (decimalPoint) { return(new TokenExpression("More than one decimal point detected", i)); } AddDotToNum(i); // Set the allowed tokens for the next character. allowedTokens = TokenTypes.Number; } else { return(new TokenExpression("Unexpected decimal point", i)); } } // --------------------------- // ----- [2] Unary Minus ----- // --------------------------- else if (c == '-' && allowedTokens.HasFlag(TokenTypes.UnaryMinus)) { exprList.Add(CalcToken.UnaryMinus(i)); } // -------------------------------- // ----- [3] Left Parenthesis ----- // -------------------------------- else if (c == '(') { if (allowedTokens.HasFlag(TokenTypes.L_Paren)) { AddLParenToExpr(i); // Set the allowed tokens for the next character. allowedTokens = TokenTypes.ExprBegin; } else { return(new TokenExpression("Unexpected left parenthesis", i)); } } // --------------------------------- // ----- [4] Right Parenthesis ----- // --------------------------------- else if (c == ')') { if (allowedTokens.HasFlag(TokenTypes.R_Paren)) { if (depthMeter.Count == 0) { return(new TokenExpression("Tried to close a subexpression before it was opened", i)); } AddRParenToExpr(i); // Set the allowed tokens for the next character. allowedTokens = TokenTypes.ExprEnd; } else { return(new TokenExpression("Unexpected right parenthesis", i)); } } // ------------------------ // ----- [5] Operator ----- // ------------------------ else if (CalcToken.IsOperatorChar(c)) { if (allowedTokens.HasFlag(TokenTypes.Operator)) { AddOperatorToExpr(c, i); // Set the allowed tokens for the next character. allowedTokens = TokenTypes.ExprBegin; } else if (CalcToken.IsDoubleOperator(prevc, c)) { UpdateLastOperator(c); // Monkey with the `c` variable, and thus the next `prevc` character. // This is to prevent operators longer than 2 chars to pass inspection. c = '\0'; } else { return(new TokenExpression("Unexpected operator: " + c, i)); } } // ----- [6] Whitespace ----- // Ignore whitespace. else if (char.IsWhiteSpace(c)) { continue; } // ---------------------------------- // ----- [7] Argument Seperator ----- // ---------------------------------- else if (c == ',') { if (allowedTokens.HasFlag(TokenTypes.R_Paren)) { if (depthMeter.Count == 0 || depthMeter.Peek() == false) { return(new TokenExpression("Illegal argument seperator", i)); } AddSepToExpr(i); // Set the allowed tokens for the next character. allowedTokens = TokenTypes.ExprBegin; } else { return(new TokenExpression("Unexpected argument seperator", i)); } } // ---------------------- // ----- [8] Symbol ----- // ---------------------- else if (allowedTokens.HasFlag(TokenTypes.Symbol)) { AddCharToSym(c, i); // Set the allowed tokens for the next character. allowedTokens = TokenTypes.Symbol | TokenTypes.L_Paren | TokenTypes.ExprEnd; } // ----- [9] Unexpected Character ----- else { return(new TokenExpression("Unexpected character: " + c, i)); } prevc = c; } // Abort on unclosed subexpression(s) / too many left parentheses. if (depthMeter.Count > 0) { return(new TokenExpression("Unclosed subexpression(s) detected, amount: " + depthMeter.Count)); } // Final check. The expression should have ended in either an operand or a right parenthesis. Both of these // set the allowedTokens to include TokenType.Operator, which would not be set by the others. So check for // that to determine whether the expression has ended correctly. if (!allowedTokens.HasFlag(TokenTypes.Operator)) { return(new TokenExpression("Expression did not end with an operand or closing parenthesis")); } AddOperandToExpr(); return(new TokenExpression(exprList)); }