在flex manual中,它提到了一个"尾随上下文"模式(r/s
),表示r
,但仅在s
后跟。但是,下面的代码没有编译(相反,它会给出错误"无法识别的规则"。为什么?
LITERAL a/b
%%
{LITERAL} { }
答案 0 :(得分:6)
简单的答案是,除非您使用{em> not 推荐的-l
选项,否则不能将尾随上下文放入名称定义中。那是因为flex:
不允许括号内的尾随上下文;以及
会自动用括号括起扩展定义,但在少数情况下(见下文)。
flex围绕括号扩展的原因是否则会发生奇怪的事情。例如:
prefix milli|centi
%%
{prefix}pede return BUG;
如果没有自动括号,模式将扩展为:
milli|centipede
与millipede
不匹配。 (各种后缀运算符也存在类似的问题。例如,考虑{prefix}?pede
。)
Flex不允许在括号内使用尾随上下文,因为很多这样的表达式更难编译。实际上,您最终可以编写两个正则表达式交集的模式。 (例如,({base}/{a}){b}
匹配{base}
后跟{b}
,{a}
是-l
的前缀或投影。)这些仍然是正则表达式,但它们不是Thomson算法没有考虑将正则表达式转换为有限状态机。由于该特征很少需要,因此没有尝试过实现它。
不幸的是,禁止括号内的尾随上下文也禁止围绕包含尾随上下文的模式的冗余括号,这包括定义扩展,因为定义是用可能多余的括号扩展的。
最初的AT& T lex没有添加括号,这就是为什么强制与r/s
的lex兼容性允许你的flex文件进行编译。但是,如上所述,它可能会导致各种其他问题,所以我不推荐它。
此外,“尾随上下文”在此处表示表单r$
或表单r/s
的完整模式。将r$
置于括号内(无论是显式还是隐式)会产生错误消息,但将$
放在括号内只会使$
匹配$
个字符,而不是强制模式在一条线的末尾匹配。在这种情况下不会发出错误或警告。
这样就无法在名称定义中使用^
(或^
)。但是,在版本2.3.53之前的某个时刻,如果定义以$
开头或以{{1}}结尾,则会插入一个hack来抑制括号。并且,由于我不完全理解的原因,如果扩展发生在尾随上下文的末尾,它也会抑制括号。这可能是一个错误,实际上有一个与之相关的错误报告。
答案 1 :(得分:1)
我在info
的{{1}}页面的常见问题解答中找到了问题的答案:“您的问题是扫描程序中的某些定义使用'/'尾随上下文运算符,并且将它包含在()中.Flex不允许将此运算符括在()中,因为这样做允许使用未定义的正则表达式,例如flex
。所以解决方法是删除括号。注意你还必须使用"(a/b)+"
选项构建扫描仪以实现AT& T lex兼容性。如果没有此选项,flex会自动将定义括在括号中。“ (引自Vern Paxson)。另请参阅FAQ trailing context
尽可能避免使用尾随上下文。如上所述,嵌套表达式中不允许使用它。您的示例适用于-l
选项。