[错误处理]变量分析器 / 语法分析错误提示函数接口

    变量分析器本身很简单,它的错误处理不需要弄得太复杂,只对正反方括号做做验证,其它的丢给表达式分析器或者LR分析器去弄就行了。(下面一段话中的括号均指方括号。)

    大致的构想是这样的:当需要反括号时,没碰到反括号,直接提示错误,然后装作啥也没发生一样重新看看这个终结符;而遇到除了括号以外的其它符号时,就终止识别(此时变量识别结束,返回)。实现如下:

void wrapname(consumeLBracket)(void* self, struct Token* t)
{
    if(LBRACKET == t->type) {
        analyserStack->push(analyserStack, newOperationAnalyser());
    } else {
        /* 返回 */
        struct VariableNode* var = ((struct VariableAnalyser*)self)->var;
        revert(analyserStack->pop(analyserStack));
        struct SyntaxAnalyser* analyser = (struct SyntaxAnalyser*)
                                       (analyserStack->peek(analyserStack));
        analyser->consumeNonTerminal(analyser,
                                     (struct AbstractSyntaxNode*)var);
        analyser = (struct SyntaxAnalyser*)
                          (analyserStack->peek(analyserStack));
        analyser->consumeToken(analyser, t);
    }
}

void wrapname(consumeRBracket)(void* self, struct Token* t)
{
    struct VariableAnalyser* varAna = (struct VariableAnalyser*)self;
    // 先认为没有错误
    varAna->consumeToken = wrapname(consumeLBracket);
    // 再来验证符号
    if(RBRACKET != t->type) {
        /* 符号不对 */
        varAna->consumeToken(varAna, t); // 继续分析
    }
}

    上次说了,如果用一堆printf来弄这些错误处理不太方便,所以这回来把错误提示的接口抽出来,以方便日后维护。对于语法分析,错误提示需要关心的是错误的类型和在哪一个终结符附近出的错。因此接口函数可以这样写

void syntaxError(ErrMsg, struct Token*);

实现则可以这样

void syntaxError(ErrMsg e, struct Token* t)
{
    failed = 1;
    if(END == t->type) {
        fprintf(stderr, "Syntax error at the end of the file.\n"
                        "    %s\n",
                e);
    } else {
        fprintf(stderr, "Syntax error @ line: %d token: `%s'\n"
                        "    %s\n",
                t->line,  t->image, e);
    }
}

那么刚才那些错误提示就可以这样搞

static ErrMsg missingRBracket = "Missing close bracket.";

void wrapname(consumeLBracket)(void* self, struct Token* t)
{
    if(LBRACKET == t->type) {
        analyserStack->push(analyserStack, newOperationAnalyser());
    } else {
        /* 返回 */
        struct VariableNode* var = ((struct VariableAnalyser*)self)->var;
        revert(analyserStack->pop(analyserStack));
        struct SyntaxAnalyser* analyser = (struct SyntaxAnalyser*)
                                       (analyserStack->peek(analyserStack));
        analyser->consumeNonTerminal(analyser,
                                     (struct AbstractSyntaxNode*)var);
        analyser = (struct SyntaxAnalyser*)
                          (analyserStack->peek(analyserStack));
        analyser->consumeToken(analyser, t);
    }
}

void wrapname(consumeRBracket)(void* self, struct Token* t)
{
    struct VariableAnalyser* varAna = (struct VariableAnalyser*)self;
    varAna->consumeToken = wrapname(consumeLBracket);
    if(RBRACKET != t->type) {
        syntaxError(missingRBracket, t); // and here
        varAna->consumeToken(varAna, t);
    }
}

 

再附上之前OperationAnalyser中错误处理的部分,请定位原来的那些输出语句,然后将其改为这些玩意儿。

 

/* wrapname(consumeOperator) 中 */
// ... 一些 if else 分支过后
    else if (isFirstFactor(token->type)) {
        struct Token fakeOp = {token->line, PLUS, NULL, "+"};
        syntaxError(wantOperator, token); // 0.0
        self->consumeToken(self, &fakeOp);
        self->consumeToken(self, token);
    } else {
        struct AbstractSyntaxNode* ret;
        struct Operator* topOp = (struct Operator*)
                                         (self->opStack->pop(self->opStack));
        while(LPARENT != topOp->op) {
            topOp->operate(topOp, self->numStack);
            topOp = (struct Operator*)(self->opStack->pop(self->opStack));
        }
        topOp->operate(topOp, NULL);
        ret = (struct AbstractSyntaxNode*)(self->numStack->pop(self->numStack));

        if(0 != self->opStack->height(self->opStack)) {
            syntaxError(excessLParent, token); // :-p
        }
        wrapname(cleanup)(self);
        struct SyntaxAnalyser* analyser = (struct SyntaxAnalyser*)
                                          (analyserStack->peek(analyserStack));
        analyser->consumeNonTerminal(analyser, ret);

        analyser = (struct SyntaxAnalyser*)(analyserStack->peek(analyserStack));
        analyser->consumeToken(analyser, token);
    }
// ...

/* wrapname(consumeFactor) 中 */
// ... 一些 if else 分支过后
        struct AbstractSyntaxNode* ret = (struct AbstractSyntaxNode*)
                                         (self->numStack->peek(self->numStack));
        if(NULL == ret && 1 == self->opStack->height(self->opStack)) {
            self->numStack->pop(self->numStack);
            wrapname(cleanup)(self);
            struct SyntaxAnalyser* analyser = (struct SyntaxAnalyser*)
                                       (analyserStack->peek(analyserStack));
            analyser->consumeNonTerminal(analyser, ret);

            analyser = (struct SyntaxAnalyser*)
                       (analyserStack->peek(analyserStack));
            analyser->consumeToken(analyser, token);
        } else {
            struct Token fakeNum = {token->line, INTEGER, NULL, "0"};
            syntaxError(wantFactor, token); // =,=
            self->consumeToken(self, &fakeNum);
            self->consumeToken(self, token);
        }
// ...

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值