# Strata.SqlTools.Rules Class Diagram This diagram shows the class hierarchy for the expression system. ```mermaid classDiagram class IVisitable { <> +Accept~T~(IVisitor~T~) T } note for IVisitable "Visitor Pattern Interface
var visitor = new MyRuleVisitor()#59;
var result = expr.Accept(visitor)#59;" class Expression { <> +Accept~T~(IVisitor~T~) T } class BoolExpr { <> } class Literal { +Value object } class LiteralGeneric~TValue~ { +Value TValue } note for LiteralGeneric "Generic Literal
var literal = new Literal<int>
{ Value = 100 }#59;" class Property { +Expression Expression +PropertyName string } note for Property "Property Access
var prop = new Property
{ PropertyName = #quot;Age#quot; }#59;" class Logical { <> +Left BoolExpr +Right BoolExpr } class Comparison { <> +Left Expression +Right Expression +ExpressionType ExpressionType } class And note for And "AND Logic
var and = new And
{
Left = expr1,
Right = expr2
}#59;" class Or note for Or "OR Logic
var or = new Or
{
Left = expr1,
Right = expr2
}#59;" class With note for With "WITH Sequential
var with = new With
{
Left = expr1,
Right = expr2
}#59;" class Equal { +ExpressionType ExpressionType } note for Equal "Equality#58; Age == 25
var eq = new Equal
{
Left = new Property
{ PropertyName = #quot;Age#quot; },
Right = new NumberLiteral
{ Value = 25m }
}#59;" class GreaterThan { +ExpressionType ExpressionType } note for GreaterThan "Comparison#58; Score > 100
var gt = new GreaterThan
{
Left = new Property
{ PropertyName = #quot;Score#quot; },
Right = new NumberLiteral
{ Value = 100m }
}#59;" class NumberLiteral { +Value decimal } note for NumberLiteral "Number Literal
var num = new NumberLiteral
{ Value = 42.5m }#59;" class StringLiteral { +Value string } note for StringLiteral "String Literal
var str = new StringLiteral
{ Value = #quot;Hello#quot; }#59;" IVisitable <|.. Expression Expression <|-- BoolExpr Expression <|-- Literal Expression <|-- Property BoolExpr <|-- Logical BoolExpr <|-- Comparison Literal <|-- LiteralGeneric LiteralGeneric <|-- NumberLiteral LiteralGeneric <|-- StringLiteral Logical <|-- And Logical <|-- Or Logical <|-- With Comparison <|-- Equal Comparison <|-- GreaterThan ``` ## Class Descriptions ### Core Classes - **IVisitable**: Interface for classes that can be visited using the visitor pattern - **Expression**: Base abstract class for all expressions - **BoolExpr**: Base class for expressions that evaluate to boolean values ### Literal Expressions - **Literal**: Represents a literal value - **Literal<TValue>**: Generic typed literal expression - **NumberLiteral**: Represents numeric literal values (decimal) - **StringLiteral**: Represents string literal values ### Property Expressions - **Property**: Represents property access in expressions ### Logical Expressions - **Logical**: Base class for logical operations (AND, OR, WITH) - **And**: Logical AND operation - **Or**: Logical OR operation - **With**: Sequential WITH operation ### Comparison Expressions - **Comparison**: Base class for comparison operations - **Equal**: Equality comparison (==) - **GreaterThan**: Greater than comparison (>) ## C# Usage Examples ### Creating Literal Expressions ```csharp // String literal var stringLiteral = new StringLiteral { Value = "Hello World" }; // Number literal var numberLiteral = new NumberLiteral { Value = 42.5m }; // Generic typed literal var typedLiteral = new Literal { Value = 100 }; ``` ### Creating Property Expressions ```csharp // Simple property access var propertyExpr = new Property { PropertyName = "Age" }; // Property with nested expression var nestedPropertyExpr = new Property { PropertyName = "Address", Expression = new Property { PropertyName = "City" } }; ``` ### Creating Comparison Expressions ```csharp // Equal comparison: Age == 25 var equalExpr = new Equal { Left = new Property { PropertyName = "Age" }, Right = new NumberLiteral { Value = 25m } }; // Greater than comparison: Score > 100 var greaterThanExpr = new GreaterThan { Left = new Property { PropertyName = "Score" }, Right = new NumberLiteral { Value = 100m } }; ``` ### Creating Logical Expressions ```csharp // AND expression: Age > 18 AND Status == "Active" var andExpr = new And { Left = new GreaterThan { Left = new Property { PropertyName = "Age" }, Right = new NumberLiteral { Value = 18m } }, Right = new Equal { Left = new Property { PropertyName = "Status" }, Right = new StringLiteral { Value = "Active" } } }; // OR expression: Type == "Premium" OR Score > 500 var orExpr = new Or { Left = new Equal { Left = new Property { PropertyName = "Type" }, Right = new StringLiteral { Value = "Premium" } }, Right = new GreaterThan { Left = new Property { PropertyName = "Score" }, Right = new NumberLiteral { Value = 500m } } }; ``` ### Complex Expression Example ```csharp // (Age > 18 AND Status == "Active") OR (Type == "Premium" WITH Score > 500) var complexExpr = new Or { Left = new And { Left = new GreaterThan { Left = new Property { PropertyName = "Age" }, Right = new NumberLiteral { Value = 18m } }, Right = new Equal { Left = new Property { PropertyName = "Status" }, Right = new StringLiteral { Value = "Active" } } }, Right = new With { Left = new Equal { Left = new Property { PropertyName = "Type" }, Right = new StringLiteral { Value = "Premium" } }, Right = new GreaterThan { Left = new Property { PropertyName = "Score" }, Right = new NumberLiteral { Value = 500m } } } }; ``` ### Using the Visitor Pattern ```csharp // Implement a custom visitor public class MyRuleVisitor : IVisitor { public string Visit(And expression) { return $"({expression.Left.Accept(this)} AND {expression.Right.Accept(this)})"; } public string Visit(Equal expression) { return $"{expression.Left.Accept(this)} == {expression.Right.Accept(this)}"; } public string Visit(StringLiteral expression) { return $"\"{expression.Value}\""; } // ... implement other Visit methods } // Use the visitor var visitor = new MyRuleVisitor(); var result = complexExpr.Accept(visitor); Console.WriteLine(result); ``` ## Markdown Parser The `Markdown` class provides functionality to parse markdown/LaTeX mathematical expressions and convert them into Expression objects. This is useful for: - Documenting rules in markdown format - Creating expressions from user-friendly text representations - Converting mathematical notation to executable rule expressions ### Supported Markdown Delimiters The parser automatically strips these common markdown delimiters: - Inline math: `$...$` - Block math: `$$...$$` - Code fence: ` ```math...``` ` ### Supported Syntax #### Logical Operators - `AND` or `\land` or `\wedge` - Logical AND - `OR` or `\lor` or `\vee` - Logical OR #### Comparison Operators - `=` - Equality - `!=` or `\neq` - Not equal - `>` or `\gt` - Greater than #### Literals - **Numbers**: `42`, `3.14` - **Strings**: `"text"` or `'text'` or `\text{text}` - **Booleans**: `true`, `false` #### Properties - Simple: `PropertyName` - With parameter: `x.PropertyName` - LaTeX format: `\text{x.PropertyName}` #### Parentheses - Regular: `(...)` - LaTeX: `\left(...\right)` ### Markdown Parser Usage Examples #### Basic Parsing ```csharp using Strata.SqlTools.Rules.Rule.Expression; // Parse a simple comparison var expr1 = Markdown.Parse("x.Age > 18"); // Returns: GreaterThan { Left = Property("x", "Age"), Right = NumberLiteral(18) } // Parse with inline math delimiters var expr2 = Markdown.Parse("$x.Status = 'active'$"); // Returns: Equal { Left = Property("x", "Status"), Right = StringLiteral("active") } // Parse with block math delimiters var expr3 = Markdown.Parse(@"$$ user.IsVerified = true $$"); // Returns: Equal { Left = Property("user", "IsVerified"), Right = Literal(true) } ``` #### Parsing Logical Operations ```csharp // Parse AND expression var andExpr = Markdown.Parse("x.Age > 18 AND x.Active = true"); // Returns: And { Left = GreaterThan(...), Right = Equal(...) } // Parse OR with LaTeX notation var orExpr = Markdown.Parse(@"$ x.Type = 'premium' \lor x.Score > 500 $"); // Returns: Or { Left = Equal(...), Right = GreaterThan(...) } // Parse with LaTeX wedge (AND) and vee (OR) var complexExpr = Markdown.Parse(@" (x.Valid = true \wedge x.Count > 0) \vee y.Override = true "); // Returns: Or { Left = And(...), Right = Equal(...) } ``` #### Parsing Complex Expressions ```csharp // Complex business rule with nested conditions var businessRule = Markdown.Parse(@"$$ (invoice.TotalCharges > 1000 \land invoice.Status = \text{pending}) \lor (invoice.Priority = \text{urgent} \land invoice.ApprovedBy \neq \text{}) $$"); // Use with visitor pattern var visitor = new MyRuleVisitor(); var result = businessRule.Accept(visitor); ``` #### Safe Parsing with TryParse ```csharp // Use TryParse for error handling if (Markdown.TryParse("x.Age > 18", out var expression)) { Console.WriteLine("Parsed successfully!"); // Use the expression var result = expression.Accept(myVisitor); } else { Console.WriteLine("Failed to parse expression"); } ``` #### Real-World Example ```csharp // Define a rule in markdown documentation var ruleMarkdown = @" # User Eligibility Rule The user must meet one of the following conditions: \`\`\`math (\text{user.Age} > 18 \land \text{user.AccountStatus} = \text{active}) \lor (\text{user.Role} = \text{admin}) \`\`\` "; // Extract and parse the math block var mathContent = ExtractMathBlock(ruleMarkdown); // Your extraction logic var eligibilityRule = Markdown.Parse(mathContent); // Apply the rule public class EligibilityChecker : IVisitor { private readonly User _user; public EligibilityChecker(User user) => _user = user; public bool VisitAnd(And expression) => expression.Left.Accept(this) && expression.Right.Accept(this); public bool VisitOr(Or expression) => expression.Left.Accept(this) || expression.Right.Accept(this); public bool VisitEqual(Equal expression) { var left = expression.Left.Accept(new PropertyEvaluator(_user)); var right = expression.Right.Accept(new LiteralEvaluator()); return Equals(left, right); } // ... other visitor methods } // Check eligibility var checker = new EligibilityChecker(currentUser); bool isEligible = eligibilityRule.Accept(checker); ``` ### Benefits of Using Markdown Parser 1. **Documentation and Code Alignment**: Keep rule documentation and implementation in sync 2. **Human-Readable Rules**: Write business rules in a format that non-developers can understand 3. **LaTeX Support**: Use standard mathematical notation for complex logical expressions 4. **Easy Testing**: Write test cases using readable markdown expressions 5. **Version Control Friendly**: Track rule changes in readable text format