/// <summary> /// Adds an attribute /// </summary> /// <param name="row">The row to add the attribute to</param> /// <param name="attribute">The attribute to be added</param> private void AddAttribute(DataGridViewRow row, Entity.Attribute attribute) { // See if the list already has a column under ColumnName DataGridViewColumn column = this.Columns[attribute.GroupName]; // Get the first column with the column Name // If no column exists make a column if (column == null) { // Make new column switch (attribute.GetAttributeType()) { case Entity.AttributeType.Image: column = new DataGridViewImageColumn() { //ValuesAreIcons = true, ImageLayout = DataGridViewImageCellLayout.Zoom }; column.DefaultCellStyle.NullValue = null; // No weird icon if no image break; default: column = new DataGridViewTextBoxColumn(); break; } // Add column to end this.Columns.Add(column); // Format column column.Name = attribute.GroupName; } // Add to cell SetCellValue(row.Cells[attribute.GroupName], attribute.GetListViewValue()); }
private StringOrError ParseAndExecute(Entity entity, Entity.Attribute attribute) { string formula = Formula.Trim(); // Check if the formula is empty if (string.IsNullOrEmpty(formula)) { return(new StringOrError(false, "")); } // Check if the formula is a literal var matchString = Regex.Match(formula, "(\"([^\"]*)\")|(\'([^\']*)\')"); if (matchString.Success && matchString.Value == formula) { return(new StringOrError(false, matchString.Groups[2].Value)); } var matchDecimal = Regex.Match(formula, "-?[0-9]+(\\.[0-9]+)?"); if (matchDecimal.Success && matchDecimal.Value == formula) { return(new StringOrError(false, matchDecimal.Value)); } // Check if it is referencing another group var matchReference = Regex.Match(formula, @"&([^^&""\(\)\+\-\\,]+)"); // Any name ommiting special characters if (matchReference.Success && matchReference.Value == formula) { string groupName = matchReference.Groups[1].Value; Entity.Attribute referencedAttribute = entity.Attributes.FirstOrDefault(x => x.GroupName == groupName); if (referencedAttribute == null) // If attribute by the name groupName doesn't exist { MissingReferences.Add(groupName); return(new StringOrError(true, $"Could not find attribute '{groupName}'")); } else // If reference is to an existing attribute { References.Add(referencedAttribute); switch (referencedAttribute.GetAttributeType()) { case Entity.AttributeType.Image: return(new StringOrError(true, $"Cannot convert image attribute '{groupName}' to string")); case Entity.AttributeType.Formula: if (attribute != null) { List <Entity.Attribute> referenceReferences = ((Entity.FormulaAttribute)referencedAttribute).Formula.References; if (referenceReferences.Contains(attribute)) // Can't have looping dependencies { return(new StringOrError(true, $"Circular reference with '{groupName}'")); } References.AddRange(referenceReferences); } break; } return(new StringOrError(false, (string)referencedAttribute.GetListViewValue())); } } // Check for monads var monadReference = Regex.Match(formula, @"([a-zA-Z]+)\(([^,]+)\)"); if (monadReference.Success && monadReference.Value == formula) { return(new StringOrError(true, $"Could not parse monad '{formula}'")); } // Check for diads var diadReference = Regex.Match(formula, @"([a-zA-Z]+)\(([^,]+),([^,]+)\)"); if (diadReference.Success && diadReference.Value == formula) { string functionName = diadReference.Groups[1].Value.ToLower(); Expression leftExp = new Expression(diadReference.Groups[2].Value); StringOrError left = leftExp.ParseAndExecute(entity, attribute); References.AddRange(leftExp.References); MissingReferences.AddRange(leftExp.MissingReferences); if (left.IsError) { return(left); } Expression rightExp = new Expression(diadReference.Groups[3].Value); StringOrError right = rightExp.ParseAndExecute(entity, attribute); References.AddRange(rightExp.References); MissingReferences.AddRange(rightExp.MissingReferences); if (right.IsError) { return(right); } if (functionName == "add" || functionName == "sub" || functionName == "mult" || functionName == "div" || functionName == "gt" || functionName == "lt") { bool isLeftInt = decimal.TryParse(left.Value, out decimal leftDec); bool isRightInt = decimal.TryParse(right.Value, out decimal rightDec); if (!isLeftInt || !isRightInt) { return(new StringOrError(true, $"Could not parse '{(isLeftInt ? left.Value : right.Value)}' to an decimal in formula '{formula}'")); } if (functionName == "add") { return(new StringOrError(false, (leftDec + rightDec).ToString())); } if (functionName == "sub") { return(new StringOrError(false, (leftDec - rightDec).ToString())); } if (functionName == "mult") { return(new StringOrError(false, (leftDec * rightDec).ToString())); } if (functionName == "div") { if (rightDec == 0M) { return(new StringOrError(true, $"Could not divide by 0 in '{formula}'")); } return(new StringOrError(false, (leftDec / rightDec).ToString())); } if (functionName == "gt") { return(new StringOrError(false, (leftDec > rightDec).ToString())); } if (functionName == "lt") { return(new StringOrError(false, (leftDec < rightDec).ToString())); } } if (functionName == "eq") { return(new StringOrError(false, (left.Value == right.Value).ToString())); } } return(new StringOrError(true, $"Could not parse expression '{formula}'")); }