Parsing 为什么我的ANTLR 4解析器规则没有返回所需的值?

Parsing 为什么我的ANTLR 4解析器规则没有返回所需的值?,parsing,antlr,antlr4,Parsing,Antlr,Antlr4,我尝试将ANTLR 4.3与同一版本的ANTLR 4 maven插件一起使用,以实现两个目标: 根据相当简单的语法验证用户提供的表达式,以防止注入无效或潜在危险的代码 重写表达式中的标识符,使其使用点符号完全限定,例如context.identifier 我对第2项有问题。因为我只需要对输入表达式进行非常小的修改,所以使用带有返回值的解析器规则似乎是合适的解决方案。但是,解析器返回原始标识符,而不是我期望看到的重写标识符 下面是语法的简化版本来说明该行为: grammar Sample; ex

我尝试将ANTLR 4.3与同一版本的ANTLR 4 maven插件一起使用,以实现两个目标:

  • 根据相当简单的语法验证用户提供的表达式,以防止注入无效或潜在危险的代码
  • 重写表达式中的标识符,使其使用点符号完全限定,例如
    context.identifier
  • 我对第2项有问题。因为我只需要对输入表达式进行非常小的修改,所以使用带有返回值的解析器规则似乎是合适的解决方案。但是,解析器返回原始标识符,而不是我期望看到的重写标识符

    下面是语法的简化版本来说明该行为:

    grammar Sample;
    
    expr
     : ( field_name ) EOF
     ;
    
    field_name returns [String fqn]
     : any_name { $fqn = "prefix." + $text; }
     ;
    
    any_name
     : IDENTIFIER
     | STRING_LITERAL
     | '(' any_name ')'
     ;
    
    IDENTIFIER
     : '"' (~'"' | '""')* '"'
     | '`' (~'`' | '``')* '`'
     | '[' ~']'* ']'
     | [a-zA-Z_] [a-zA-Z_0-9]*
     ;
    
    STRING_LITERAL
     : '\'' ( ~'\'' | '\'\'' )* '\''
     ;
    
    field_name规则用于将限定符前置到遇到的任何名称,并返回完全限定的名称。然而,在我的测试中,这似乎从来都不起作用:

    package sample;
    
    import static org.junit.Assert.assertEquals;
    
    import org.antlr.v4.runtime.ANTLRInputStream;
    import org.antlr.v4.runtime.BailErrorStrategy;
    import org.antlr.v4.runtime.CharStream;
    import org.antlr.v4.runtime.CommonTokenStream;
    import org.antlr.v4.runtime.ParserRuleContext;
    import org.antlr.v4.runtime.TokenStream;
    import org.junit.Test;
    
    public class SampleParserTest {
    
        @Test
        public void testSampleParser() {
            CharStream input = new ANTLRInputStream("field1");
            SampleLexer lexer = new SampleLexer(input);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            SampleParser parser = new SampleParser(tokens);
            BailErrorStrategy errorHandler = new BailErrorStrategy();
            parser.setErrorHandler(errorHandler);
            ParserRuleContext tree = parser.expr();
            TokenStream tokenStream = parser.getTokenStream();
            String fqn = tokenStream.getText(tree);
            assertEquals("prefix.field1", fqn);
            // org.junit.ComparisonFailure: expected:<[prefix.]field1> but
            // was:<[]field1>
        }
    
    }
    
    包装样品;
    导入静态org.junit.Assert.assertEquals;
    导入org.antlr.v4.runtime.antlInputStream;
    导入org.antlr.v4.runtime.BailErrorStrategy;
    导入org.antlr.v4.runtime.CharStream;
    导入org.antlr.v4.runtime.CommonTokenStream;
    导入org.antlr.v4.runtime.ParserRuleContext;
    导入org.antlr.v4.runtime.TokenStream;
    导入org.junit.Test;
    公共类SampleParserTest{
    @试验
    public void testSampleParser(){
    CharStream输入=新的AntlInputStream(“字段1”);
    SampleLexer lexer=新的SampleLexer(输入);
    CommonTokenStream令牌=新的CommonTokenStream(lexer);
    SampleParser=新的SampleParser(标记);
    BailErrorStrategy errorHandler=新的BailErrorStrategy();
    setErrorHandler(errorHandler);
    ParserRuleContext树=parser.expr();
    TokenStream TokenStream=parser.getTokenStream();
    字符串fqn=tokenStream.getText(树);
    assertEquals(“前缀.field1”,fqn);
    //org.junit.ComparisonFailure:应为:但
    //是:
    }
    }
    
    我的语法或单元测试有什么问题,它阻止field_name规则返回预期的完全限定名?有没有其他(更好的)方法来实现同样的目标

    提前感谢您的时间和专业知识