Regex jflex最高效的前瞻性替代品

Regex jflex最高效的前瞻性替代品,regex,flex-lexer,regex-lookarounds,lexer,jflex,Regex,Flex Lexer,Regex Lookarounds,Lexer,Jflex,我正在用jflex编写标记器。我需要匹配像干扰素-a这样的单词作为一个标记,像干扰素-alpha这样的单词作为三个标记 显而易见的解决方案是lookaheads,但它们在jflex中不起作用。对于一个类似的任务,我编写了一个函数,在匹配的模式之后匹配一个额外的通配符,检查它在java代码中是否是空白,并将其返回匹配字符串的一部分或不带匹配字符串的一部分 REGEX=[:letter:][+\-[:letter:][. 从字符串interferon alpha中,它将匹配interferon al

我正在用jflex编写标记器。我需要匹配像
干扰素-a
这样的单词作为一个标记,像
干扰素-alpha
这样的单词作为三个标记

显而易见的解决方案是lookaheads,但它们在jflex中不起作用。对于一个类似的任务,我编写了一个函数,在匹配的模式之后匹配一个额外的通配符,检查它在java代码中是否是空白,并将其返回匹配字符串的一部分或不带匹配字符串的一部分

REGEX=[:letter:][+\-[:letter:][.

从字符串
interferon alpha
中,它将匹配
interferon al
。 然后,在Java代码部分,它将检查匹配的最后一个字符是否是空白。事实并非如此,因此
-al
将被推回并
干扰素
返回

干扰素-a
的情况下,空格将被推回并
干扰素
返回


但是,如果匹配的字符串没有任何结果,则此函数不起作用。而且,它看起来很笨重。因此,我想知道是否有更好的方法来确保下面的字符是空白,而不需要实际匹配并返回它。

JFlex当然有一个前瞻功能,与(f)lex相同。与Java正则表达式前瞻断言不同,JFlex前瞻只能在匹配结束时应用,但在其他方面类似。其描述见:

在词汇规则中,正则表达式
r
后面可能跟一个先行表达式。前瞻表达式可以是
$
(行尾运算符)或后跟任意正则表达式的
/
。在这两种情况下,前瞻不被使用,也不包括在匹配的文本区域中,但在确定哪个规则具有最长的匹配时,会被考虑

所以你当然可以写下规则:

[:letter:]+\-[:letter:]/\s
但是,您不能将这样的规则放入宏定义(
REGEX=…
),因为手册中也提到了(在中):

右侧的正则表达式必须格式正确,并且不能包含
^
/
$
运算符

因此,前瞻运算符只能在模式规则中使用

请注意,
\s
匹配任何空格字符,包括换行符,而
不匹配任何换行符。我想这就是导致您评论的原因,
REGEX=[:letter:][+\-[:letter:][.
“如果匹配的字符串没有任何后续内容,则不起作用”(我猜您的意思是“在同一行上没有任何后续内容,并且您打算编写
而不是
.

您可能(取决于您的语言)更喜欢测试非单词字符,而不是测试以下空白:

[:letter:]+\-[:letter:]/\W
或者制作一个更精确的规范作为一组Unicode属性,如
\W
的定义(也可以在JFlex手册的链接部分找到)

说到这里,我想重复你的建议:首先使用更具体的模式。例如,使用以下两种模式将确保第一种模式能够拾取带有单个字母后缀的单词,同时避免显式回推

[:letter:]+(-[:letter:])?   { /* matches 'interferon' or 'interferon-a' */ }
[:letter:]+/-[:letter:]+    { /* matches only 'interferon' from 'interferon-alpha' */ }

当然,在这种情况下,您可以通过使用
{2,}轻松避免第二个模式和第一个模式之间的冲突
而不是
+
进行第二次重复,但是依赖模式排序是完全可以的,因为保证模式不重叠通常是不方便的。

我不确定这是否是Maven问题,但我无法使用/或$-编译任何内容,例如,正则表达式会导致生成错误。这也是我不能这样做的原因尽管JFlex不支持lookaheads。@圣地亚哥:你说得对,我错了。JFlex不允许宏中出现
/
;我修复了示例并添加了一个注释。另请参见答案末尾的新注释。