我需要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}
字符,但这也会将此字符添加到匹配项中。
另一种解决方案似乎是使用负面的前瞻性,但是每次我尝试解析它们时,它们都会返回语法错误 - jFlex似乎不支持它。(Flex 似乎不支持正则表达式前瞻断言(快速 lex 分析器))
有谁知道如何在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-labeled
和MXs12-C123
处理。MXs12-labeledblack
和MXs12-labeled-black
都将报告为单个令牌;我完全不清楚你对这些输入的期望是什么。
Rici的回答解决了这个问题 -yypushback()
这正是我所需要的。截至目前
- jflex 捕获所有字符串,带或不带后缀
- 在ACRONYMS的输出部分中有额外的Java正则表达式,检查字符串是否有后缀,如果是,则使用
yypushback()
。
使用额外的 java 正则表达式,我可以涵盖上述边缘情况,例如"\-labeled$"
确保后缀位于传递的字符串的末尾,并且MXs12-labeled-black
将作为一个标记返回,而MXs12-labeled
作为三个标记返回。谢谢!