简易计算器(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;
}

你可能感兴趣的:(随笔)