一个简单的解释器(3)—— 连续表达式

这一章,我们将实现形如"1+12+123-123"这样连续的多位数加减法实现,为此,我们需要一点点编译原理。

语法图与语法分析

对于上述表达式,我们可以构建一个简单的语法图

lsbasi_part3_syntax_diagram.png

对于这个语法图,类似以下输入都是合法的:

  • 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!
当然真正的编程语言的语法图跟语法分析要远远比这个复杂,我们以后再慢慢迭代,只是通过这个例子了解一下编译原理的第一步。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容