整体设计思路
- 解析字符串:使用解析库将字符串解析成抽象语法树(AST),以表示条件逻辑。
- 求值AST:遍历AST,根据变量值对条件进行求值。
- 性能优化:缓存变量值,避免重复计算;在解析过程中尽量减少不必要的内存分配。
关键代码片段
use pest::Parser;
// 定义语法规则
#[derive(Parser)]
#[grammar = "condition.pest"]
struct ConditionParser;
// 条件表达式的AST节点
enum ConditionNode {
Variable(String),
Integer(i32),
Boolean(bool),
Equal(Box<ConditionNode>, Box<ConditionNode>),
And(Box<ConditionNode>, Box<ConditionNode>),
// 可以根据需要添加更多逻辑操作符和节点类型
}
// 从Pest AST转换为自定义AST
fn transform_ast(ast: pest::iterators::Pair<Rule>) -> ConditionNode {
match ast.as_rule() {
Rule::variable => ConditionNode::Variable(ast.as_str().to_string()),
Rule::integer => ConditionNode::Integer(ast.as_str().parse().unwrap()),
Rule::boolean => ConditionNode::Boolean(ast.as_str() == "true"),
Rule::equal => {
let mut children = ast.into_inner();
let left = transform_ast(children.next().unwrap());
let right = transform_ast(children.next().unwrap());
ConditionNode::Equal(Box::new(left), Box::new(right))
}
Rule::and => {
let mut children = ast.into_inner();
let left = transform_ast(children.next().unwrap());
let right = transform_ast(children.next().unwrap());
ConditionNode::And(Box::new(left), Box::new(right))
}
_ => unreachable!(),
}
}
// 求值AST
fn evaluate_ast(node: &ConditionNode, variables: &HashMap<String, ConditionNode>) -> bool {
match node {
ConditionNode::Variable(name) => evaluate_ast(variables.get(name).unwrap(), variables),
ConditionNode::Integer(_) | ConditionNode::Boolean(_) => match node {
ConditionNode::Integer(i) => *i == 0,
ConditionNode::Boolean(b) => *b,
_ => unreachable!(),
},
ConditionNode::Equal(left, right) => evaluate_ast(left, variables) == evaluate_ast(right, variables),
ConditionNode::And(left, right) => evaluate_ast(left, variables) && evaluate_ast(right, variables),
}
}
fn main() {
let rules_str = read_rules_from_config();
let parsed = ConditionParser::parse(Rule::condition, &rules_str).expect("Failed to parse");
let ast = transform_ast(parsed.next().unwrap());
let mut variables = HashMap::new();
variables.insert("var1".to_string(), ConditionNode::Integer(5));
variables.insert("var2".to_string(), ConditionNode::Boolean(true));
let result = evaluate_ast(&ast, &variables);
println!("Result: {}", result);
}
说明
pest
库:用于解析字符串为AST,condition.pest
文件定义了条件逻辑的语法规则。
- 自定义AST:
ConditionNode
枚举表示自定义的AST节点,方便求值。
- 求值函数:
evaluate_ast
函数递归遍历AST,根据变量值计算条件结果。
- 变量管理:
variables
哈希表存储变量值,在求值时使用。