pub struct GRLParser;Expand description
Simple GRL Parser for parsing rule files
Implementationsยง
Sourceยงimpl GRLParser
impl GRLParser
Sourcepub fn parse_rules(content: &str) -> Result<Vec<Rule>>
pub fn parse_rules(content: &str) -> Result<Vec<Rule>>
Parse a complete GRL file content into rules
Examples found in repository?
examples/debug_conditions.rs (line 21)
9fn test_simple_conditions() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Testing Simple Conditions ===");
11
12 // Create Knowledge Base
13 let kb = KnowledgeBase::new("TestConditions");
14
15 // Test compound condition with &&
16 let compound_rule = r#"rule "CompoundRule" { when TestCar.speedUp == true && TestCar.speed < TestCar.maxSpeed then TestCar.result = "compound_fired"; }"#;
17
18 println!("Testing rule: {}", compound_rule);
19
20 // Parse and add rule
21 let rules = GRLParser::parse_rules(compound_rule)?;
22 let rule = rules.into_iter().next().unwrap();
23 println!("Parsed rule: {:?}", rule);
24
25 let _ = kb.add_rule(rule);
26
27 // Create engine with debug mode
28 let config = EngineConfig {
29 max_cycles: 10,
30 timeout: None,
31 enable_stats: true,
32 debug_mode: true,
33 };
34 let engine = RustRuleEngine::with_config(kb, config);
35
36 // Create facts
37 let facts = Facts::new();
38
39 // Create simple TestCar object with all needed properties
40 let test_car = FactHelper::create_object(vec![
41 ("speedUp", Value::Boolean(true)),
42 ("speed", Value::Number(30.0)),
43 ("maxSpeed", Value::Number(100.0)),
44 ("result", Value::String("not_fired".to_string())),
45 ]);
46
47 facts.add_value("TestCar", test_car)?;
48
49 println!("\n๐ Before execution:");
50 if let Some(car) = facts.get("TestCar") {
51 println!(" TestCar.speedUp = {:?}", car.get_property("speedUp"));
52 println!(" TestCar.speed = {:?}", car.get_property("speed"));
53 println!(" TestCar.maxSpeed = {:?}", car.get_property("maxSpeed"));
54 println!(" TestCar.result = {:?}", car.get_property("result"));
55 }
56
57 // Execute rules
58 println!("\n๐ Executing rule...");
59 let result = engine.execute(&facts)?;
60
61 println!("Rules fired: {}", result.rules_fired);
62
63 println!("\n๐ After execution:");
64 if let Some(car) = facts.get("TestCar") {
65 println!(" TestCar.speedUp = {:?}", car.get_property("speedUp"));
66 println!(" TestCar.result = {:?}", car.get_property("result"));
67 }
68
69 Ok(())
70}More examples
examples/advanced_method_calls.rs (line 22)
9fn demo_method_calls() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Demo: Advanced Method Calls ===");
11
12 // Create Knowledge Base
13 let kb = KnowledgeBase::new("MethodCallsDemo");
14
15 // Define rule with simpler condition first
16 let speedup_rule = r#"rule "SpeedUp" salience 10 {
17 when TestCar.speedUp == true
18 then TestCar.Speed = 70;
19 }"#;
20
21 // Parse and add rule
22 let rules = GRLParser::parse_rules(speedup_rule)?;
23 let rule = rules.into_iter().next().unwrap();
24 let _ = kb.add_rule(rule);
25
26 // Create engine with debug mode
27 let config = EngineConfig {
28 max_cycles: 10,
29 timeout: None,
30 enable_stats: true,
31 debug_mode: true,
32 };
33 let engine = RustRuleEngine::with_config(kb, config);
34
35 // Create facts
36 let facts = Facts::new();
37
38 // Create TestCar object using helper
39 let test_car = FactHelper::create_test_car(
40 true, // speedUp
41 50.0, // speed
42 100.0, // maxSpeed
43 10.0, // speedIncrement
44 );
45
46 // Create DistanceRecord object using helper
47 let distance_record = FactHelper::create_distance_record(0.0);
48
49 // Add facts
50 facts.add_value("TestCar", test_car)?;
51 facts.add_value("DistanceRecord", distance_record)?;
52
53 println!("\n๐ Initial state:");
54 if let Some(car) = facts.get("TestCar") {
55 if let Some(speed) = car.get_property("Speed") {
56 println!(" TestCar.Speed = {:?}", speed);
57 }
58 if let Some(speed_up) = car.get_property("speedUp") {
59 println!(" TestCar.speedUp = {:?}", speed_up);
60 }
61 }
62
63 // Execute rules multiple cycles to see progression
64 println!("\n๐ Executing SpeedUp rule multiple times...");
65 for i in 1..=3 {
66 println!("\n--- Cycle {} ---", i);
67 let result = engine.execute(&facts)?;
68
69 println!("Rules fired: {}", result.rules_fired);
70
71 if let Some(car) = facts.get("TestCar") {
72 if let Some(speed) = car.get_property("Speed") {
73 println!("TestCar.Speed after cycle {}: {:?}", i, speed);
74 }
75 }
76
77 // Check if we reached max speed
78 if let Some(car) = facts.get("TestCar") {
79 if let Some(speed) = car.get_property("speed") {
80 if let Some(max_speed) = car.get_property("maxSpeed") {
81 if speed.to_number() >= max_speed.to_number() {
82 println!("๐ Max speed reached!");
83 break;
84 }
85 }
86 }
87 }
88 }
89
90 println!("\n๐ Final Results:");
91 if let Some(car) = facts.get("TestCar") {
92 if let Some(speed) = car.get_property("Speed") {
93 println!(" Final TestCar.Speed = {:?}", speed);
94 }
95 }
96
97 Ok(())
98}examples/method_calls_demo.rs (line 48)
9fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
10 println!("๐ฏ Method Calls Demo with Rule File");
11 println!("===================================\n");
12
13 // Read rules from file
14 let rule_file_path = "examples/rules/method_calls.grl";
15 println!("๐ Reading rules from file: {}", rule_file_path);
16
17 let rule_content = fs::read_to_string(rule_file_path)
18 .map_err(|e| format!("Failed to read rule file: {}", e))?;
19
20 println!("๐ Rule file content:");
21 println!("---");
22 println!("{}", rule_content);
23 println!("---\n");
24
25 // Create facts
26 let facts = Facts::new();
27
28 // TestCar data
29 let mut test_car_props = HashMap::new();
30 test_car_props.insert("Speed".to_string(), Value::Number(30.0));
31 test_car_props.insert("MaxSpeed".to_string(), Value::Number(100.0));
32 test_car_props.insert("SpeedIncrement".to_string(), Value::Number(10.0));
33 test_car_props.insert("SpeedUp".to_string(), Value::Boolean(true));
34
35 facts.add_value("TestCar", Value::Object(test_car_props))?;
36
37 println!("๐ Initial state:");
38 if let Some(car) = facts.get("TestCar") {
39 println!(" TestCar = {car:?}");
40 }
41 println!();
42
43 // Create knowledge base and add rules from GRL file
44 let kb = KnowledgeBase::new("MethodCallsDemo");
45
46 // Parse rules from GRL file
47 println!("๐ง Parsing GRL file content...");
48 let rules = GRLParser::parse_rules(&rule_content)
49 .map_err(|e| format!("Failed to parse GRL file: {:?}", e))?;
50
51 println!("โ
Successfully parsed {} rules from file", rules.len());
52 for rule in &rules {
53 println!(" ๐ Rule: {} (salience: {})", rule.name, rule.salience);
54 let _ = kb.add_rule(rule.clone());
55 }
56 println!();
57
58 // Create engine
59 let config = EngineConfig {
60 debug_mode: true,
61 max_cycles: 5,
62 ..Default::default()
63 };
64 let mut engine = RustRuleEngine::with_config(kb, config);
65
66 // Register custom functions for speed control
67 engine.register_function("increaseSpeed", |_args, facts| {
68 if let Some(car) = facts.get("TestCar") {
69 if let Value::Object(obj) = car {
70 let current_speed = obj.get("Speed").cloned().unwrap_or(Value::Number(0.0));
71 let increment = obj
72 .get("SpeedIncrement")
73 .cloned()
74 .unwrap_or(Value::Number(10.0));
75
76 if let (Value::Number(speed), Value::Number(inc)) = (current_speed, increment) {
77 let new_speed = speed + inc;
78 println!("๐ Increasing speed: {} -> {}", speed, new_speed);
79 // In real implementation, this would update the fact
80 return Ok(Value::Number(new_speed));
81 }
82 }
83 }
84 Ok(Value::String("Speed increase attempted".to_string()))
85 });
86
87 engine.register_function("decreaseSpeed", |_args, facts| {
88 if let Some(car) = facts.get("TestCar") {
89 if let Value::Object(obj) = car {
90 let current_speed = obj.get("Speed").cloned().unwrap_or(Value::Number(0.0));
91 let increment = obj
92 .get("SpeedIncrement")
93 .cloned()
94 .unwrap_or(Value::Number(10.0));
95
96 if let (Value::Number(speed), Value::Number(inc)) = (current_speed, increment) {
97 let new_speed = (speed - inc).max(0.0);
98 println!("๐ Decreasing speed: {} -> {}", speed, new_speed);
99 // In real implementation, this would update the fact
100 return Ok(Value::Number(new_speed));
101 }
102 }
103 }
104 Ok(Value::String("Speed decrease attempted".to_string()))
105 });
106
107 // Execute rules
108 println!("๐ Executing method calls rules from file...");
109 let result = engine.execute(&facts)?;
110
111 println!("\n๐ Method Calls Execution Results:");
112 println!(" Cycles: {}", result.cycle_count);
113 println!(" Rules evaluated: {}", result.rules_evaluated);
114 println!(" Rules fired: {}", result.rules_fired);
115 println!(" Execution time: {:?}", result.execution_time);
116
117 println!("\n๐ Final state:");
118 if let Some(car) = facts.get("TestCar") {
119 println!(" TestCar = {car:?}");
120 }
121
122 println!("\n๐ฏ Method Calls from Rule File Demonstrated:");
123 println!(" ๐ Rules defined in external .grl file");
124 println!(" ๐ง Method calls: setSpeed(), setSpeedUp()");
125 println!(" ๐ Custom functions: increaseSpeed(), decreaseSpeed()");
126 println!(" ๐ Speed control simulation");
127 println!(" โก Salience-based rule execution order");
128
129 Ok(())
130}examples/complete_speedup_demo.rs (line 33)
9fn demo_complete_speedup_rule() -> std::result::Result<(), Box<dyn Error>> {
10 println!("=== Demo: Complete SpeedUp Rule with Method Calls ===");
11 println!("Implementing the exact rule from the requirement:");
12 println!("rule \"SpeedUp\" salience 10");
13 println!("when");
14 println!(" $TestCar : TestCarClass( speedUp == true && speed < maxSpeed )");
15 println!(" $DistanceRecord : DistanceRecordClass()");
16 println!("then");
17 println!(" $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement);");
18 println!(" update($TestCar);");
19 println!(" $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed);");
20 println!(" update($DistanceRecord);");
21 println!("end\n");
22
23 // Create Knowledge Base
24 let kb = KnowledgeBase::new("SpeedUpDemo");
25
26 // For now, we'll use a simplified version that works with our current parser
27 let speedup_rule = r#"rule "SpeedUp" salience 10 {
28 when TestCar.speedUp == true && TestCar.speed < TestCar.maxSpeed
29 then $TestCar.setSpeed($TestCar.Speed + $TestCar.SpeedIncrement); update($TestCar); $DistanceRecord.setTotalDistance($DistanceRecord.getTotalDistance() + $TestCar.Speed); update($DistanceRecord);
30 }"#;
31
32 // Parse and add rule
33 let rules = GRLParser::parse_rules(speedup_rule)?;
34 let rule = rules.into_iter().next().unwrap();
35 let _ = kb.add_rule(rule);
36
37 // Create engine with debug mode
38 let config = EngineConfig {
39 max_cycles: 10,
40 timeout: None,
41 enable_stats: true,
42 debug_mode: true,
43 };
44 let engine = RustRuleEngine::with_config(kb, config);
45
46 // Create facts
47 let facts = Facts::new();
48
49 // Create TestCar object - initial speed less than max
50 let test_car = FactHelper::create_test_car(
51 true, // speedUp
52 30.0, // speed (less than maxSpeed)
53 100.0, // maxSpeed
54 15.0, // speedIncrement
55 );
56
57 // Create DistanceRecord object
58 let distance_record = FactHelper::create_distance_record(0.0);
59
60 // Add facts
61 facts.add_value("TestCar", test_car)?;
62 facts.add_value("DistanceRecord", distance_record)?;
63
64 println!("๐ Initial state:");
65 if let Some(car) = facts.get("TestCar") {
66 println!(
67 " TestCar.speed = {:?}",
68 car.get_property("speed").unwrap_or(Value::Null)
69 );
70 println!(
71 " TestCar.Speed = {:?}",
72 car.get_property("Speed").unwrap_or(Value::Null)
73 );
74 println!(
75 " TestCar.maxSpeed = {:?}",
76 car.get_property("maxSpeed").unwrap_or(Value::Null)
77 );
78 println!(
79 " TestCar.speedUp = {:?}",
80 car.get_property("speedUp").unwrap_or(Value::Null)
81 );
82 println!(
83 " TestCar.SpeedIncrement = {:?}",
84 car.get_property("SpeedIncrement").unwrap_or(Value::Null)
85 );
86 }
87 if let Some(record) = facts.get("DistanceRecord") {
88 println!(
89 " DistanceRecord.TotalDistance = {:?}",
90 record.get_property("TotalDistance").unwrap_or(Value::Null)
91 );
92 }
93
94 // Execute rules multiple cycles
95 println!("\n๐ Executing SpeedUp rule...");
96 for i in 1..=5 {
97 println!("\n--- Cycle {} ---", i);
98 let result = engine.execute(&facts)?;
99
100 println!("Rules fired: {}", result.rules_fired);
101
102 if let Some(car) = facts.get("TestCar") {
103 println!(
104 "TestCar.Speed = {:?}",
105 car.get_property("Speed").unwrap_or(Value::Null)
106 );
107 println!(
108 "TestCar.speed = {:?}",
109 car.get_property("speed").unwrap_or(Value::Null)
110 );
111 }
112 if let Some(record) = facts.get("DistanceRecord") {
113 println!(
114 "DistanceRecord.TotalDistance = {:?}",
115 record.get_property("TotalDistance").unwrap_or(Value::Null)
116 );
117 }
118
119 // Check if we reached max speed
120 if let Some(car) = facts.get("TestCar") {
121 if let Some(speed) = car.get_property("speed") {
122 if let Some(max_speed) = car.get_property("maxSpeed") {
123 if speed.to_number() >= max_speed.to_number() {
124 println!("๐ Max speed reached! Rule will no longer fire.");
125 break;
126 }
127 }
128 }
129 }
130
131 if result.rules_fired == 0 {
132 println!("โน๏ธ No rules fired this cycle.");
133 break;
134 }
135 }
136
137 println!("\n๐ Final Summary:");
138 println!("โ
Successfully demonstrated method calls in GRL:");
139 println!(" โข Method calls: $Object.method(args)");
140 println!(" โข Property access: $Object.Property");
141 println!(" โข Arithmetic expressions: $A.prop + $B.prop");
142 println!(" โข update() function calls");
143 println!(" โข Complex conditions with && operator");
144
145 Ok(())
146}examples/inline_rules_demo.rs (line 91)
8fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
9 println!("๐ฏ Inline GRL Rules Demo");
10 println!("========================\n");
11
12 // Define rules directly in code as strings
13 let grl_rules = r#"
14 rule "HighValueCustomer" salience 20 {
15 when
16 Customer.TotalSpent > 1000.0
17 then
18 sendWelcomeEmail(Customer.Email, "GOLD");
19 log("Customer upgraded to GOLD tier");
20 }
21
22 rule "LoyaltyBonus" salience 15 {
23 when
24 Customer.OrderCount >= 10
25 then
26 applyLoyaltyBonus(Customer.Id, 50.0);
27 log("Loyalty bonus applied");
28 }
29
30 rule "NewCustomerWelcome" salience 10 {
31 when
32 Customer.IsNew == false
33 then
34 sendWelcomeEmail(Customer.Email, "EXISTING");
35 log("Welcome email sent to existing customer");
36 }
37
38 rule "LowRiskTransaction" salience 5 {
39 when
40 Transaction.Amount < 1000.0
41 then
42 log("Low-risk transaction processed");
43 }
44 "#;
45
46 println!("๐ Inline GRL Rules:");
47 println!("---");
48 println!("{}", grl_rules.trim());
49 println!("---\n");
50
51 // Create facts
52 let facts = Facts::new();
53
54 // Customer data
55 let mut customer_props = HashMap::new();
56 customer_props.insert("Id".to_string(), Value::String("CUST001".to_string()));
57 customer_props.insert(
58 "Email".to_string(),
59 Value::String("john.doe@example.com".to_string()),
60 );
61 customer_props.insert("TotalSpent".to_string(), Value::Number(1250.0)); // Qualifies for GOLD
62 customer_props.insert("YearsActive".to_string(), Value::Integer(4)); // Long-time customer
63 customer_props.insert("OrderCount".to_string(), Value::Integer(12)); // Qualifies for loyalty
64 customer_props.insert("Tier".to_string(), Value::String("SILVER".to_string()));
65 customer_props.insert("IsNew".to_string(), Value::Boolean(false));
66 customer_props.insert("RiskScore".to_string(), Value::Integer(35)); // Low risk
67 customer_props.insert("WelcomeEmailSent".to_string(), Value::Boolean(false));
68
69 // Transaction data
70 let mut transaction_props = HashMap::new();
71 transaction_props.insert("Id".to_string(), Value::String("TXN001".to_string()));
72 transaction_props.insert("Amount".to_string(), Value::Number(750.0)); // Normal amount
73 transaction_props.insert("Currency".to_string(), Value::String("USD".to_string()));
74
75 facts.add_value("Customer", Value::Object(customer_props))?;
76 facts.add_value("Transaction", Value::Object(transaction_props))?;
77
78 println!("๐ Initial state:");
79 if let Some(customer) = facts.get("Customer") {
80 println!(" Customer = {customer:?}");
81 }
82 if let Some(transaction) = facts.get("Transaction") {
83 println!(" Transaction = {transaction:?}");
84 }
85 println!();
86
87 // Create knowledge base and parse inline rules
88 let kb = KnowledgeBase::new("InlineRulesDemo");
89
90 println!("๐ง Parsing inline GRL rules...");
91 let parsed_rules = GRLParser::parse_rules(grl_rules)
92 .map_err(|e| format!("Failed to parse inline GRL rules: {:?}", e))?;
93
94 println!(
95 "โ
Successfully parsed {} rules from inline strings",
96 parsed_rules.len()
97 );
98 for rule in parsed_rules {
99 println!(" ๐ Rule: {} (salience: {})", rule.name, rule.salience);
100 let _ = kb.add_rule(rule);
101 }
102 println!();
103
104 // Create engine with configuration
105 let config = EngineConfig {
106 debug_mode: true,
107 max_cycles: 2,
108 ..Default::default()
109 };
110 let mut engine = RustRuleEngine::with_config(kb, config);
111
112 // Register custom functions called from the inline rules
113 println!("๐ Registering custom functions for inline rules...");
114
115 // Customer tier management
116 engine.register_function("Customer.setTier", |args, _facts| {
117 let new_tier = args.get(0).unwrap().to_string();
118
119 let result = format!("๐ Customer tier updated to: {}", new_tier);
120 println!(" {}", result);
121 Ok(Value::String(result))
122 });
123
124 // Email service
125 engine.register_function("sendWelcomeEmail", |args, _facts| {
126 let email = args.get(0).unwrap().to_string();
127 let tier = args.get(1).unwrap().to_string();
128
129 let result = format!("๐ง Welcome email sent to {} for {} tier", email, tier);
130 println!(" {}", result);
131 Ok(Value::String(result))
132 });
133
134 // Loyalty system
135 engine.register_function("applyLoyaltyBonus", |args, _facts| {
136 let customer_id = args.get(0).unwrap().to_string();
137 let bonus_amount = args.get(1).unwrap();
138
139 let result = format!(
140 "๐ฐ Loyalty bonus of {:?} applied to customer {}",
141 bonus_amount, customer_id
142 );
143 println!(" {}", result);
144 Ok(Value::String(result))
145 });
146
147 // Security functions
148 engine.register_function("flagForReview", |args, _facts| {
149 let transaction_id = args.get(0).unwrap().to_string();
150
151 let result = format!(
152 "๐จ Transaction {} flagged for manual review",
153 transaction_id
154 );
155 println!(" {}", result);
156 Ok(Value::String(result))
157 });
158
159 engine.register_function("notifySecurityTeam", |args, _facts| {
160 let customer_id = args.get(0).unwrap().to_string();
161 let amount = args.get(1).unwrap();
162
163 let result = format!(
164 "๐ Security team notified: Customer {} - Amount {:?}",
165 customer_id, amount
166 );
167 println!(" {}", result);
168 Ok(Value::String(result))
169 });
170
171 // Customer status updates
172 engine.register_function("Customer.setWelcomeEmailSent", |args, _facts| {
173 let sent = args.get(0).unwrap();
174
175 let result = format!("โ
Welcome email status updated: {:?}", sent);
176 println!(" {}", result);
177 Ok(Value::String(result))
178 });
179
180 println!("โ
Registered 6 custom functions for inline rules:");
181 println!(" ๐ Customer.setTier");
182 println!(" ๐ง sendWelcomeEmail");
183 println!(" ๐ฐ applyLoyaltyBonus");
184 println!(" ๐จ flagForReview");
185 println!(" ๐ notifySecurityTeam");
186 println!(" โ
Customer.setWelcomeEmailSent");
187 println!();
188
189 // Execute the inline rules
190 println!("๐ Executing inline GRL rules...");
191 let result = engine.execute(&facts)?;
192
193 println!("\n๐ Inline Rules Execution Results:");
194 println!(" Cycles: {}", result.cycle_count);
195 println!(" Rules evaluated: {}", result.rules_evaluated);
196 println!(" Rules fired: {}", result.rules_fired);
197 println!(" Execution time: {:?}", result.execution_time);
198
199 println!("\n๐ Final state:");
200 if let Some(customer) = facts.get("Customer") {
201 println!(" Customer = {customer:?}");
202 }
203 if let Some(transaction) = facts.get("Transaction") {
204 println!(" Transaction = {transaction:?}");
205 }
206
207 println!("\n๐ฏ Inline GRL Rules Demonstrated:");
208 println!(" ๐ Rules defined as strings directly in code");
209 println!(" ๐ง No external files needed");
210 println!(" โก Quick prototyping and testing");
211 println!(" ๐ Customer tier management");
212 println!(" ๐ฐ Loyalty bonus system");
213 println!(" ๐ Security and fraud detection");
214 println!(" ๐ง Email notification system");
215
216 Ok(())
217}examples/rule_file_functions_demo.rs (line 58)
9fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
10 println!("๐ฏ Custom Functions from Rule File Demo");
11 println!("=======================================\n");
12
13 // Read rules from file
14 let rule_file_path = "examples/rules/car_functions.grl";
15 println!("๐ Reading rules from file: {}", rule_file_path);
16
17 let rule_content = fs::read_to_string(rule_file_path)
18 .map_err(|e| format!("Failed to read rule file: {}", e))?;
19
20 println!("๐ Rule file content:");
21 println!("---");
22 println!("{}", rule_content);
23 println!("---\n");
24
25 // Create facts
26 let facts = Facts::new();
27
28 // Car data - set speed > 80 to trigger speed limit rule
29 let mut car_props = HashMap::new();
30 car_props.insert("Speed".to_string(), Value::Number(95.0)); // Above speed limit
31 car_props.insert("MaxSpeed".to_string(), Value::Number(120.0));
32 car_props.insert("Engine".to_string(), Value::String("V6".to_string()));
33 car_props.insert("IsRunning".to_string(), Value::Boolean(true));
34
35 // Driver data
36 let mut driver_props = HashMap::new();
37 driver_props.insert("Name".to_string(), Value::String("John Doe".to_string()));
38 driver_props.insert("Experience".to_string(), Value::Integer(7)); // Experienced driver
39 driver_props.insert("License".to_string(), Value::String("VALID".to_string()));
40
41 facts.add_value("Car", Value::Object(car_props))?;
42 facts.add_value("Driver", Value::Object(driver_props))?;
43
44 println!("๐ Initial state:");
45 if let Some(car) = facts.get("Car") {
46 println!(" Car = {car:?}");
47 }
48 if let Some(driver) = facts.get("Driver") {
49 println!(" Driver = {driver:?}");
50 }
51 println!();
52
53 // Create knowledge base
54 let mut kb = KnowledgeBase::new("RuleFileDemo");
55
56 // Parse GRL file and add rules to knowledge base
57 println!("๐ง Parsing GRL file content...");
58 let parsed_rules = SimpleGRLParser::parse_rules(&rule_content)
59 .map_err(|e| format!("Failed to parse GRL file: {:?}", e))?;
60
61 println!(
62 "โ
Successfully parsed {} rules from file",
63 parsed_rules.len()
64 );
65 for rule in parsed_rules {
66 println!(" ๐ Rule: {} (salience: {})", rule.name, rule.salience);
67 let _ = kb.add_rule(rule);
68 }
69 println!();
70
71 // Create engine
72 let config = EngineConfig {
73 debug_mode: true,
74 max_cycles: 3,
75 ..Default::default()
76 };
77 let mut engine = RustRuleEngine::with_config(kb, config);
78
79 // Register all custom functions called from the rule file
80 println!("๐ Registering custom functions from rule file...");
81
82 // Functions from SpeedLimitCheck rule
83 engine.register_function("checkSpeedLimit", |args, facts| {
84 let speed_field = args.get(0).unwrap().to_string();
85 let limit = args.get(1).unwrap();
86
87 let speed = if let Some(car) = facts.get("Car") {
88 if let Value::Object(obj) = car {
89 obj.get("Speed").cloned().unwrap_or(Value::Number(0.0))
90 } else {
91 Value::Number(0.0)
92 }
93 } else {
94 Value::Number(0.0)
95 };
96
97 let result = format!("๐ฆ Speed check: {:?} vs limit {:?}", speed, limit);
98 println!("{}", result);
99 Ok(Value::String(result))
100 });
101
102 engine.register_function("sendAlert", |args, facts| {
103 let message = args.get(0).unwrap().to_string();
104 let driver_field = args.get(1).unwrap().to_string();
105
106 let driver_name = if let Some(driver) = facts.get("Driver") {
107 if let Value::Object(obj) = driver {
108 obj.get("Name")
109 .cloned()
110 .unwrap_or(Value::String("Unknown".to_string()))
111 } else {
112 Value::String("Unknown".to_string())
113 }
114 } else {
115 Value::String("Unknown".to_string())
116 };
117
118 let alert = format!("๐จ ALERT to {:?}: {}", driver_name, message);
119 println!("{}", alert);
120 Ok(Value::String(alert))
121 });
122
123 // Functions from DriverValidation rule
124 engine.register_function("validateDriver", |args, _facts| {
125 let name_field = args.get(0).unwrap().to_string();
126 let exp_field = args.get(1).unwrap().to_string();
127
128 let result = format!(
129 "โ
Driver validation: {} (experience: {})",
130 name_field, exp_field
131 );
132 println!("{}", result);
133 Ok(Value::String(result))
134 });
135
136 engine.register_function("calculateInsurance", |args, _facts| {
137 let exp_field = args.get(0).unwrap().to_string();
138 let engine_field = args.get(1).unwrap().to_string();
139
140 let result = format!(
141 "๐ฐ Insurance: Experience {} + Engine {} = Premium",
142 exp_field, engine_field
143 );
144 println!("{}", result);
145 Ok(Value::String(result))
146 });
147
148 // Functions from EngineDiagnostics rule
149 engine.register_function("performDiagnostics", |args, _facts| {
150 let engine_field = args.get(0).unwrap().to_string();
151 let speed_field = args.get(1).unwrap().to_string();
152
153 let result = format!(
154 "๐ง Diagnostics: Engine {} at speed {} - OK",
155 engine_field, speed_field
156 );
157 println!("{}", result);
158 Ok(Value::String(result))
159 });
160
161 engine.register_function("optimizePerformance", |args, _facts| {
162 let current_speed = args.get(0).unwrap().to_string();
163 let max_speed = args.get(1).unwrap().to_string();
164
165 let result = format!(
166 "โก Performance: {} / {} - Optimized",
167 current_speed, max_speed
168 );
169 println!("{}", result);
170 Ok(Value::String(result))
171 });
172
173 // Functions from MaintenanceCheck rule
174 engine.register_function("scheduleMaintenanceCheck", |args, _facts| {
175 let engine_field = args.get(0).unwrap().to_string();
176 let exp_field = args.get(1).unwrap().to_string();
177
178 let result = format!(
179 "๐ง Maintenance scheduled: Engine {} (driver exp: {})",
180 engine_field, exp_field
181 );
182 println!("{}", result);
183 Ok(Value::String(result))
184 });
185
186 engine.register_function("updateMaintenanceRecord", |args, _facts| {
187 let name_field = args.get(0).unwrap().to_string();
188 let engine_field = args.get(1).unwrap().to_string();
189
190 let result = format!("๐ Record updated: {} - {}", name_field, engine_field);
191 println!("{}", result);
192 Ok(Value::String(result))
193 });
194
195 println!("โ
Registered {} custom functions from rule file:", 8);
196 println!(" ๐ฆ checkSpeedLimit");
197 println!(" ๐จ sendAlert");
198 println!(" โ
validateDriver");
199 println!(" ๐ฐ calculateInsurance");
200 println!(" ๐ง performDiagnostics");
201 println!(" โก optimizePerformance");
202 println!(" ๐ง scheduleMaintenanceCheck");
203 println!(" ๐ updateMaintenanceRecord");
204 println!();
205
206 // Execute rules
207 println!("๐ Executing rules from file...");
208 let result = engine.execute(&facts)?;
209
210 println!("\n๐ Rule File Execution Results:");
211 println!(" Cycles: {}", result.cycle_count);
212 println!(" Rules evaluated: {}", result.rules_evaluated);
213 println!(" Rules fired: {}", result.rules_fired);
214 println!(" Execution time: {:?}", result.execution_time);
215
216 println!("\n๐ Final state:");
217 if let Some(car) = facts.get("Car") {
218 println!(" Car = {car:?}");
219 }
220 if let Some(driver) = facts.get("Driver") {
221 println!(" Driver = {driver:?}");
222 }
223
224 println!("\n๐ฏ Rule File Custom Functions Demonstrated:");
225 println!(" ๐ Rules defined in external .grl file");
226 println!(" ๐ Custom functions called from rule file");
227 println!(" ๐ง Business logic separated from rule definitions");
228 println!(" ๐ File-based rule management");
229 println!(" โก Function registry with rule file integration");
230
231 Ok(())
232}Auto Trait Implementationsยง
impl Freeze for GRLParser
impl RefUnwindSafe for GRLParser
impl Send for GRLParser
impl Sync for GRLParser
impl Unpin for GRLParser
impl UnwindSafe for GRLParser
Blanket Implementationsยง
Sourceยงimpl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Sourceยงfn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more