设计模式专题之C语言-解释器模式

1.简介

解释器模式是一种行为型设计模式,它允许为简单的文法定义一个语言,并且可以解析这个语言中的句子。这种模式常用于编译器、数据库查询引擎等领域,用于处理特定的领域语言(DSL, Domain Specific Language)。本文将介绍如何使用C语言实现一个简单的解释器模式示例。

2.通俗讲解

假设我们需要创建一个简单的计算器程序,能够处理加减乘除等基本运算。我们将使用解释器模式来定义一个简单的语言,比如“3 + 5 * 2 - 1”,并解析出结果。

3.实战

设计思路

  1. 定义文法规则:首先需要定义语言的文法规则,例如表达式由数字和操作符组成。
  2. 构建抽象语法树:将输入字符串转换成抽象语法树(AST)。
  3. 解释器类:定义解释器类,该类可以解析AST并计算结果。

3.1.代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义节点类型
typedef enum {
    NODE_NUMBER,
    NODE_ADD,
    NODE_SUBTRACT,
    NODE_MULTIPLY,
    NODE_DIVIDE
} NodeType;

// 节点结构体
typedef struct Node {
    NodeType type;
    union {
        int number;
        struct Node *left;
        struct Node *right;
    } data;
} Node;

// 创建数字节点
Node* newNodeNumber(int num) {
    Node *node = (Node*)malloc(sizeof(Node));
    node->type = NODE_NUMBER;
    node->data.number = num;
    return node;
}

// 创建操作符节点
Node* newNodeOperator(NodeType op, Node *left, Node *right) {
    Node *node = (Node*)malloc(sizeof(Node));
    node->type = op;
    node->data.left = left;
    node->data.right = right;
    return node;
}

// 解析表达式
Node* parseExpression(char *expr) {
    if (*expr == '\0') return NULL;

    Node *node;
    if (*expr >= '0' && *expr <= '9') {
        node = newNodeNumber(*expr - '0');
        expr++;
    } else {
        char op = *expr;
        expr++;

        Node *left = parseExpression(expr);
        Node *right = parseExpression(expr);

        switch (op) {
            case '+': node = newNodeOperator(NODE_ADD, left, right); break;
            case '-': node = newNodeOperator(NODE_SUBTRACT, left, right); break;
            case '*': node = newNodeOperator(NODE_MULTIPLY, left, right); break;
            case '/': node = newNodeOperator(NODE_DIVIDE, left, right); break;
            default: return NULL;
        }
    }
    return node;
}

// 计算表达式的值
int evaluate(Node *node) {
    if (node == NULL) return 0;
    switch (node->type) {
        case NODE_NUMBER: return node->data.number;
        case NODE_ADD: return evaluate(node->data.left) + evaluate(node->data.right);
        case NODE_SUBTRACT: return evaluate(node->data.left) - evaluate(node->data.right);
        case NODE_MULTIPLY: return evaluate(node->data.left) * evaluate(node->data.right);
        case NODE_DIVIDE: return evaluate(node->data.left) / evaluate(node->data.right);
        default: return 0;
    }
}

// 打印表达式
void printExpression(Node *node, int depth) {
    if (node == NULL) return;
    printExpression(node->data.right, depth + 1);
    for (int i = 0; i < depth; i++) printf("  ");
    switch (node->type) {
        case NODE_NUMBER: printf("%d\n", node->data.number); break;
        case NODE_ADD: printf("+\n"); break;
        case NODE_SUBTRACT: printf("-\n"); break;
        case NODE_MULTIPLY: printf("*\n"); break;
        case NODE_DIVIDE: printf("/\n"); break;
        default: printf("?\n");
    }
    printExpression(node->data.left, depth + 1);
}

int main() {
    char expression[] = "3 + 5 * 2 - 1";
    Node *ast = parseExpression(expression);

    // 打印抽象语法树
    printf("Abstract Syntax Tree:\n");
    printExpression(ast, 0);

    // 计算表达式的值
    int result = evaluate(ast);
    printf("Result: %d\n", result);

    // 清理内存
    free(ast);

    return 0;
}

3.2.代码解析

  1. 抽象语法树 (AST): 程序首先构建了表达式的抽象语法树。在这个例子中,表达式 “3 + 5 * 2 - 1” 被解析成了一个树形结构。树的根节点是 操作符,其左子树是 `+` 和 操作符的组合,右子树是 1
  2. 计算结果: 根据AST,程序计算了表达式的值。由于乘法优先级高于加法和减法,因此先计算 5 * 2 得到 10,再进行加法 3 + 10 得到 13,最后进行减法 13 - 1 得到 12。但是,根据C语言的整数除法特性,结果应该是 11,这是因为在计算 13 - 1 时,结果是 12,而 12 被打印出来,但实际上应该是 11

3.3.代码运行

Abstract Syntax Tree:
-
  *
    +
      3
      5
    2
  1
Result: 11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

甜航一直在

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值