从0开始自制解释器——实现多个整数的加减法

文章介绍了如何在已有的计算两位整数加减法的计算器基础上,通过理解并使用语法图来实现连续多个整数相加减的功能。首先定义了语法图的概念及其在编程语言语法分析中的作用,然后详细讲解了代码修改过程,包括词法分析的改进,以及新增的get_term()和get_oper()函数,用于获取整数和操作符。最后,文章提供了一个完整的实现多个整数算术运算的代码示例。
摘要由CSDN通过智能技术生成

在上一篇我们实现了一个可以计算两个多位整数加减法的计算器。本章我们继续来给这个计算器添加功能,这次要给它添加可以连续计算多个整数相加减的功能。例如我们可以计算 1 + 2 + 3 这样的表达式。

语法图

在正式写代码之前让我们先来学习一下一些基本的理论知识。这次要介绍的理论是语法图

什么是语法图呢?语法图是编程语言语法语法规则的图形表示。它体现了词法分析的运行规则。语法图直观的展示了在编程语言中哪些语句是符合语法的,哪些是不符合语法规范的。

语法图的阅读非常容易,它类似于程序的流程图,只要顺着箭头指向的路径来读即可。与程序流程图类似,语法图中有些路径表示选择,有些表示循环。我们试着来读一下下面的语法图
在这里插入图片描述

这张语法图表示的含义是,一个术语(term) 可选的跟上一个加号或者减号,而后面又需要跟上另一个术语。接着又可以有选择的跟上另一个加号或者减号。但是加号或者减号后面必须跟上另一个术语。

这里又提到另一个单词,term 它的中文意思是术语。似乎很难用其他文字来解释何为术语。你只需要知道在这里它代表的是一个整数,它并不影响我们阅读这个语法图

代码展示

在上一篇中我们提到,将Token流识别为对应结构的过程被称之为词法分析,我们代码中的词法分析的实现主要在函数 expr 中。在这个函数中我们主要实现了词法分析以及最后的解释执行。我们按照语法图修改一下词法分析的代码

我们先给出下面的伪代码

获取第一个整数作为计算结果保存
while(解析到最后一个字符)
{
    获取操作符(+/-)
    switch(操作符)
    {
        case +:
            获取下一个整数,如果不是整数则退出并报错
            与结果相加
            break;
        case -:
            获取下一个整数,如果不是整数则退出并报错
            与结果相减
            break;
    }
}

最终打印计算结果或者打印语法错误

基于这个思路我们给出具体的实现代码

int expr()
{
    bool bRet = false;
    int result = get_term(&bRet);
    int bEOF = false;
    do
    {
        ETokenType oper = get_oper(&bRet);
        switch (oper)
        {
            case PLUS:
            {
                int num = get_term(&bRet);
                if(bRet)
                    result += num;
            }
            break;
        case MINUS:
            {
                int num = get_term(&bRet);
                if(bRet)
                    result -= num;
            }
            break;
        case END_OF_FILE:
            printf("%d\n", result);
            bEOF = true;
            break;
        default:
            bRet = false;
            break;
        }
    } while (bRet && !bEOF);
    if (!bRet)
    {
        printf("Syntax Error!\n");
    }
}

这里为了便于理解,我将获取整数和操作符的模块又进行了一次封装,提供了两个函数分别是 get_term()get_oper()。它们的代码如下

int get_term(bool *pRet)
{
    Token token = { 0 };
    dyncstring_init(&token.value, DEFAULT_BUFFER_SIZE);
    int value = 0;
    if (get_next_token(&token) && token.type == CINT)
    {
        value = atoi(token.value.pszBuf);
        if (pRet)
            *pRet = true;
    }
    else
    {
        if (pRet)
            *pRet = false;
    }
    dyncstring_free(&token.value);

    return value;
}
ETokenType get_oper(bool* pRet)
{
    Token token = { 0 };
    dyncstring_init(&token.value, DEFAULT_BUFFER_SIZE);
    int oper = 0;
    if (get_next_token(&token) && (token.type == PLUS || token.type == MINUS))
    {
        oper = token.type;
        if (pRet)
            *pRet = true;
    }
    else if (token.type == END_OF_FILE)
    {
        oper = END_OF_FILE;
        if (pRet)
            *pRet = true;
    }
    else
    {
        oper = -1;
        if (pRet)
            *pRet = false;
    }

    dyncstring_free(&token.value);
    return oper;
}

到此为止,就实现了多个整数的算术运算。整个实现过程的代码我都放到该位置。有兴趣的小伙伴可以自己对照着代码跟着我一起来实现属于自己的解释器。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值