解释器模式(Interpreter Pattern)及C++实现

发布于:2025-08-16 ⋅ 阅读:(15) ⋅ 点赞:(0)

解释器模式是一种行为设计模式,它定义了一种语言的文法表示,并提供一个解释器来解释该语言中的句子。这种模式常用于需要解释执行特定领域语言的场景。

解释器模式核心结构
解释器模式包含以下主要角色:

AbstractExpression(抽象表达式):声明一个抽象的解释操作

TerminalExpression(终结符表达式):实现与文法中的终结符相关的解释操作

NonterminalExpression(非终结符表达式):实现文法规则的解释操作

Context(上下文):包含解释器之外的一些全局信息

Client(客户端):构建语法树并调用解释操作

解释器模式典型应用场景
正则表达式引擎

SQL查询解析器

数学表达式计算器

编译器语法分析

业务规则引擎

配置文件解析器

C++实现示例
1. 简单数学表达式计算器

#include <iostream>
#include <string>
#include <unordered_map>
#include <memory>
#include <stack>
#include <stdexcept>

// 抽象表达式
class Expression {
public:
    virtual ~Expression() = default;
    virtual int interpret(std::unordered_map<char, int>& context) = 0;
};

// 终结符表达式:变量
class Variable : public Expression {
public:
    explicit Variable(char name) : name(name) {}
    
    int interpret(std::unordered_map<char, int>& context) override {
        return context[name];
    }

private:
    char name;
};

// 终结符表达式:数字常量
class Number : public Expression {
public:
    explicit Number(int value) : value(value) {}
    
    int interpret(std::unordered_map<char, int>&) override {
        return value;
    }

private:
    int value;
};

// 非终结符表达式:加法
class Add : public Expression {
public:
    Add(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
        : left(std::move(left)), right(std::move(right)) {}
    
    int interpret(std::unordered_map<char, int>& context) override {
        return left->interpret(context) + right->interpret(context);
    }

private:
    std::unique_ptr<Expression> left;
    std::unique_ptr<Expression> right;
};

// 非终结符表达式:减法
class Subtract : public Expression {
public:
    Subtract(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
        : left(std::move(left)), right(std::move(right)) {}
    
    int interpret(std::unordered_map<char, int>& context) override {
        return left->interpret(context) - right->interpret(context);
    }

private:
    std::unique_ptr<Expression> left;
    std::unique_ptr<Expression> right;
};

// 非终结符表达式:乘法
class Multiply : public Expression {
public:
    Multiply(std::unique_ptr<Expression> left, std::unique_ptr<Expression> right)
        : left(std::move(left)), right(std::move(right)) {}
    
