ANTLR lexer 模式 [\p{Emoji}]+ 匹配数字

ANTLR lexer patern [\p{Emoji}]+ is matching numbers

ANTLR4 词法分析器模式 [\p{Emoji}]+ 正在匹配数字。见截图。请注意,它正确地拒绝了字母字符。模式有问题吗?

查看 the code 似乎定义了表情符号代码点:

UnicodeSet emojiRKUnicodeSet = new UnicodeSet("[\p{GCB=Regional_Indicator}\*#0-9\u00a9\u00ae\u2122\u3030\u303d]");

它看起来包括数字(为什么,我不知道,请查看 sepp2k 的出色解释)。 如果你觉得有什么地方不对可以随时raise an issue

您也可以只使用这样的字符 class:

Identifier
 : [\u00a9\u00ae\u2000-\u3300\ud83c\ud000-\udfff\ud83d\ud000-\udfff\ud83e\ud000-\udfff]+
 ;

\p{Emoji} 匹配所有具有 Unicode 表情符号 属性 的内容。数字确实有 属性,所以 \p{Emoji} 在匹配它们时是正确的。为什么呢?

Unicode 标准将任何代码点定义为具有表情符号 属性,前提是它可以作为表情符号的一部分出现。数字可以作为表情符号的一部分出现(例如,我认为上面有数字的形状,出于他们的原因算作表情符号,由一个形状组成,后跟一个连接,然后是数字),所以他们有 属性.

如果您只想匹配本身就是表情符号的代码点,您可以只使用 Emoji_Presentation 属性。但是,这将无法匹配组合的表情符号。

如果你想匹配任何创建表情符号的序列,我想你会想要匹配类似“Emoji_Presentation,后跟零个或多个'(Join_ControlVariation_Selector) 后跟 Emoji'"(这里你想要 Emoji 而不是 Emoji_Presentation 因为那是允许数字的地方)。


但是,为了允许在标识符中使用表情符号(而不是词法分析器规则来匹配表情符号而不是其他任何东西),您实际上不必担心数字是否是表情符号的一部分,只是它没有作为标识符的第一个字符出现。因此,您可以简单地将起始字符的片段定义为仅包含 Emoji_Presentation,然后将连续字符的片段定义为包含 Emoji 以及 Join_ControlVariation_Selector.

所以这样的事情会起作用:

fragment IdStart
    : [_\p{Alpha}\p{General_Category=Other_Letter}\p{Emoji_Presentation}]
    ;

fragment IdContinue
    : IdStart
    // The `\p{Number}` might be redundant, I'm not sure. I don't know
    // whether there are any (non-ascii) numeric codepoints that don't
    // also have the `Emoji` property.
    | [\p{Number}\p{Emoji}\p{Join_Control}\p{Variation_Selector}]
    ;

Identifier: IdStart IdContinue*;

当然,这是假设您确实想要允许表情符号以外的字符。您问题中的定义仅包含表情符号(或者无论如何都意味着),但由于它被称为 Identifier,我假设您只是删除了其他允许的类别以简化它。