public void ReduceRoot() { if (this.Tokens.Count == 1) { Token token = this.LastToken; // Delete naked groups if (token is PartialCompletedExpression g) { this.Tokens.Clear(); this.Tokens.AddRange(g.Tokens); } // Artificially insert a bogus operator for values if (token is ValueToken) { this.AddToken(OperatorToken.CreateFromString("*", -1)); this.AddToken(ValueToken.Create(1, -1)); } } }
private static List <Token> Tokenize(string expression) { Stack <ParsingContext> parsingContextStack = new Stack <ParsingContext>(); ParsingContext parsingContext = new ParsingContext(); int index; void CompleteNumber() { StringBuilder currentToken = parsingContext.CurrentToken; if (currentToken.Length > 0) { parsingContext.AddToken(ValueToken.CreateFromString(currentToken.ToString(), index)); } currentToken.Clear(); } void CompleteMinusExpression(bool isOperator) { if (parsingContext.PossiblePendingOperator != '-') { return; } if (isOperator) { parsingContext.AddToken( OperatorToken.CreateFromString("-", index + 1) ); parsingContext.PossiblePendingOperator = Char.MinValue; return; } if (parsingContext.LastToken is PartialCompletedExpression g) { List <Token> tokenList = new List <Token> { ValueToken.CreateFromString("-1", index), OperatorToken.CreateFromString("*", index), g }; // Last is a group, and "-(1 * 3)" is actually "-1 * (1 * 3)" parsingContext.ReplaceToken( parsingContext.LastToken, PartialCompletedExpression.Create( tokenList ) ); } else if (parsingContext.LastToken is ValueToken vt) { parsingContext.ReplaceToken( parsingContext.LastToken, ValueToken.Create(-1 * vt.Value, vt.Position) ); } else { parsingContext.AppendToPartiallyCompletedToken(parsingContext.PossiblePendingOperator); } parsingContext.PossiblePendingOperator = Char.MinValue; } // Parse token from right to left for (index = expression.Length - 1; index >= 0; index--) { char ch = expression[index]; // Whitespace does not matter if (Char.IsWhiteSpace(ch)) { continue; } // Group take precedence if (ch == ')') { CompleteNumber(); CompleteMinusExpression(true); parsingContextStack.Push(parsingContext); parsingContext = new ParsingContext(); continue; } // Group end if (ch == '(') { CompleteMinusExpression(false); CompleteNumber(); ParsingContext groupContext = parsingContext; parsingContext = parsingContextStack.Pop(); parsingContext.AddToken( PartialCompletedExpression.Create(groupContext.Tokens) ); continue; } if (ch == '-') { // Otherwise it is probably part of a number, so just prepend it CompleteNumber(); if (parsingContext.PossiblePendingOperator == ch) { CompleteMinusExpression(false); } parsingContext.PossiblePendingOperator = ch; continue; } if (Char.IsDigit(ch) || ch == '.') { CompleteMinusExpression(true); parsingContext.AppendToPartiallyCompletedToken(ch); } else { CompleteMinusExpression(false); CompleteNumber(); parsingContext.AddToken(OperatorToken.CreateFromString(ch.ToString(), index)); } } CompleteNumber(); CompleteMinusExpression(false); parsingContext.ReduceRoot(); return(parsingContext.Tokens); }