public ExpressinPosition(int index, int length) { this.Index = index; this.Length = length; this.Parameter = -1; this.Part = ExpressionPart.Text; }
private INode YieldExpression(ExpressionPart expressionPart) { if (expressionPart == null) { return(null); } var node = new ExpressionNode(expressionPart); return(node); }
public ExpressionNode(ExpressionPart expressionPart) : this(expressionPart.Expression) { }
/// <summary> /// Creates elements of the expression parts and checks. /// </summary> /// <param name="s">ExpressionString whose bracketed parts are parsed.</param> /// <returns>True if partsyntax was correct.</returns> private bool ParseExpressionPart(string s) { bool readVal = true; // true - reading values and unary operations; false - reading binary operations // adding a part ExpressionPart part = new ExpressionPart(); part.expression = s; for (int i = 0; i < s.Length; i++) { SkipSpaces(s, ref i); if (i >= s.Length) break; // reading element Element element = new Element(ref _floatingFormat); if (readVal) { if (!ReadValue(s, ref i, element)) return false; } else { if (!ReadOperation(s, ref i, element)) return false; } // saving element part.elements.Add(element); //in case operation was unary the next element should be value as well if (element.operation != tkOperation.operNOT && element.operation != tkOperation.operChangeSign) readVal = !readVal; } if (part.elements.Count > 0) { _parts.Add(part); return true; } return false; }
/// <summary>Gets the ExpressionValue of the element of the given part. /// </summary> /// <param name="part">Part that contains the element.</param> /// <param name="elementId">Id of the element whose value is returned.</param> /// <returns>Value of the element.</returns> private ExpressionValue GetValue(ExpressionPart part, int elementId) { Element element = part.elements[elementId]; if (element.wasCalculated) return element.calcVal; else if (element.partIndex != -1) return _parts[element.partIndex].val; else return element.val; }
/// <summary> /// Seeks operation with the highest priority and operands. /// </summary> /// <param name="part"></param> /// <param name="operation"></param> /// <returns></returns> private bool FindOperation(ExpressionPart part, Operation operation) { // seeking operation bool found = false; int priority = 255; List<Element> elements = part.elements; int size = elements.Count; for (int i = 0; i < size; i++) { Element element = elements[i]; if (!element.turnedOff) { if (element.type == tkElementType.etOperation) { if (element.priority < priority) { found = true; priority = element.priority; operation.id = i; } } } } if (!found) { _errorMessage = SymbologyMessageStrings.Expression_OperationNotFound; return false; } // seeking right operand operation.left = operation.right = -1; for (int i = operation.id + 1; i < size; i++) { Element element = elements[i]; if (!element.turnedOff) { if (element.type == tkElementType.etOperation) { if (element.operation != tkOperation.operNOT && element.operation != tkOperation.operChangeSign) { _errorMessage = SymbologyMessageStrings.Expression_OpereratorInsteadOfValue; return false; } } else { operation.right = i; break; } } } if (operation.right == -1) { _errorMessage = SymbologyMessageStrings.Expression_RightOperandMissing; return false; } // if the operator is binary, seeking left operand if (elements[operation.id].operation != tkOperation.operNOT && elements[operation.id].operation != tkOperation.operChangeSign) { for (int i = operation.id - 1; i >= 0; i--) { if (!elements[i].turnedOff) { operation.left = i; break; } } if (operation.left == -1) { _errorMessage = SymbologyMessageStrings.Expression_LeftOperandMissing; return false; } operation.binaryOperation = true; } else { operation.binaryOperation = false; } // caching operations if (_saveOperations) { Operation op = new Operation(); op.left = operation.left; op.right = operation.right; op.id = operation.id; op.binaryOperation = operation.binaryOperation; _operations.Add(op); } return true; }
/// <summary> /// Calculates the given operation for the values of the given part. /// </summary> /// <param name="part"></param> /// <param name="operation"></param> /// <returns></returns> private bool CalculateOperation(ExpressionPart part, Operation operation) { ExpressionValue valLeft = null; ExpressionValue valRight = null; Element elLeft = null; Element elRight = null; tkOperation oper = part.elements[operation.id].operation; valRight = GetValue(part, operation.right); elRight = part.elements[operation.right]; if (oper == tkOperation.operNOT) // tis is an unary operator and we read only right operand { if (valRight.type != tkValueType.vtBoolean) { _errorMessage = SymbologyMessageStrings.Expression_OperationNotSupported; return false; } elRight.calcVal.bln = !(valRight.bln); elRight.calcVal.type = tkValueType.vtBoolean; elRight.wasCalculated = true; part.elements[operation.id].turnedOff = true; } else if (oper == tkOperation.operChangeSign) // tis is an unary operator and we read only right operand { if (valRight.type != tkValueType.vtDouble) { _errorMessage = SymbologyMessageStrings.Expression_OperationNotSupported; return false; } elRight.calcVal.dbl = -valRight.dbl; elRight.calcVal.type = tkValueType.vtDouble; elRight.wasCalculated = true; part.elements[operation.id].turnedOff = true; } else // these are binary operators as we read left and right operands { valLeft = GetValue(part, operation.left); elLeft = part.elements[operation.left]; if (oper == tkOperation.operLineBreak) { elLeft.calcVal.str = valLeft.ToString() + Environment.NewLine + valRight.ToString(); elLeft.calcVal.type = tkValueType.vtString; } else if (valLeft.type == valRight.type) { if (valLeft.type == tkValueType.vtDouble) { CalculateDoubleOperation(oper, elLeft, elRight, valLeft, valRight); } else if (valLeft.type == tkValueType.vtString) { CalculateStringOperation(oper, elLeft, elRight, valLeft, valRight); } else if (valLeft.type == tkValueType.vtBoolean) { CalculateBoolOperation(oper, elLeft, elRight, valLeft, valRight); } } else if (oper != tkOperation.operPlus) // plus is the only operation that can have different valuetypes { _errorMessage = SymbologyMessageStrings.Expression_OperationNotSupported; return false; } else if (valLeft.type == tkValueType.vtBoolean || valRight.type == tkValueType.vtBoolean) // boolean can't be added { _errorMessage = SymbologyMessageStrings.Expression_PlusNotAllowed; return false; } else //concat strings and doubles { elLeft.calcVal.str = valLeft.ToString() + valRight.ToString(); elLeft.calcVal.type = tkValueType.vtString; } elLeft.wasCalculated = true; part.elements[operation.id].turnedOff = true; part.elements[operation.right].turnedOff = true; } return true; }
/// <summary> /// Parses the given string to Expression. /// </summary> /// <param name="s"></param> /// <returns>True if string can be parsed to expression.</returns> public bool ParseExpression(string s) { _errorMessage = ""; if (_expressionString != s) { _expressionString = s; _expChanged = true; _valid = false; } else { _expChanged = false; if (_valid) return true; } if (s.Length == 0) return false; ExpressionPart bracket = new ExpressionPart(); _saveOperations = true; _variables.Clear(); _parts.Clear(); _operations.Clear(); _strings.Clear(); foreach (string c in new string[] { "{", "}" }) { int pos = s.IndexOf(c); if (pos > -1) { _errorMessage = "Unallowed character " + c + " at " + pos; return false; } } Regex r = new Regex(@"\[(\d+|\w+)\]"); //all fields in [] that contain only word characters and numbers var matches = r.Matches(s); for (int i = matches.Count - 1; i >= 0; i--) { _strings.Add(matches[i].Value.Substring(1, matches[i].Length - 2)); ReplaceSubString(ref s, matches[i].Index, matches[i].Length, "{f" + (_strings.Count - 1) + "}"); } r = new Regex("(\"([^\"\n]*(\"\")*[^\"\n]*)*\")"); //everything inside "" all the same wether it contains no " or paired " matches = r.Matches(s); for (int i = matches.Count - 1; i >= 0; i--) { _strings.Add(matches[i].Value.Substring(1, matches[i].Length - 2)); ReplaceSubString(ref s, matches[i].Index, matches[i].Length, "{s" + (_strings.Count - 1) + "}"); } if (s.Contains("\"")) { _errorMessage = SymbologyMessageStrings.Expression_UnpairedTextquotes; return false; } if (s.Contains("[]")) { _errorMessage = SymbologyMessageStrings.Expression_EmptyField; return false; } if (s.Contains("[") || s.Contains("]")) { _errorMessage = SymbologyMessageStrings.Expression_UnpairedBracket; return false; } bool found = true; while (found) { // seeking brackets int begin = 0; int end = 0; found = GetBrackets(s, ref begin, ref end); string expression = found ? s.Substring(begin + 1, end - begin - 1) : s; if (!ParseExpressionPart(expression)) return false; if (found) ReplaceSubString(ref s, begin, end - begin + 1, "{p" + (_parts.Count - 1) + "}"); } _strings.Clear(); // building field list for faster access for (int i = 0; i < _parts.Count; i++) { ExpressionPart part = _parts[i]; for (int j = 0; j < part.elements.Count; j++) { if (part.elements[j].isField) { _variables.Add(part.elements[j]); } } } return true; }