一個簡單的解釋器(2)—— 處理空格和多位整數(shù)

在上一篇中,我們實(shí)現(xiàn)了一個簡單的加法解釋器,它僅支持一位數(shù)加法,接下來,我們向解釋器添加以下特性:

  • 支持多位整數(shù)
  • 可以跳過空格
  • 支持減法

處理多位整數(shù)

上一篇中,我們直接使用單個字符來判斷其所屬的Token類型,為了支持多位整數(shù),我們需要對連續(xù)字符串進(jìn)行判斷,所以我們需要在Interpreter類中實(shí)現(xiàn)一個advance函數(shù):

void Interpreter::advance()
{
    currentPos++;
    if (currentPos >= strlen(text.c_str())) 
    {
        currentChar = '\0';
    }
    else 
    {
        currentChar = text.c_str()[currentPos];
    }
}

然后,在getNextTokenPtr時,如果讀取到第一個字符是整數(shù),那么連續(xù)讀取一直到當(dāng)前字符不是整數(shù)為止,為此,實(shí)現(xiàn)一個integer函數(shù):

int Interpreter::integer()
{
    int result = 0;
    while (isDigit(currentChar)) 
    {
        result *= 10;
        result += currentChar - '0';
        advance();
    }
    return result;
}

注意這里的isDigit,C++庫有提供自帶的isdigit函數(shù),不過我還是自己實(shí)現(xiàn)了一個,因?yàn)閷砦覀儾粌H僅是需要isdigit這樣子簡單的判斷,早晚都是要自己寫的:

bool Interpreter::isDigit(char c)
{
    return c >= '0' && c <= '9';
}

處理空格

處理空格比較簡單,實(shí)現(xiàn)一個isSpace的判斷函數(shù),然后實(shí)現(xiàn)一個skipWhiteSpaces,遇到則跳過就行,同樣的,我們不用C++庫自帶的issapce:

bool Interpreter::isSpace(char c)
{
    return c == ' ' || c == '\t';
}

void Interpreter::skipWhiteSpaces()
{
    while (isSpace(currentChar)) 
    {
        advance();
    }
}

處理減法

處理減法則是跟處理加法的邏輯相同,只要往TokenType里加一個枚舉值,然后在getNextToken時加一個判斷就行,最終實(shí)現(xiàn)如下:

TokenPtr Interpreter::getNextTokenPtr()
{
    while (currentChar != '\0') 
    {
        if (isSpace(currentChar)) 
        {
            skipWhiteSpaces();
            continue;
        }

        if (isDigit(currentChar)) 
        {
            return make_shared<Token>(TokenType::TT_INTEGER, integer());
        }

        if (currentChar == '+') 
        {
            advance();
            return make_shared<Token>(TokenType::TT_PLUS, '+');
        }

        if (currentChar == '-') 
        {
            advance();
            return make_shared<Token>(TokenType::TT_MINUS, '-');
        }
        raiseError();
    }
    return make_shared<Token>(TokenType::TT_EOF, NULL);
}

int Interpreter::expr()
{
    currentTokenPtr = getNextTokenPtr();
    TokenPtr left = currentTokenPtr;
    eat(TokenType::TT_INTEGER);

    TokenPtr op = currentTokenPtr;
    if (op->getType() == TokenType::TT_PLUS ||
        op->getType() == TokenType::TT_MINUS) 
    {
        eat(op->getType());
    }
    else 
    {
        raiseError();
    }
    
    TokenPtr right = currentTokenPtr;
    eat(TokenType::TT_INTEGER);

    switch (op->getType())
    {
    case TokenType::TT_MINUS:
        return get<int>(left->getValue()) - get<int>(right->getValue());
    case TokenType::TT_PLUS:
        return get<int>(left->getValue()) + get<int>(right->getValue());
    default:
        raiseError();
    }
    return 0;
}

然后我們寫一個main來驗(yàn)證:

#include<iostream>
#include<sstream>
#include "Interpreter.h"
#include "InterpreterException.h"
using namespace std;

int main() 
{
    try 
    {
        while (true) 
        {
            std::string text;
            getline(cin, text);
            Interpreter i(text);
            cout << i.expr() << endl;
        }
    }
    catch  (InterpreterException e)
    {
        return 0;
    }
}

注意這里用sstream的getline,如果直接cin,無法輸入空格,現(xiàn)在,我們可以愉快地使用這個加減法解釋器了,看起來已經(jīng)有點(diǎn)樣子了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容