(F)lex 没有实现negative lookahead assertions。 (注意:前面的链接不是认可。)
您可以在flex manual 中找到 flex 接受的正则表达式运算符的完整列表;如果语法不在该列表中,则无论在线正则表达式服务告诉您什么,它都不会被识别。 (注意:前面的链接是背书。)
(F)lex 确实实现了积极的前瞻断言,但仅在模式的最后。这用trailing context operator / 表示。您可以使用该运算符来识别您的令牌,方法是要求它后跟 A 以外的其他内容:
[bB]{4,}[aA]{1,3}/[^Aa] { printf("%s ", yytext); }
但这不是完全相同的语义,因为它不会在输入的最后识别标记。它要求令牌后面跟着不是 A 的 something; begin 后跟 nothing 不算。 (实际上,这可能没有太大区别。如果您正在扫描来自文本流的输入,您可以合理地期望该流将换行符作为最后一个字符,并且换行符将匹配 [^Aa]。但是,如果您打算扫描可能根本没有换行符的文本字符串,那么您需要注意这个问题。)
大多数时候,这并不是你真正想要的。或者,如果它确实是您想要的,那么 (f)lex 可能不适合您的用例。
(F)lex 旨在将输入划分为连续的标记。它不搜索令牌;它在当前输入点识别令牌。它预计整个输入将由标记组成,因此需要在每个点匹配一些模式。
在此基础上,你需要考虑一个不匹配的序列是什么样的标记。举个例子:
bbbbbbbaaaa
这有太多的 a 不能成为您的规则的“字符串”。那是什么?
有效令牌 bbbbbbbaaa 后跟另一个以 a 开头的令牌?
与其他模式匹配的有效令牌? (例如LONG_STRING)?
应忽略的无效令牌,允许继续扫描?
不可恢复的错误?
所有这些情况都可以在不使用任何环视运算符的情况下处理。
在第一种情况下,使用匹配有效标记的正则表达式就足够了:
[bB]{4,}[aA]{1,3} { printf("Valid STRING: %s ", yytext); }
在第二种情况下,您可以依赖 (f)lex 最大 munch 匹配规则,该规则指出将使用最长匹配对应的模式:
[bB]{4,}[aA]{1,3} { printf("Valid STRING: %s ", yytext); }
[bB]{4,}[aA]{4,} { printf("Valid LONG STRING: %s ", yytext); }
这可以简化:
[bB]{4,}[aA]{1,3} { printf("Valid STRING: %s ", yytext); }
[bB]{4,}[aA] { printf("Valid LONG STRING: %s ", yytext); }
这将产生相同的效果,因为 (f)lex 规则在两个具有最长匹配项的模式之间做出决定是使用输入文件中的第一个模式。所以bbbbaa--- 的前六个字符匹配两个模式,因此第一个获胜,而bbbbaaaa--- 与第一个模式匹配七个字符,与第二个匹配八个字符,因此第二个获胜。
对于第三种和第四种情况,也可以使用上面的一对模式;唯一的区别在于对应于第二种模式的动作。对于案例 3:忽略令牌,可能会发出警告;对于案例 4:生成错误消息并终止扫描。