ANTLR4 -> 检查文字是 STRING_LITERAL 还是 NUMBER_LITERAL

ANTLR4 -> Check a literal is STRING_LITERAL or a NUMBER_LITERAL

目前,我正在使用这个 ANTLR4 语法(部分)来获得 stringsnumbers:

算一下这​​个总结语法:

gramm
 : expr SCOL
 ;

expr
 : literal          #LiteralExpression
 ;

literal
 : NUMERIC_LITERAL
 | STRING_LITERAL
 ;

NUMERIC_LITERAL
 : DIGIT+ ( '.' DIGIT* )? ( E [-+]? DIGIT+ )?
 | '.' DIGIT+ ( E [-+]? DIGIT+ )?
 ;

STRING_LITERAL
 : '\'' ( ~'\'' | '\'\'' )* '\''
 ;

SPACES
 : [ \u000B\t\r\n] -> channel(HIDDEN)
 ;

fragment DIGIT : [0-9];

所以,我正在实施 GrammBaseVisitor<Void>

我不太明白如何检查文字是 NUMERIC_LITERAL 还是 STRING_LITERAL

据我所知,我已经覆盖了 visitLiteral()visitLiteralExpression():

@Override
public Void visitLiteral(LiteralContext ctx) {
    // TODO What should I do here in order to check whether
    // ctx contains an STRING_LITERAL or a NUMBER_LITERAL?
    return super.visitLiteral(ctx);
}

@Override
public Void visitLiteralExpression(LiteralExpressionContext ctx) {
    return super.visitLiteralExpression(ctx);
}

visitLiteralvisitLiteralExpression()有什么区别?

您的 literal 产生式由两个可能的终端组成,即数字和字符串文字。解析后的输入是否包含一个或另一个,您可以在 visitLiteral.

中使用 null 检查来确定
@Override
public Object visitLiteral(LiteralContext ctx) {            
    TerminalNode numeric = ctx.NUMERIC_LITERAL();
    TerminalNode string = ctx.STRING_LITERAL();
    if (numeric != null) {
        System.out.println(numeric.getSymbol().getType());
    } else if (string != null) {
        System.out.println(string.getSymbol().getType());
    }
    return super.visitLiteral(ctx);
}

您可以通过覆盖 visitTerminal.

访问所有终端
@Override
public Object visitTerminal(TerminalNode node) {
    int type = node.getSymbol().getType(); // matches a constant in your parser

    switch (type) {
        case GrammParser.NUMERIC_LITERAL:
            System.out.println("numeric literal");
            break;
        case GrammParser.STRING_LITERAL:
            System.out.println("string literal");
            break;
    }

    System.out.println(node.getSymbol().getText());
    return super.visitTerminal(node); 
}

What's the difference between visitLiteral and visitLiteralExpression()?

前者代表你的literal作品,后者代表你的expr作品。请注意,# 符号在 ANTLR 4 语法中具有特殊含义,代表一个标签 - 产品内部备选方案的名称。这不是评论。因为你的expr只有一个选择,所以变成了visitLiteralExpression。尝试将其注释掉 (//) 并查看生成的代码更改。