我需要在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中解决这个问题吗?
答案 0 :(得分:1)
如您所见,使用正匹配比使用负匹配要容易得多。 (很明显,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-labeled
和MXs12-C123
。 MXs12-labeledblack
和MXs12-labeled-black
都将被报告为单个令牌;我不清楚您对这些投入的期望是什么。
答案 1 :(得分:0)
Rici的答案解决了这个问题-yypushback()
正是我所需要的。截至目前
yypushback()
。使用其他Java正则表达式,我可以涵盖上述的极端情况,例如"\\-labeled$"
确保后缀位于传递的字符串的末尾,并且MXs12-labeled-black
将作为一个令牌返回,而MXs12-labeled
将作为三个令牌返回。非常感谢你!