有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java ANTLR以递归方式替换令牌

我的语法如下:

rule: q=QualifiedName {System.out.println($q.text);};

QualifiedName
   :   
        i=Identifier { $i.setText($i.text + "_");}
        ('[' (QualifiedName+ | Integer)? ']')*
   ;


Integer
    : Digit Digit*
    ;

fragment
Digit 
    : '0'..'9'
    ;

fragment
Identifier
    :   (   '_'
        |   '$'
        |   ('a'..'z' | 'A'..'Z')
        )
        ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$')*
    ;

以及来自Java的代码:

ANTLRStringStream stream = new ANTLRStringStream("array1[array2[array3[index]]]");
TestLexer lexer = new TestLexer(stream);
CommonTokenStream tokens = new TokenRewriteStream(lexer);
TestParser parser = new TestParser(tokens);
try {
    parser.rule();
} catch (RecognitionException e) {
    e.printStackTrace();
}

对于输入:array1[array2[array3[index]]],我想修改每个标识符。我希望看到输出:array1_[array_2[array3_[index_]]],但输出与输入相同

所以问题是:setText()方法为什么在这里不起作用

编辑:

我用以下方式修改了巴特的答案:

rule: q=qualifiedName {System.out.println($q.modified);};

qualifiedName returns [String modified]
   :   
        Identifier
        ('[' (qualifiedName+ | Integer)? ']')*
        {
            $modified = $text + "_";
        }
   ;

Identifier
    :   (   '_'
        |   '$'
        |   ('a'..'z' | 'A'..'Z')
        )
        ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$')*
    ;

Integer
    : Digit Digit*
    ;

fragment
Digit 
    : '0'..'9'
    ;

我想修改规则qualifiedName匹配的每个标记。我尝试了上面的代码,对于输入array1[array2[array3[index]]],我希望看到输出array1[array2[array3[index_]_]_]_,但是只修改了最后一个标记:array1[array2[array3[index]]]_

我怎样才能解决这个问题


共 (1) 个答案

  1. # 1 楼答案

    创建令牌后,您只能使用setText(...)。您正在递归地调用此令牌设置其他一些文本,这将不起作用。您需要从QualifiedName而不是lexer规则中创建解析器规则,并删除Identifier之前的fragment

    rule: q=qualifiedName {System.out.println($q.text);};
    
    qualifiedName
       :   
            i=Identifier { $i.setText($i.text + "_");}
            ('[' (qualifiedName+ | Integer)? ']')*
       ;
    
    Identifier
        :   (   '_'
            |   '$'
            |   ('a'..'z' | 'A'..'Z')
            )
            ('a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '$')*
        ;
    
    Integer
        : Digit Digit*
        ;
    
    fragment
    Digit 
        : '0'..'9'
        ;
    

    现在,它将在控制台上打印:array1_[array2_[array3_[index_]]]

    编辑

    我不知道您为什么要这样做,但似乎您只是试图将]重写为]_,这可以通过与上面所示相同的方式完成:

    qualifiedName
       :   
            Identifier
            ('[' (qualifiedName+ | Integer)? t=']' {$t.setText("]_");} )*
       ;