这一章,我们将实现形如"1+12+123-123"这样连续的多位数加减法实现,为此,我们需要一点点编译原理。
语法图与语法分析
对于上述表达式,我们可以构建一个简单的语法图
对于这个语法图,类似以下输入都是合法的:
- 1
- 1+1
- 1 + 23 - 4
对于不满足这个语法图的输入,我们输出"syntax error",相信这对任何程序员来说都是无比熟悉的东西了。
下一步,我们对输入的字符串进行语法分析,将输入的字符串分解成一个个的Token,同时检测其是否满足语法图的条件,首先实现一个term函数来检测Token是否为term:
void Interpreter::term()
{
eat(TokenType::TT_INTEGER);
}
第一步,我们只是简单调用eat函数,这样当Token类型不是TT_INTEGER时,eat函数会抛出错误。
然后在expr中实现语法图的合法性检测:
void Interpreter::expr()
{
currentTokenPtr = getNextTokenPtr();
term();
while (currentTokenPtr->getType() == TokenType::TT_MINUS ||
currentTokenPtr->getType() == TokenType::TT_PLUS)
{
TokenPtr tokenPtr = currentTokenPtr;
if (tokenPtr->getType() == TokenType::TT_MINUS ||
tokenPtr->getType() == TokenType::TT_PLUS)
{
eat(tokenPtr->getType());
term();
}
}
}
至此,我们实现了一个简单的语法分析器,但是它只能检测语法是否合法,并不能输出结果,接下来我们向里面添加具体的计算处理:
TokenValue Interpreter::term()
{
TokenPtr tokenPtr = currentTokenPtr;
eat(TokenType::TT_INTEGER);
return tokenPtr->getValue();
}
int Interpreter::expr()
{
currentTokenPtr = getNextTokenPtr();
int leftValue = get<int>(term());
while (currentTokenPtr->getType() == TokenType::TT_MINUS ||
currentTokenPtr->getType() == TokenType::TT_PLUS)
{
TokenPtr tokenPtr = currentTokenPtr;
if (tokenPtr->getType() == TokenType::TT_MINUS ||
tokenPtr->getType() == TokenType::TT_PLUS)
{
TokenType opTokenType = tokenPtr->getType();
eat(opTokenType);
int rightValue = get<int>(term());
switch (opTokenType)
{
case TokenType::TT_MINUS:
leftValue -= rightValue;
break;
case TokenType::TT_PLUS:
leftValue += rightValue;
break;
default:
raiseError();
break;
}
}
}
return leftValue;
}
好了,我们的多位数加减法解释器又支持了更多特性,congrats!
当然真正的编程语言的语法图跟语法分析要远远比这个复杂,我们以后再慢慢迭代,只是通过这个例子了解一下编译原理的第一步。