如何使用 Flex 在可读模式中使用尾随上下文?

how to use trailing context in readable patterns with Flex?

在 Flex 中,我可以像这样在名称定义中使用尾随模式:

NAME  foo$|bar

这通过了 flex。

但我不喜欢这样写没有空格的正则表达式,因为它们很难阅读。所以我想好好做:

NAME  (?x: foo$ | bar )

但是现在 flex 失败了,因为根据手册,"‘$’, cannot be grouped inside parentheses".

恕我直言,这很愚蠢,允许一些构造,但不允许以可读的方式描述它。

如何在 Flex 中使用具有可读模式的尾随上下文?

首先,回答您的问题:“如何在 Flex 中使用具有可读模式的尾随上下文?”。如果您坚持只有在模式中撒上空格时模式才可读,那么答案是 “你不能。” 对不起,但就是这样这是。 (?x: flag 在某些时候被 hack 到 flex 中,仍然有很多粗糙的边缘。

在某种程度上,这无关紧要,因为您不能将 $ 运算符用作 r|s 正则表达式中一个替代项的一部分。因此,即使您可以使用“可读语法”,它也不会是您想要的。您当然可以使用以下“可读语法”(至少,我认为它是可读的)。这意味着不同的东西,但它是 flex 支持的 $ 运算符的唯一用途:

NAME (?x: foo | bar )$

下面是一些注释。


In Flex, I can use the a trailing pattern in a name definition like this:

NAME  foo$|bar

不,你不能。或者,更好地说,您可以这样写,但它不涉及尾随上下文,因为:

…a '$' which does not occur at the end of a rule loses its special properties and is treated as a normal character.

(来自 Flex manual;这是该点中的最后一个短语,表示您不能将尾随上下文运算符放在括号内。)

flex 确实会拒绝(并且有点奇怪):

NAME  (?x: foo$ | bar )

尽管它会接受:

NAME  (?x: foo$| bar )

我会冒险说这是一个错误。仅当 $ 位于模式末尾时,它才会被识别为尾随上下文运算符。但是,检查的代码只是检查下一个字符是否为空白,因为模式在第一个空白字符处终止。 (模式不在定义中解析;当它实际包含在某些规则模式中时,它会被解析。)测试不检查 $ 是否在 [=24= 中] 块,所以在

(?x: foo$ | bar )

$是尾随上下文运算符,属于语法错误(运算符必须出现在模式的最末尾),而在

(?x: foo$| bar )

$只是一个普通字符,合法但可能出乎意料。


最后,注意一点:以下是完全合法的,$ 将被视为尾随上下文运算符,前提是定义用于模式的最后:

NAME  bar|foo$

但是,它可能也不是您认为的意思。尾随上下文运算符的优先级低于交替运算符,因此只要扩展位于模式的末尾,就会像写入一样进行解析

NAME  (bar|foo)$

我强烈建议不要使用这样的定义。 (事实上​​,我通常不鼓励使用定义,部分原因是所有这些怪癖。)以 $ 结尾的定义被插入到引用模式中而没有被括号包围(所以$ 可以被视为运算符)。这会导致各种意想不到的行为。例如,如果您写:

NAME  bar|foo$

然后使用它:

x{NAME}y       /* Some action */

最终结果就像你写的一样

xbar|foo"$"y   /* Some action */

(没有括号,但是 $ 是一个普通字符。)

另一方面,如果你这样使用它:

x{NAME}        /* Some action */

这就像你写的一样

xbar|foo$      /* Some action */

其中 $ 是尾随上下文运算符,但由于该运算符的优先级较低,它最终等同于

(xbar|foo)$    /* Some action */

这些扩展中的任何一个都不太可能是您想要的,阅读您的代码的人更不可能期望得到这些结果。