在flex中匹配尾随上下文

jle*_*ahy 1 parsing lex flex-lexer

flex手册中,它提到了一个"尾随上下文"模式(r/s),这意味着r,但只有在后面跟着s.但是,以下代码无法编译(相反,它会出现"无法识别的规则"错误.为什么?

LITERAL a/b
%%
{LITERAL} { }
Run Code Online (Sandbox Code Playgroud)

ric*_*ici 6

简单的答案是,除非您使用推荐的-l选项,否则不能将尾随上下文放入名称定义中.这是因为flex:

  • 不允许括号内的尾随上下文; 和

  • 除了少数情况外(见下文),用括号自动包围定义的扩展.

flex围绕扩展括号的原因是否则会发生奇怪的事情.例如:

prefix        milli|centi
%%
{prefix}pede  return BUG;
Run Code Online (Sandbox Code Playgroud)

如果没有自动括号,模式将扩展为:

milli|centipede
Run Code Online (Sandbox Code Playgroud)

哪个不匹配millipede.(各种后缀运算符也有类似的问题.例如{prefix}?pede,考虑一下.)

Flex不允许在括号内使用尾随上下文,因为许多此类表达式更难编译.实际上,您最终可以编写两个正则表达式交集的模式.(例如,({base}/{a}){b}匹配{base}后跟{b}一个前缀或一个投影{a}.)这些仍然是正则表达式,但Thomson算法不会考虑将正则表达式转换为有限状态机.由于该特征是很少,如果有需要,没有尝试实施它.

不幸的是,禁止括号内的尾随上下文也禁止围绕包含尾随上下文的模式的冗余括号,这包括定义扩展,因为定义是用可能多余的括号扩展的.

最初的AT&T lex没有添加括号,这就是为什么强制lex兼容性-l允许你的flex文件编译.但是,如上所述,它可能会导致各种其他问题,所以我不推荐它.

此外,"尾随上下文"在这里表示表单r/s或表单的完整模式r$.放在r/s括号内(无论是显式还是隐式)会产生错误消息,但放在r$括号内只会使$匹配成为一个$字符,而不是强制模式在一行的末尾匹配.在这种情况下不会发出错误或警告.

这将使得无法在名称定义中使用$(或^).但是,在版本2.3.53之前的某个时刻,插入了一个hack,如果定义以^或以其结尾,则会抑制括号$.并且,由于我不完全理解的原因,如果扩展发生在尾随上下文的末尾,它也会抑制括号.这可能是一个错误,确实有一个与之相关的错误报告.