【问题标题】:Matching trailing context in flex在 flex 中匹配尾随上下文
【发布时间】:2013-03-11 14:54:56
【问题描述】:

flex manual 中,它提到了一个“尾随上下文”模式(r/s),这意味着r,但前提是后面跟着s。但是以下代码无法编译(而是给出“无法识别的规则”的错误。为什么?

LITERAL a/b
%%
{LITERAL} { }

【问题讨论】:

    标签: parsing lex flex-lexer


    【解决方案1】:

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

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

    • 自动用括号括住定义的扩展,少数情况除外(见下文)。

    flex 用括号括住扩展的原因是,否则会发生奇怪的事情。例如:

    prefix        milli|centi
    %%
    {prefix}pede  return BUG;
    

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

    milli|centipede
    

    millipede 不匹配。 (各种后缀运算符也存在类似问题。例如,考虑{prefix}?pede。)

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

    不幸的是,禁止括号内的尾随上下文也禁止在包含尾随上下文的模式周围使用冗余括号,这包括定义扩展,因为定义可能使用冗余括号进行扩展。

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

    此外,这里的“尾随上下文”是指r/sr$ 形式的完整模式。将r/s 放在括号内(无论是显式还是隐式)都会产生错误消息,但将r$ 放在括号内只会使$ 匹配$ 字符,而不是强制模式匹配在行尾.在这种情况下不会发出错误或警告。

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

    【讨论】:

    • "原来的 AT&T lex 没有添加多余的括号" 正确,但它们不是多余的,否则不会存在此问题。大约在 1991 年,应我的要求,这在 flex 中进行了更改。
    • @EJP,我认为他们是个好主意。我不是说清楚了吗?但如果模式仅由扩展组成,它们肯定是多余的。不过,我会改正你抱怨的那句话。
    【解决方案2】:

    我在flexinfo 页面的常见问题解答中找到了您问题的答案:“您的问题是扫描仪中的某些定义使用了'/' 尾随上下文运算符,并将其包含在() 的。Flex 不允许将此运算符包含在 () 中,因为这样做允许未定义的正则表达式,例如 "(a/b)+"。因此解决方案是删除括号。请注意,您还必须构建扫描仪使用-l 选项以实现 AT&T lex 兼容性。没有此选项,flex 会自动将定义括在括号中。” (引自弗恩·帕克森)。另见FAQ trailing context

    尽可能避免使用尾随上下文。如上所述,它不允许在嵌套表达式中使用。您的示例确实适用于 -l 选项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-24
      • 2018-12-14
      相关资源
      最近更新 更多