    int interpret(std::unordered_map<char, int>& context) override {
        return left->interpret(context) * right->interpret(context);
    }

private:
    std::unique_ptr<Expression> left;
    std::unique_ptr<Expression> right;
};

// 表达式解析器
class Parser {
public:
    std::unique_ptr<Expression> parse(const std::string& expr) {
        std::stack<std::unique_ptr<Expression>> stack;
        
        for (size_t i = 0; i < expr.size(); ++i) {
            char c = expr[i];
            
            if (isdigit(c)) {
                int num = 0;
                while (i < expr.size() && isdigit(expr[i])) {
                    num = num * 10 + (expr[i++] - '0');
                }
                --i;
                stack.push(std::make_unique<Number>(num));
            }
            else if (isalpha(c)) {
                stack.push(std::make_unique<Variable>(c));
            }
            else if (c == '+' || c == '-' || c == '*') {
                if (stack.size() < 2) {
                    throw std::runtime_error("Invalid expression");
                }
                
                auto right = std::move(stack.top()); stack.pop();
                auto left = std::move(stack.top()); stack.pop();
                
                switch (c) {
                    case '+': 
                        stack.push(std::make_unique<Add>(std::move(left), std::move(right)));
                        break;
                    case '-':
                        stack.push(std::make_unique<Subtract>(std::move(left), std::move(right)));
                        break;
                    case '*':
                        stack.push(std::make_unique<Multiply>(std::move(left), std::move(right)));
                        break;
                }
            }
        }
        
        if (stack.size() != 1) {
            throw std::runtime_error("Invalid expression");
        }
        
        return std::move(stack.top());
    }
};

int main() {
    // 上下文:变量值
    std::unordered_map<char, int> context = {
        {'a', 5},
        {'b', 10},
        {'c', 2}
    };
    
    Parser parser;
    
    // 解析并计算表达式
    try {
        // 计算 a + b * c
        auto expr1 = parser.parse("a b c * +");
        std::cout << "a + b * c = " << expr1->interpret(context) << std::endl;
        
        // 计算 (a + b) * c
        auto expr2 = parser.parse("a b + c *");
        std::cout << "(a + b) * c = " << expr2->interpret(context) << std::endl;
        
        // 计算 100 - a * b
        auto expr3 = parser.parse("100 a b * -");
        std::cout << "100 - a * b = " << expr3->interpret(context) << std::endl;
    }
    catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    
    return 0;
}

2. 简单SQL WHERE条件解析器

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <stdexcept>

// 数据库记录类型
using Record = std::unordered_map<std::string, std::string>;

// 抽象表达式
class SQLExpression {
public:
    virtual ~SQLExpression() = default;
    virtual bool evaluate(const Record& record) const = 0;
};

// 终结符表达式:等于比较
class Equals : public SQLExpression {
public:
    Equals(const std::string& field, const std::string& value)
        : field(field), value(value) {}
    
    bool evaluate(const Record& record) const override {
        auto it = record.find(field);
        return it != record.end() && it->second == value;
    }

private:
    std::string field;
    std::string value;
};

// 终结符表达式:大于比较
class GreaterThan : public SQLExpression {
public:
    GreaterThan(const std::string& field, const std::string& value)
        : field(field), value(value) {}
    
    bool evaluate(const Record& record) const override {
        auto it = record.find(field);
        return it != record.end() && it->second > value;
    }

private:
    std::string field;
    std::string value;
};

// 非终结符表达式:AND逻辑
class And : public SQLExpression {
public:
    And(std::unique_ptr<SQLExpression> left, std::unique_ptr<SQLExpression> right)
        : left(std::move(left)), right(std::move(right)) {}
    
    bool evaluate(const Record& record) const override {
        return left->evaluate(record) && right->evaluate(record);
    }

private:
    std::unique_ptr<SQLExpression> left;
    std::unique_ptr<SQLExpression> right;
};

// 非终结符表达式:OR逻辑
class Or : public SQLExpression {
public:
    Or(std::unique_ptr<SQLExpression> left, std::unique_ptr<SQLExpression> right)
        : left(std::move(left)), right(std::move(right)) {}
    
    bool evaluate(const Record& record) const override {
        return left->evaluate(record) || right->evaluate(record);
    }

private:
    std::unique_ptr<SQLExpression> left;
    std::unique_ptr<SQLExpression> right;
};

// 非终结符表达式:NOT逻辑
class Not : public SQLExpression {
public:
    explicit Not(std::unique_ptr<SQLExpression> expr)
        : expr(std::move(expr)) {}
    
