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

时间:2019-07-17 16:52:06

标签: regex flex-lexer jflex

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

我的正则表达式是:

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

字符串“带有MXs12标签的” 应该标记为“ MXs12”,“-”,“标签” (以后由不同的正则表达式捕获的连字符)和“ MXs12-C123” 转换为'MXs12-C123',因为C123不在后缀列表中。

但是,我获得的令牌是“ MXs12-labele” -比例外禁止的字母短一个字母。

一个明显的解决方案是在正则表达式中包含其他非{ALPHANUMERIC}字符,但这也会将该字符添加到匹配项中。 另一个解决方案似乎是使用负前瞻,但是每次我尝试解析它们时它们都返回语法错误-jFlex似乎不支持它。 (Flex seems do not support a regex lookahead assertion (the fast lex analyzer)

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

2 个答案:

答案 0 :(得分:1)

如您所见,使用正匹配比使用负匹配要容易得多。 (很明显,labelelabeled不匹配,而且它是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都将被报告为单个令牌;我不清楚您对这些投入的期望是什么。

答案 1 :(得分:0)

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

  1. jflex捕获带后缀或不带后缀的所有字符串
  2. 输出部分中还有ACRONYMS的其他Java正则表达式,用于检查字符串是否具有后缀,如果有则使用yypushback()

使用其他Java正则表达式,我可以涵盖上述的极端情况,例如"\\-labeled$"确保后缀位于传递的字符串的末尾,并且MXs12-labeled-black将作为一个令牌返回,而MXs12-labeled将作为三个令牌返回。非常感谢你!