Parsing 所有ANTLR语法都会产生错误“;输入端没有可行的替代方案'&书信电报;EOF>'&引用;

Parsing 所有ANTLR语法都会产生错误“;输入端没有可行的替代方案'&书信电报;EOF>'&引用;,parsing,antlr,antlr3,Parsing,Antlr,Antlr3,我需要解析一个小的表达式语言(并且,或者,不,parens改变优先级),所以选择了ANTLR来完成任务,我取得了很好的进展(ANTLRWorks对于新手来说非常好)。我使用了antlr网站上的一些入门参考资料,然后找到了两篇非常适合我尝试完成的博客文章: 我遇到的问题是,无论我输入什么,我总是会得到错误: 第1行:29输入“EOF”处无可行的替代方案 因此,作为故障排除的一部分,我决定尝试一种我知道很好的语法,并从第一个链接中找到的ECalc.g语法生成一个lexer/parser。令我惊讶

我需要解析一个小的表达式语言(并且,或者,不,parens改变优先级),所以选择了ANTLR来完成任务,我取得了很好的进展(ANTLRWorks对于新手来说非常好)。我使用了antlr网站上的一些入门参考资料,然后找到了两篇非常适合我尝试完成的博客文章:

我遇到的问题是,无论我输入什么,我总是会得到错误:

第1行:29输入“EOF”处无可行的替代方案

因此,作为故障排除的一部分,我决定尝试一种我知道很好的语法,并从第一个链接中找到的ECalc.g语法生成一个lexer/parser。令我惊讶的是,我在使用那个语法时也犯了同样的错误!我被迷惑了。我对语法所做的唯一更改是让它生成Java代码,并在@members部分删除了一些CSharp代码

这是我的测试人员课程:

public class ECalcTester {
private final static Logger logger = Logger.getLogger(ECalcTester.class);

public static void main(String[] args) {
    BasicConfigurator.configure();
    ECalcLexer lex = new ECalcLexer(new ANTLRStringStream("false || not (false and true)"));

    Token token;
    while (true) {
        token = lex.nextToken();
        if (token.getType() == Token.EOF) {
            break;
        }

        System.out.println("Token: ‘" + token.getText() + "’");
    }

    CommonTokenStream tokens = new CommonTokenStream(lex);
    lex.nextToken();

    ECalcParser parser = new ECalcParser(tokens);
    try {
        logger.debug(parser.expression().getTree());
    } catch (org.antlr.runtime.RecognitionException e) {
        logger.error("Exception ", e);
    }

}
以下是输出:

Token: ‘false’
Token: ‘ ’
Token: ‘||’
Token: ‘ ’
Token: ‘not’
Token: ‘ ’
Token: ‘(’
Token: ‘false’
Token: ‘ ’
Token: ‘and’
Token: ‘ ’
Token: ‘true’
Token: ‘)’
line 1:29 no viable alternative at input '<EOF>'
0 [main] DEBUG ECalcTester  - <unexpected: [@0,29:29='<EOF>',<-1>,1:29], resync=>
Token:'false'
令牌:“”
标记:“||”
令牌:“”
标记:“不是”
令牌:“”
令牌:'('
标记:“假”
令牌:“”
标记:“和”
令牌:“”
标记:“真的”
令牌:')'
第1行:29输入“”处无可行的替代方案
0[main]调试eCalTester-
如果我能弄清楚为什么这会发生在一个应该是好的语法中,我应该能够弄清楚为什么同样的事情会发生在我的语法中(非常相似的概念)


有人能提供任何见解吗?

打印出您的代币后,您将处于代币流的末尾。您需要通过调用重置令牌流

lex.reset();

这将使lexer返回到令牌流的开头,以便您可以调用解析器。

是否需要重置lexer令牌流?现在你已经浏览了所有的标记,解析器的第一件事是羞愧地垂下头是的,是的,我需要调用lex.reset()…叹气。我是这样一个新手,我不知道这个方法,虽然知道它是一个我迭代过的流,但我应该考虑需要重置它,这是一个非常常见的概念。好消息是,这解决了我使用这个方法时遇到的问题。然而,这并不能解决我的语法问题。我以为我已经找到了常见的问题,但完全没有找到问题所在……啊。@Michael:-)至少现在已经解决了。如果你在一个新问题中发布你的其他问题,我们可以看一看!我发布了另一个问题,这是我真正的问题。不确定在这里链接是否是不礼貌的,所以不会。我用了同样的标签。