package expression import ( "errors" "strconv" "strings" "unicode" ) // Deprecated: 待优化, 简单表达式解析与求值器,支持变量、比较运算符和逻辑运算符 type Parser struct { expr string pos int } type Node interface { Eval(vars map[string]interface{}) (bool, error) } type numberNode struct{ val float64 } type boolNode struct{ val bool } type varNode struct{ name string } type binaryNode struct { op string left, right Node } type compareNode struct { op string left, right Node } type logicNode struct { op string left, right Node } type unaryNode struct { op string operand Node } // NewParser 创建解析器 func Parse(expr string) (*Parser, error) { expr = strings.ReplaceAll(expr, " ", "") // 去除空格 if expr == "" { return nil, errors.New("表达式为空") } return &Parser{expr: expr}, nil } // 解析并返回 AST 根节点 func (p *Parser) Parse() (Node, error) { node, err := p.parseLogicOr() if err != nil { return nil, err } if p.pos != len(p.expr) { return nil, errors.New("表达式末尾有多余字符") } return node, nil } // ====================== 解析层级 ====================== func (p *Parser) parseLogicOr() (Node, error) { left, err := p.parseLogicAnd() if err != nil { return nil, err } for p.pos < len(p.expr) && p.substr(p.pos, 2) == "||" { p.pos += 2 right, err := p.parseLogicAnd() if err != nil { return nil, err } left = &logicNode{op: "||", left: left, right: right} } return left, nil } func (p *Parser) parseLogicAnd() (Node, error) { left, err := p.parseComparison() if err != nil { return nil, err } for p.pos < len(p.expr) && p.substr(p.pos, 2) == "&&" { p.pos += 2 right, err := p.parseComparison() if err != nil { return nil, err } left = &logicNode{op: "&&", left: left, right: right} } return left, nil } func (p *Parser) parseComparison() (Node, error) { left, err := p.parseExpression() if err != nil { return nil, err } ops := []string{">=", "<=", "==", "!=", ">", "<"} var op string for _, candidate := range ops { if p.substr(p.pos, len(candidate)) == candidate { op = candidate p.pos += len(candidate) break } } if op != "" { right, err := p.parseExpression() if err != nil { return nil, err } return &compareNode{op: op, left: left, right: right}, nil } return left, nil } func (p *Parser) parseExpression() (Node, error) { left, err := p.parseTerm() if err != nil { return nil, err } for p.pos < len(p.expr) && (p.current() == '+' || p.current() == '-') { op := string(p.current()) p.pos++ right, err := p.parseTerm() if err != nil { return nil, err } left = &binaryNode{op: op, left: left, right: right} } return left, nil } func (p *Parser) parseTerm() (Node, error) { left, err := p.parseUnary() if err != nil { return nil, err } for p.pos < len(p.expr) && (p.current() == '*' || p.current() == '/') { op := string(p.current()) p.pos++ right, err := p.parseUnary() if err != nil { return nil, err } left = &binaryNode{op: op, left: left, right: right} } return left, nil } func (p *Parser) parseUnary() (Node, error) { if p.current() == '!' { p.pos++ operand, err := p.parseUnary() if err != nil { return nil, err } return &unaryNode{op: "!", operand: operand}, nil } return p.parseAtom() } func (p *Parser) parseAtom() (Node, error) { ch := p.current() if ch == '(' { p.pos++ node, err := p.parseLogicOr() if err != nil { return nil, err } if p.current() != ')' { return nil, errors.New("缺少右括号") } p.pos++ return node, nil } if unicode.IsDigit(rune(ch)) || ch == '.' || ch == '-' && p.pos+1 < len(p.expr) && (unicode.IsDigit(rune(p.expr[p.pos+1])) || p.expr[p.pos+1] == '.') { return p.parseNumber() } if unicode.IsLetter(rune(ch)) || ch == '_' { return p.parseIdentifierOrBool() } return nil, errors.New("无效字符: " + string(ch)) } func (p *Parser) parseNumber() (Node, error) { start := p.pos if p.current() == '-' { p.pos++ } for p.pos < len(p.expr) && (unicode.IsDigit(rune(p.expr[p.pos])) || p.expr[p.pos] == '.') { p.pos++ } val, err := strconv.ParseFloat(p.expr[start:p.pos], 64) if err != nil { return nil, err } return &numberNode{val: val}, nil } func (p *Parser) parseIdentifierOrBool() (Node, error) { start := p.pos for p.pos < len(p.expr) && (unicode.IsLetter(rune(p.expr[p.pos])) || unicode.IsDigit(rune(p.expr[p.pos])) || p.expr[p.pos] == '_') { p.pos++ } name := p.expr[start:p.pos] if name == "true" { return &boolNode{val: true}, nil } if name == "false" { return &boolNode{val: false}, nil } return &varNode{name: name}, nil } // ====================== 辅助函数 ====================== func (p *Parser) current() byte { if p.pos >= len(p.expr) { return 0 } return p.expr[p.pos] } func (p *Parser) substr(start, length int) string { if start+length > len(p.expr) { return "" } return p.expr[start : start+length] } // ====================== 求值 ====================== func (n *numberNode) Eval(_ map[string]interface{}) (bool, error) { return false, errors.New("数字节点不能直接作为布尔表达式") } func (n *boolNode) Eval(_ map[string]interface{}) (bool, error) { return n.val, nil } func (n *varNode) Eval(vars map[string]interface{}) (bool, error) { val, exists := vars[n.name] if !exists { return false, errors.New("未定义的变量: " + n.name) } switch v := val.(type) { case float64: return v != 0, nil // 数字非零视为 true(可选逻辑) case bool: return v, nil default: return false, errors.New("变量必须是 float64 或 bool") } } func (n *binaryNode) Eval(vars map[string]interface{}) (bool, error) { _, err := evalToFloat(n.left, vars) if err != nil { return false, err } r, err := evalToFloat(n.right, vars) if err != nil { return false, err } switch n.op { case "+": return false, errors.New("二元运算不能直接返回 bool") case "-": return false, errors.New("二元运算不能直接返回 bool") case "*": return false, errors.New("二元运算不能直接返回 bool") case "/": if r == 0 { return false, errors.New("除以零") } return false, errors.New("二元运算不能直接返回 bool") } return false, errors.New("未知运算符") } func (n *compareNode) Eval(vars map[string]interface{}) (bool, error) { l, err := evalToFloat(n.left, vars) if err != nil { return false, err } r, err := evalToFloat(n.right, vars) if err != nil { return false, err } switch n.op { case ">": return l > r, nil case "<": return l < r, nil case "==": return l == r, nil case ">=": return l >= r, nil case "<=": return l <= r, nil case "!=": return l != r, nil } return false, errors.New("未知比较符") } func (n *logicNode) Eval(vars map[string]interface{}) (bool, error) { l, err := evalToBool(n.left, vars) if err != nil { return false, err } r, err := evalToBool(n.right, vars) if err != nil { return false, err } if n.op == "&&" { return l && r, nil } return l || r, nil } func (n *unaryNode) Eval(vars map[string]interface{}) (bool, error) { val, err := evalToBool(n.operand, vars) if err != nil { return false, err } return !val, nil } // 辅助求值函数 func evalToFloat(node Node, vars map[string]interface{}) (float64, error) { // 简化实现:这里假设算术表达式最终求值后用于比较 // 实际项目中可扩展返回 interface{} switch n := node.(type) { case *numberNode: return n.val, nil case *varNode: if v, ok := vars[n.name].(float64); ok { return v, nil } return 0, errors.New("变量不是数字") case *binaryNode: l, _ := evalToFloat(n.left, vars) r, _ := evalToFloat(n.right, vars) switch n.op { case "+": return l + r, nil case "-": return l - r, nil case "*": return l * r, nil case "/": if r == 0 { return 0, errors.New("除以零") } return l / r, nil } } return 0, errors.New("无法求值为数字") } func evalToBool(node Node, vars map[string]interface{}) (bool, error) { return node.Eval(vars) } // ====================== 使用示例 ====================== func Evaluate(expr string, vars map[string]interface{}) (bool, error) { p, err := Parse(expr) if err != nil { return false, err } ast, err := p.Parse() if err != nil { return false, err } return ast.Eval(vars) }