在上一篇中,我們實(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)樣子了。