1

我有以下语法:

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]]]_

我该如何解决这个问题?

4

1 回答 1

1

您只能setText(...)在创建令牌后使用。您正在递归调用此令牌设置一些其他文本,这将不起作用。您需要创建一个解析器规则QualifiedName而不是词法分析器规则,并删除fragmentbefore Identifier

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("]_");} )*
   ;
于 2012-05-01T10:22:08.610 回答