private static ResultCode MakeImplicitMultiplications( ExpressionOptions options, List <Token> tokens) { for (int i = 0; i < tokens.Count; i++) { var token = tokens[i]; if (token is CollectionToken collectionToken) { var code = MakeImplicitMultiplications(options, collectionToken.Children); if (code != ResultCode.Ok) { return(code); } } else if (token.Type != TokenType.Name) { // Skip as this type is not allowed to have an implicit factor prefix. continue; } if (i - 1 < 0) { continue; // We are at the list's beginning. } var leftToken = tokens[i - 1]; if (leftToken.Type == TokenType.Operator || leftToken.Type == TokenType.Name || leftToken.Type == TokenType.ListSeparator) { continue; } if (leftToken.Type != TokenType.DecimalDigit && leftToken.Type != TokenType.DecimalNumber && leftToken.Type != TokenType.List) { return(ResultCode.InvalidTokenBeforeList); } var multiplyOpDef = options.GetOperatorDefinition(OperatorType.Multiply); if (multiplyOpDef == null) { return(ResultCode.MissingMultiplicationDefinition); } var opToken = new ValueToken(TokenType.Operator, multiplyOpDef.Names[0]); tokens.Insert(i, opToken); } return(ResultCode.Ok); }
public static EError?ValidateOperatorTokens( ExpressionOptions options, ValueToken op, Token?left, Token?right) { var opDef = options.GetOperatorDefinition(op.Value); if (opDef != null) { if (left == null && ( opDef.Associativity == OperatorSidedness.Both || opDef.Associativity.HasFlag(OperatorSidedness.Left))) { return(EErrorCode.OperatorMissingLeftValue); } if (right == null && ( opDef.Associativity == OperatorSidedness.Both || opDef.Associativity.HasFlag(OperatorSidedness.Right))) { return(EErrorCode.OperatorMissingRightValue); } } return(null); }
private static ResultCode MakeOperatorGroups(ExpressionOptions options, List <Token> tokens) { var listStack = new Stack <List <Token> >(); listStack.Push(tokens); var opIndices = new List <(int index, ValueToken token, OperatorDefinition definition)>(); var opShifts = new List <(int index, int shift)>(); while (listStack.Count > 0) { var currentTokens = listStack.Pop(); for (int j = 0; j < currentTokens.Count; j++) { var token = currentTokens[j]; if (token is CollectionToken collectionToken) { listStack.Push(collectionToken.Children); } } // Gather operators so we can sort them by priority rules. opIndices.Clear(); for (int j = 0; j < currentTokens.Count; j++) { var token = currentTokens[j]; if (token.Type != TokenType.Operator) { continue; } var opToken = (ValueToken)token; var opDef = options.GetOperatorDefinition(opToken.Value); if (opDef == null) { return(ResultCode.UnknownSymbol); } opIndices.Add((index: j, opToken, opDef)); } opIndices.Sort((x, y) => { int xPriority = x.definition?.Precedence ?? 0; int yPriority = y.definition?.Precedence ?? 0; // Sort types in descending order. int priorityCompare = yPriority.CompareTo(xPriority); if (priorityCompare != 0) { return(priorityCompare); } // Sort indices of same type in ascending order. return(x.index.CompareTo(y.index)); }); // Merge token triplets with a center operator or // pairs with a leading operator. opShifts.Clear(); for (int i = 0; i < opIndices.Count; i++) { var(opIndex, opToken, opDef) = opIndices[i]; // Offset "opIndex" by shifts caused by previous operator merges. for (int j = 0; j < opShifts.Count; j++) { var(shiftIndex, shift) = opShifts[j]; if (shiftIndex < opIndex) { opIndex += shift; } } Token?leftToken = null; Token?rightToken = null; int left = opIndex - 1; if (opDef?.Associativity != OperatorSidedness.Right) { if (left < 0) { if (opDef != null && opDef.Associativity.HasFlag(OperatorSidedness.Left)) { return(ResultCode.OperatorMissingLeftValue); } } else { leftToken = currentTokens[left]; } } if (leftToken?.Type == TokenType.Operator) { continue; } int right = opIndex + 1; if (opDef != null && opDef.Associativity != OperatorSidedness.Left) { if (right >= currentTokens.Count) { if (opDef.Associativity.HasFlag(OperatorSidedness.Right)) { return(ResultCode.OperatorMissingRightValue); } } else { rightToken = currentTokens[right]; if (rightToken.Type == TokenType.Operator) { continue; } // Mitigates operators with following operators. if (rightToken.Type == TokenType.Operator) { int secondRight = opIndex + 2; if (secondRight < currentTokens.Count) { var subToken = new ListToken(new List <Token>(2) { rightToken, currentTokens[secondRight] }); rightToken = subToken; currentTokens[right] = rightToken; currentTokens.RemoveAt(secondRight); opShifts.Add((right, -1)); opIndices.RemoveAll(x => x.index == right); } else { return(ResultCode.OperatorMissingRightValue); } } } } int sideTokenCount = 0; if (leftToken != null) { sideTokenCount++; } if (rightToken != null) { sideTokenCount++; } // Try to skip making a 1-item list. int resultCount = 1 + sideTokenCount; if (resultCount == currentTokens.Count) { continue; } var resultList = new List <Token>(resultCount); if (leftToken != null) { resultList.Add(leftToken); } resultList.Add(opToken); if (rightToken != null) { resultList.Add(rightToken); } int firstIndex = opIndex - (leftToken != null ? 1 : 0); var resultToken = new ListToken(resultList); currentTokens[firstIndex] = resultToken; currentTokens.RemoveRange(firstIndex + 1, resultList.Count - 1); int nextShift = 1 - resultList.Count; opShifts.Add((opIndex, nextShift)); } } return(ResultCode.Ok); }