Java ANTLR:处理表情符号

Java ANTLR:处理表情符号,java,unicode,antlr,antlr4,Java,Unicode,Antlr,Antlr4,我正在使用下面的EmojiLexer.g4和antlr4.7.2 lexer grammar EmojiLexer; String : '"' StringChar* '"' ; fragment StringChar : ~["\r\n] ; Punctuation : ( '[' | ':' | ']' | ';' | '@' ) ; fra

我正在使用下面的EmojiLexer.g4和antlr4.7.2

lexer grammar EmojiLexer;

String
    : '"'   StringChar*  '"'
    ;

fragment StringChar
    : ~["\r\n]
    ;

Punctuation
    : ( '['
      | ':'
      | ']'
      | ';'
      | '@'
      )
    ;

fragment IdentifierNonDigit
    : [a-zA-Z_$\u0080-\uffff]
    ;

Identifier
    : IdentifierNonDigit+
    ;

Whitespace
    : [ \t]+
      -> skip
    ;

Newline
    : ( '\r' '\n'?
      | '\n'
      )
      -> skip
    ;
下面的Java代码将lex转换为字符串:

public class EmojiTest {

public static void main(String[] args) {
    final String string = "[foo bar:bazz];\n"
                          + "\n"
                          + "@\"emojis break it: \uD83D\uDE31\";\n"
                          + "\n"
                          + "[foo bar:bazz];\n";
    final CharStream charStream = CharStreams.fromString(string);
    final EmojiLexer lexer = new EmojiLexer(charStream);
    while (true) {
        final Token token = lexer.nextToken();
        final int type = token.getType();
        if (type < 0) {
            break;
        }

        final int startIndex = token.getStartIndex();
        final int stopIndex = token.getStopIndex() + 1;
        System.out.println(startIndex + "-" + stopIndex + ": " + type + ": " + escape(string.substring(startIndex, stopIndex)));
    }
}

private static String escape(String s) {
    final StringBuilder buffer = new StringBuilder();
    for (int i = 0; i < s.length(); i++) {
        final char chr = s.charAt(i);
        if (chr >= 0x20 && chr < 0x7f) {
            buffer.append(chr);
        }
        else {
            buffer.append("\\u");
            final String hex = Integer.toHexString(chr);
            for (int j = hex.length(); j < 4; j++) {
                buffer.append('0');
            }
            buffer.append(hex);
        }
    }
    return buffer.toString();
}
公共类EmojiTest{
公共静态void main(字符串[]args){
final String=“[foo-bar:bazz];\n”
+“\n”
+“@\”表情符号打断它:\uD83D\uDE31\”;\n
+“\n”
+“[foo-bar:bazz];\n”;
final CharStream CharStream=CharStreams.fromString(字符串);
最终EmojiLexer lexer=新的EmojiLexer(charStream);
while(true){
最终令牌=lexer.nextToken();
final int type=token.getType();
如果(类型<0){
打破
}
final int startIndex=token.getStartIndex();
final int stopIndex=token.getStopIndex()+1;
System.out.println(startIndex+“-”+stopIndex+”:“+type+”:“+escape(string.substring(startIndex,stopIndex)));
}
}
私有静态字符串转义(字符串s){
最终StringBuilder缓冲区=新StringBuilder();
对于(int i=0;i=0x20&&chr<0x7f){
缓冲区追加(chr);
}
否则{
buffer.append(“\\u”);
最终字符串hex=Integer.toHexString(chr);
对于(int j=hex.length();j<4;j++){
buffer.append('0');
}
buffer.append(十六进制);
}
}
返回buffer.toString();
}
}


但不知何故,您使用了一个代理项对来指定表情符号。我不确定这是否仍然得到支持。相反,使用完整的UTF-32规范:
\u{1f631}
for的问题是,ANTLR是代码点感知的,返回的索引是代码点索引。因此,应用程序代码也需要调整以处理代码点。

似乎是一个bug:很高兴认识Mike!添加行不会改变任何事情。同时,将StringChar的定义更改为片段StringChar:([\p{Emoji}]| ~[“\r\n])也不会help@Mike:为了让语法和代码按预期工作,我到底需要更改什么?@ThomasS。我在答案中添加了我的令牌输出。这里的一个要点似乎是如何指定输入。