带有硬编码异常的 jFlex 中的正则表达式

Regex in jFlex with hardcoded exceptions

我需要 jFlex 中的正则表达式来匹配字符串文字,其中包含一些字符,后跟一个连字符,再后跟一个单词。但是,有一些硬编码的例外。我的 jFlex 版本是 1.6.1

我的正则表达式是:

SUFFIXES = labeled|deficient
ALPHANUMERIC = [:letter:]|[:digit:]
AVOID_SUFFIXES = {SUFFIXES} | !({ALPHANUMERIC}+)
WORD = ({ALPHANUMERIC}+([\-\/\.]!{AVOID_SUFFIXES})*)

字符串 "MXs12-labeled" 应标记为 'MXs12', '-', 'labeled'(连字符稍后被不同的正则表达式捕获),而 "MXs12-C123" 应标记为 'MXs12-C123',因为 C123 不在后缀列表中。

然而,我获得的令牌是 "MXs12-labele" - 比异常禁止的字母少一个字母。

一个明显的解决方案是在正则表达式中包含额外的非 {ALPHANUMERIC} 字符,但这也会将此字符添加到匹配项中。

另一个解决方案似乎是使用否定前瞻,但每次我尝试解析它们时它们 return 出现语法错误 - jFlex 似乎不支持它。 (Flex seems do not support a regex lookahead assertion (the fast lex analyzer))

有谁知道如何在 jFlex 中解决这个问题?

如您所见,使用正匹配比使用负匹配要容易得多。 (很明显,labele 不匹配 labeled,而且它是 labeled 的最长前缀,它不匹配 labeled,所以如果你试图匹配一个!labeled 这个词,你会得到 labele 作为匹配项。

JFlex 没有实现否定的先行断言,它们略有不同但仍然存在问题。否定的先行断言肯定会拒绝 MXs12-labeled 中的后缀,但它也会拒绝 MXs12-labeledblack 中的后缀,我认为这有点令人惊讶。

不过,如果您用肯定的匹配项来重新表述,那就真的很简单了。这个想法是指定每个正匹配需要做什么。在这种情况下,我们想要对 -labeled 的正匹配做的是将其放回输入流中,这可以用 yypushback 完成。这会建议这样的规则:

{ALPHANUMERIC}+ ({DELIMITER}{ALPHANUMERIC}+)* "-labeled"  { yypushback(8); /* return the WORD */ }
{ALPHANUMERIC}+ ({DELIMITER}{ALPHANUMERIC}+)* "-deficient"  { yypushback(10); return /* return the WORD */ }
{ALPHANUMERIC}+ ({DELIMITER}{ALPHANUMERIC}+)* { return /* return the WORD */ }

请注意顺序很重要,因为序列依赖于前两个模式的优先级高于最后一个模式。 (匹配前两个模式之一的输入也将匹配最后一个模式,但顺序中的规则表明最后一个模式不会获胜。)

这可能是也可能不是您真正想要的。它将按照您的问题中的指示处理 MXs12-labeledMXs12-C123MXs12-labeledblackMXs12-labeled-black 都将被报告为单个标记;我完全不清楚您对这些输入的期望是什么。

Rici 的回答解决了问题 - yypushback() 正是我所需要的。截至目前

  1. jflex 捕获所有带或不带后缀的字符串
  2. ACRONYMS 的输出部分有额外的 java 正则表达式,检查字符串是否有后缀,如果有则使用 yypushback()

使用额外的 java 正则表达式,我可以涵盖提到的边缘情况,例如"\-labeled$" 确保后缀位于传递字符串的末尾,并且 MXs12-labeled-black 将作为一个标记返回,而 MXs12-labeled 作为三个标记返回。非常感谢!