解析器模式(Parser Pattern)

定义

解析器模式(Parser Pattern)是一种行为设计模式,用于将输入的数据解析成特定的结构或对象。它通常涉及到一个或多个解析器类,这些类负责处理输入并构建所需的输出结构。解析器模式特别适用于复杂的语法或格式要求,比如编程语言、配置文件或数据协议。

示例

以下是一个使用C++实现的简单解析器模式的示例。我们将创建一个简单的算术表达式解析器,用于解析并计算加法和减法表达式。

首先,定义表达式的基本结构:

cpp 复制代码
#include <iostream>  
#include <memory>  
#include <string>  
#include <stdexcept>  
  
// 基础表达式类  
class Expression {  
public:  
    virtual ~Expression() = default;  
    virtual int evaluate() const = 0;  
};  
  
// 数字表达式类  
class NumberExpression : public Expression {  
private:  
    int number;  
public:  
    NumberExpression(int n) : number(n) {}  
    int evaluate() const override {  
        return number;  
    }  
};  
  
// 加法表达式类  
class AdditionExpression : public Expression {  
private:  
    std::unique_ptr<Expression> left;  
    std::unique_ptr<Expression> right;  
public:  
    AdditionExpression(std::unique_ptr<Expression> l, std::unique_ptr<Expression> r)  
        : left(std::move(l)), right(std::move(r)) {}  
    int evaluate() const override {  
        return left->evaluate() + right->evaluate();  
    }  
};  
  
// 减法表达式类  
class SubtractionExpression : public Expression {  
private:  
    std::unique_ptr<Expression> left;  
    std::unique_ptr<Expression> right;  
public:  
    SubtractionExpression(std::unique_ptr<Expression> l, std::unique_ptr<Expression> r)  
        : left(std::move(l)), right(std::move(r)) {}  
    int evaluate() const override {  
        return left->evaluate() - right->evaluate();  
    }  
};

接下来,创建解析器类,用于解析表达式字符串:

cpp 复制代码
class ExpressionParser {  
private:  
    std::string input;  
    size_t position;  
  
    // 辅助函数,用于跳过空格  
    void skipSpaces() {  
        while (position < input.size() && isspace(input[position])) {  
            ++position;  
        }  
    }  
  
    // 辅助函数,用于解析数字  
    std::unique_ptr<Expression> parseNumber() {  
        size_t start = position;  
        while (position < input.size() && isdigit(input[position])) {  
            ++position;  
        }  
        int number = std::stoi(input.substr(start, position - start));  
        return std::make_unique<NumberExpression>(number);  
    }  
  
    // 辅助函数,用于解析加法或减法表达式  
    std::unique_ptr<Expression> parseExpression() {  
        std::unique_ptr<Expression> left = parseNumber();  
        while (position < input.size() && (input[position] == '+' || input[position] == '-')) {  
            char op = input[position++];  
            std::unique_ptr<Expression> right = parseExpression();  
            if (op == '+') {  
                left = std::make_unique<AdditionExpression>(std::move(left), std::move(right));  
            } else if (op == '-') {  
                left = std::make_unique<SubtractionExpression>(std::move(left), std::move(right));  
            }  
        }  
        return left;  
    }  
  
public:  
    ExpressionParser(const std::string& expr) : input(expr), position(0) {}  
    std::unique_ptr<Expression> parse() {  
        skipSpaces();  
        std::unique_ptr<Expression> expr = parseExpression();  
        if (position != input.size()) {  
            throw std::invalid_argument("Invalid expression");  
        }  
        return expr;  
    }  
};

最后,使用解析器来解析和计算表达式:

cpp 复制代码
int main() {  
    try {  
        // 创建一个解析器对象并解析表达式  
        ExpressionParser parser("23 + 45 - 6");  
        std::unique_ptr<Expression> expr = parser.parse();  
  
        // 计算并打印结果  
        int result = expr->evaluate();  
        std::cout << "Result: " << result << std::endl;  
    } catch (const std::exception& e) {  
        // 捕获并打印任何异常  
        std::cerr << "Error parsing expression: " << e.what() << std::endl;  
        return 1; // 表示程序异常退出  
    }  
  
    return 0; // 表示程序正常退出  
}

示例总结:

  1. 定义表达式结构 :我们定义了几个类来表示不同类型的算术表达式,包括Expression(基础表达式类),NumberExpression(数字表达式类),AdditionExpression(加法表达式类),和SubtractionExpression(减法表达式类)。每个类都有一个evaluate方法用于计算表达式的值。

  2. 创建解析器类ExpressionParser类负责解析表达式字符串。它使用了一系列辅助函数来跳过空格、解析数字,以及递归地解析表达式。parse方法是解析器的入口点,它返回一个指向解析得到的表达式的智能指针。

  3. 使用解析器 :在main函数中,我们创建了一个ExpressionParser对象,并调用其parse方法来解析一个表达式字符串。如果解析成功,我们计算并打印表达式的值;如果解析失败,我们捕获异常并打印错误信息。

这个示例展示了如何使用解析器模式来解析和计算简单的算术表达式。解析器模式特别适用于需要处理复杂语法或格式的场景,因为它允许你将解析逻辑封装在单独的类中,使得代码更加模块化和可维护。同时,使用智能指针(如std::unique_ptr)可以帮助管理动态分配的内存,减少内存泄漏和悬挂指针的风险。

相关推荐
杨充1 天前
10.可测试性实战设计
设计模式·开源·代码规范
杨充1 天前
9.重构十二式的实战
设计模式·开源·代码规范
杨充1 天前
6.设计原则的全景图
设计模式·开源·全栈
杨充1 天前
2.面向对象的特性
设计模式
杨充1 天前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充1 天前
8.反模式与坏味道
设计模式·开源·代码规范
杨充1 天前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式