    bool evaluate(const Record& record) const override {
        return !expr->evaluate(record);
    }

private:
    std::unique_ptr<SQLExpression> expr;
};

// SQL解析器(简化版)
class SQLParser {
public:
    std::unique_ptr<SQLExpression> parse(const std::string& condition) {
        // 这里简化了解析过程,实际应用中需要更复杂的解析器
        if (condition.find("AND") != std::string::npos) {
            size_t pos = condition.find(" AND ");
            auto left = parse(condition.substr(0, pos));
            auto right = parse(condition.substr(pos + 5));
            return std::make_unique<And>(std::move(left), std::move(right));
        }
        else if (condition.find("OR") != std::string::npos) {
            size_t pos = condition.find(" OR ");
            auto left = parse(condition.substr(0, pos));
            auto right = parse(condition.substr(pos + 4));
            return std::make_unique<Or>(std::move(left), std::move(right));
        }
        else if (condition.find("NOT") != std::string::npos) {
            size_t pos = condition.find("NOT ");
            auto expr = parse(condition.substr(pos + 4));
            return std::make_unique<Not>(std::move(expr));
        }
        else if (condition.find("=") != std::string::npos) {
            size_t pos = condition.find("=");
            std::string field = condition.substr(0, pos);
            std::string value = condition.substr(pos + 1);
            trim(field);
            trim(value);
            return std::make_unique<Equals>(field, value);
        }
        else if (condition.find(">") != std::string::npos) {
            size_t pos = condition.find(">");
            std::string field = condition.substr(0, pos);
            std::string value = condition.substr(pos + 1);
            trim(field);
            trim(value);
            return std::make_unique<GreaterThan>(field, value);
        }
        
        throw std::runtime_error("Invalid SQL condition: " + condition);
    }

private:
    void trim(std::string& s) {
        s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
            return !std::isspace(ch);
        }));
        s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
            return !std::isspace(ch);
        }).base(), s.end());
    }
};

int main() {
    // 模拟数据库记录
    std::vector<Record> database = {
        {{"name", "Alice"}, {"age", "30"}, {"salary", "50000"}},
        {{"name", "Bob"}, {"age", "25"}, {"salary", "45000"}},
        {{"name", "Charlie"}, {"age", "35"}, {"salary", "60000"}},
        {{"name", "David"}, {"age", "28"}, {"salary", "55000"}}
    };
    
    SQLParser parser;
    
    try {
        // 解析WHERE条件
        auto condition1 = parser.parse("age > 28 AND salary > 50000");
        auto condition2 = parser.parse("name = Bob OR name = Alice");
        auto condition3 = parser.parse("NOT age > 30");
        
        // 筛选记录
        std::cout << "Records where age > 28 AND salary > 50000:\n";
        for (const auto& record : database) {
            if (condition1->evaluate(record)) {
                std::cout << record.at("name") << " (age: " << record.at("age") 
                          << ", salary: " << record.at("salary") << ")\n";
            }
        }
        
        std::cout << "\nRecords where name = Bob OR name = Alice:\n";
        for (const auto& record : database) {
            if (condition2->evaluate(record)) {
                std::cout << record.at("name") << "\n";
            }
        }
        
        std::cout << "\nRecords where NOT age > 30:\n";
        for (const auto& record : database) {
            if (condition3->evaluate(record)) {
                std::cout << record.at("name") << " (age: " << record.at("age") << ")\n";
            }
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    
    return 0;
}

解释器模式的特点
优点:
易于扩展文法:添加新的表达式类即可扩展语言

实现文法简单:每个文法规则都可以表示为一个类

易于改变和扩展解释过程:可以通过继承或组合来改变解释行为

缺点:
复杂的文法难以维护:文法规则很多时,类层次结构会变得庞大

执行效率较低:解释器模式通常使用递归调用,效率不如命令式代码

难以调试:复杂的解释逻辑可能难以调试

解释器模式适用场景
需要解释执行的语言:当有一个语言需要解释执行,并且可以将该语言中的句子表示为一个抽象语法树时

简单文法:文法较为简单时(复杂文法需要大量的类来表示规则)

效率不是关键问题:当效率不是关键问题时(解释器模式通常比编译型语言慢)

实际应用中的变体
使用访问者模式遍历语法树:将操作与语法树结构分离

使用生成器模式构建语法树:简化复杂语法树的构建过程

共享终结符:使用享元模式共享终结符表达式实例

解释器模式在需要实现简单语言解释器时非常有用,但需要注意控制文法的复杂度,避免类爆炸问题。在实际应用中,通常会结合其他模式(如访问者模式)来提高灵活性和可维护性。


网站公告

今日签到

点亮在社区的每一天
去签到