간이 계산기(3) - 확장(괄호 및 음수 지원)

5574 단어 수필.
괄호와 음수를 지원할 수 있도록 간단한 계산기를 계속 확장하십시오.수정 코드는 다음과 같다. 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.
"
); exit(1); } } else { // fprintf(stderr, "syntax error.
");
// 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; }

좋은 웹페이지 즐겨찾기