简易计算器(3)- 扩展(支持括号和负数)

继续上文扩展简易计算器,使它支持括号和负数。
修改代码如下:
在TokenKind枚举中加入左右括号的枚举值
lex.h

#ifndef _LEX_H
#define _LEX_H

typedef enum {
    TOKEN_BAD,
    TOKEN_NUM,
    TOKEN_OP_ADD,
    TOKEN_OP_SUB,
    TOKEN_OP_MUL,
    TOKEN_OP_DIV,
    TOKEN_OP_PAREN_LEFT,
    TOKEN_OP_PAREN_RIGHT,
    TOKEN_LINE_END,
} TokenKind;

#define MAX_TOKEN_SIZE  (100)

typedef struct {
    TokenKind kind;
    double value;
    char  str[MAX_TOKEN_SIZE];
} Token;

void SetLine(char *file);
void GetToken(Token *token);

#endif

在parser.c 中ParsePrimaryExp函数中加入解析负数和括号逻辑
parser.c


#include "parser.h"

static Token stLookAheadTok;
static int stLookAheadTokExist;

static void MyGetToken(Token *tok)
{
    if (stLookAheadTokExist) {
        *tok = stLookAheadTok;
        stLookAheadTokExist = 0;
    } else {
        GetToken(tok);
    }
}

static void UngetToken(Token *tok)
{
    stLookAheadTok = *tok;
    stLookAheadTokExist = 1;
}

static double ParsePrimaryExp()
{
    Token tok;
    double val = 0.0;
    int minusFlag = 0;
    MyGetToken(&tok);
    // negative NUM
    if (tok.kind == TOKEN_OP_SUB) {
        minusFlag = 1;
    } else {
        UngetToken(&tok);
    }
    MyGetToken(&tok);
    if (tok.kind == TOKEN_NUM) {
        val =  tok.value;
    } else if (tok.kind == TOKEN_OP_PAREN_LEFT) {   // Support ( )
        val = ParseExp();
        MyGetToken(&tok);
        if (tok.kind != TOKEN_OP_PAREN_RIGHT) {
            fprintf(stderr, "missing ')' error.\n");
            exit(1);
        }
    } else {
        // fprintf(stderr, "syntax error. \n");
        // exit(1);
        // return 0.0; // make compiler happy
        UngetToken(&tok);
    }
    return minusFlag ? (-val) : val;
}

static double ParseTerm()
{
    double v1;
    double v2;
    Token tok;

    v1 = ParsePrimaryExp();
    for (;;) {
        MyGetToken(&tok);
        if (tok.kind != TOKEN_OP_MUL
            && tok.kind != TOKEN_OP_DIV) {
            UngetToken(&tok);
            break;
        }
        v2 = ParsePrimaryExp();
        if (tok.kind == TOKEN_OP_MUL) {
            v1 *= v2;
        } else if (tok.kind == TOKEN_OP_DIV) {
            v1 /= v2;
        }
    }
    return v1;
}

double ParseExp()
{
    double v1;
    double v2;
    Token tok;
    v1 = ParseTerm();
    for (;;) {
        MyGetToken(&tok);
        if (tok.kind != TOKEN_OP_ADD
           && tok.kind != TOKEN_OP_SUB) {
            UngetToken(&tok);
            break;
        }
        v2 = ParseTerm();
        if (tok.kind == TOKEN_OP_ADD) {
            v1 += v2;
        } else if (tok.kind == TOKEN_OP_SUB) {
            v1 -= v2;
        } else {
            UngetToken(&tok);
        }
    }
    return v1;
}

double ParseLine()
{
    double val;
    stLookAheadTokExist = 0;
    val = ParseExp();
    return val;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值