在 flex manual它提到了“尾随上下文”模式 (r/s
),这意味着 r
,但前提是后跟 s
。但是,以下代码无法编译(相反,它给出了“无法识别的规则”的错误。为什么?
LITERAL a/b
%%
{LITERAL} { }
最佳答案
简单的答案是,除非您使用 -l
选项(不建议使用该选项),否则您无法将尾随上下文放入名称定义中。那是因为弹性:
不允许括号内有尾随上下文;和
自动用括号将定义的扩展括起来,少数情况除外(见下文)。
flex 用括号包围扩展的原因是否则会发生奇怪的事情。例如:
prefix milli|centi
%%
{prefix}pede return BUG;
如果没有自动括号,模式将扩展为:
milli|centipede
这与millipede
不匹配。 (各种后缀运算符也存在类似的问题。例如,考虑 {prefix}?pede
。)
Flex 不允许括号内包含尾随上下文,因为许多此类表达式更难编译。实际上,您最终可以编写两个正则表达式的交集模式。 (例如,({base}/{a}){b}
匹配 {base}
后跟 {b}
,它可以是{a}
的前缀或投影。)这些仍然是正则表达式,但 Thomson 算法并未考虑将正则表达式转换为有限状态机。由于该功能很少需要,因此从未尝试过实现它。
不幸的是,禁止括号内的尾随上下文也会禁止包含尾随上下文的模式周围的冗余括号,这包括定义扩展,因为定义是用可能冗余的括号扩展的。
原始的 AT&T lex 没有添加括号,这就是为什么用 -l
强制 lex 兼容可以让你的 Flex 文件编译。但是,如上所述,它可能会导致各种其他问题,因此我不推荐它。
此外,这里的“尾随上下文”是指 r/s
形式或 r$
形式的完整模式。将 r/s
放在括号内(无论是显式还是隐式)会产生错误消息,但将 r$
放在括号内只会使 $
匹配$
字符,而不是强制模式在行尾匹配。在这种情况下,不会发出错误或警告。
这将导致无法在名称定义中使用 $
(或 ^
)。然而,在版本 2.3.53 之前的某个时刻,插入了一个 hack,如果定义以 ^
开头或以 $
结尾,则会抑制括号。而且,由于我不完全理解的原因,如果扩展发生在尾随上下文的末尾,它也会抑制括号。这可能是一个错误,并且确实有一个与之相关的错误报告。
关于parsing - 匹配 Flex 中的尾随上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15558684/