带有硬编码异常的 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-labeled
和 MXs12-C123
。 MXs12-labeledblack
和 MXs12-labeled-black
都将被报告为单个标记;我完全不清楚您对这些输入的期望是什么。
Rici 的回答解决了问题 - yypushback()
正是我所需要的。截至目前
- jflex 捕获所有带或不带后缀的字符串
- ACRONYMS 的输出部分有额外的 java 正则表达式,检查字符串是否有后缀,如果有则使用
yypushback()
。
使用额外的 java 正则表达式,我可以涵盖提到的边缘情况,例如"\-labeled$"
确保后缀位于传递字符串的末尾,并且 MXs12-labeled-black
将作为一个标记返回,而 MXs12-labeled
作为三个标记返回。非常感谢!
我需要 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-labeled
和 MXs12-C123
。 MXs12-labeledblack
和 MXs12-labeled-black
都将被报告为单个标记;我完全不清楚您对这些输入的期望是什么。
Rici 的回答解决了问题 - yypushback()
正是我所需要的。截至目前
- jflex 捕获所有带或不带后缀的字符串
- ACRONYMS 的输出部分有额外的 java 正则表达式,检查字符串是否有后缀,如果有则使用
yypushback()
。
使用额外的 java 正则表达式,我可以涵盖提到的边缘情况,例如"\-labeled$"
确保后缀位于传递字符串的末尾,并且 MXs12-labeled-black
将作为一个标记返回,而 MXs12-labeled
作为三个标记返回。非常感谢!