在flex 手册中,它提到了一个“尾随上下文”模式 ( r/s
),这意味着r
,但只有在后面跟着s
. 但是以下代码无法编译(而是给出“无法识别的规则”的错误。为什么?
LITERAL a/b
%%
{LITERAL} { }
在flex 手册中,它提到了一个“尾随上下文”模式 ( 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}
后跟 a {b}
,它是前缀或 的投影{a}
。)这些仍然是正则表达式,但 Thomson 算法并未考虑将正则表达式转换为有限状态机。因为该特征是很少需要,也没有尝试实施它。
不幸的是,禁止括号内的尾随上下文也禁止在包含尾随上下文的模式周围使用冗余括号,这包括定义扩展,因为定义可能使用冗余括号进行扩展。
最初的 AT&T lex 没有添加括号,这就是为什么强制 lex-compatibility with-l
允许您的 flex 文件编译的原因。但是,如上所述,它可能会导致各种其他问题,因此我不推荐它。
此外,这里的“尾随上下文”是指 formr/s
或 form的完整模式r$
。放入r/s
括号内(无论是显式还是隐式)都会产生错误消息,但放入r$
括号内只会使$
匹配成为一个$
字符,而不是强制模式在行尾匹配。在这种情况下不会发出错误或警告。
这将使得在名称定义中无法使用$
(or )。^
但是,在版本 2.3.53 之前的某个时间点,插入了一个 hack,如果定义^
以$
. 而且,由于我不完全理解的原因,如果扩展发生在尾随上下文的末尾,它也会抑制括号。这可能是一个错误,并且确实有一个与之相关的错误报告。
info
我在以下页面的常见问题解答中找到了您问题的答案flex
:“您的问题是扫描仪中的某些定义使用'/'尾随上下文运算符,并将其包含在 () 中。Flex 不允许此运算符包含在 () 中,因为这样做允许未定义的正则表达式,例如"(a/b)+"
。所以解决方案是删除括号。请注意,您还必须使用-l
AT&T lex 兼容性选项构建扫描仪。没有此选项, flex 自动将定义括在括号中。” (引自弗恩·帕克森)。另请参阅常见问题解答尾随上下文
如果可能,最好避免使用尾随上下文。如上所述,它不允许在嵌套表达式中使用。您的示例确实适用于该-l
选项。