antlr infinit eof loop

时间:2013-01-27 16:36:51

标签: antlr infinite-loop eof

请查看我的语法:https://bitbucket.org/rstoll/tsphp-parser/raw/cdb41531e86ec66416403eb9c29edaf60053e5df/src/main/antlr/TSPHP.g

不知何故,ANTLR为以下输入产生无限循环,发现无限EOF标记:

class a{public function void a(}

虽然,只有前卫希望EOF classBody以某种方式接受它。有人知道如何解决这个问题,我必须改变那个classBody分别不接受EOF令牌吗?

生成的类中的代码:

// D:\\TSPHP-parser\\src\\main\\antlr\\TSPHP.g:287:129: ( classBody )*
loop17:
do {
    int alt17=2;
    int LA17_0 = input.LA(1);
    if ( (LA17_0==EOF||LA17_0==Abstract||LA17_0==Const||LA17_0==Final||LA17_0==Function||LA17_0==Private||(LA17_0 >= Protected && LA17_0 <= Public)||LA17_0==Static) ) {
        alt17=1;
    }

    switch (alt17) {
    case 1 :
        // D:\\TSPHP-parser\\src\\main\\antlr\\TSPHP.g:287:129: classBody
        {
        pushFollow(FOLLOW_classBody_in_classDeclaration1603);
        classBody38=classBody();
        state._fsp--;
        if (state.failed) return retval;
        if ( state.backtracking==0 ) stream_classBody.add(classBody38.getTree());
        }
        break;

    default :
        break loop17;
    }
} while (true);

出现问题,当token = EOF时,循环永远不会退出,因为EOF是一个有效的令牌,即使我没有这样指定。

编辑如果我将第342行和第347行注释掉(规则accessModifierWithoutPrivateOrPublic中的空案例,分别是accessModifierOrPublic),则不会收到错误

编辑2 我可以解决我的问题。我重写了methodModifier规则(在一个规则中集成了所有可能的修饰符)。这样,在 / in

之后,ANTLR不相信EOF是有效令牌
accessModifierOrPublic
    :   accessModifier 
    |   /* empty */ -> Public["public"]
    ;

1 个答案:

答案 0 :(得分:1)

在ANTLR 3的错误处理中可能会发生此类错误。在ANTLR 4中,IntStream.consume() 方法已更新为要求抛出以下异常以抢占此问题。

  

抛出:   IllegalStateException - 如果尝试使用流的结尾(即LA(1) == EOF,则在调用之前)。

对于ANTLR 3语法,您至少可以通过使用自己的TokenStream实现(可能最容易扩展CommonTokenStream)来防止无限循环,并在违反上面列出的条件时抛出此异常。请注意,可能需要允许违反此条件一次(原因很复杂),因此如果代码尝试消耗超过2或3的EOF,请保持计数并抛出IllegalStateException倍。请记住,这只是为了打破无限循环,以便在实际检查中有点“模糊”。