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

时间:2016-09-30 20:34:30

标签: flex-lexer

在Flex中,我可以在名称定义中使用a trailing模式,如下所示:

NAME  foo$|bar

这会传递flex。

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

NAME  (?x: foo$ | bar )

但是现在这会导致flex失败,因为根据手册"‘$’, cannot be grouped inside parentheses"

恕我直言,这是愚蠢的,允许一些构造,但不允许可读地描述它。

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

1 个答案:

答案 0 :(得分:2)

首先,回答你的问题:“如何在Flex中使用具有可读模式的尾随上下文?”。如果您坚持认为模式只有洒满空格才能读取,那么答案就是 “你不能。” 抱歉,但就是这样。 (?x:标志在某个时刻被侵入弯曲,并且仍有很多粗糙的边缘。

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

NAME (?x: foo | bar )$

以下是一些注释。

  

在Flex中,我可以在名称定义中使用a trailing模式,如下所示:

NAME  foo$|bar
不,你不能。或者,更好地说,你可以写,但它不涉及尾随上下文,因为:

  

...在规则末尾没有出现的'$'会丢失其特殊属性,并被视为普通字符。

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

flex会拒绝:

这是真的(并且有点好奇)
NAME  (?x: foo$ | bar )

虽然它会接受:

NAME  (?x: foo$| bar )

我会站出来说这是一个错误。仅当 $ 位于模式的末尾时,它才被识别为尾随上下文运算符。但是,检查它的代码只是检查下一个字符是否是空格,因为模式终止于第一个空白字符。 (该模式未在定义中解析;当它实际包含在某些规则模式中时会对其进行解析。)测试不会检查 $ 是否在(?x:块内,所以在

(?x: foo$ | bar )

$ 是一个尾随上下文运算符,这是一个语法错误(运算符必须出现在模式的最后),而在

(?x: foo$| bar )

$ 只是一个普通的角色,这是合法的,但也许是意外的。

最后,请注意:以下内容完全合法, $ 将被视为尾随上下文运算符,前提是该定义在模式的最后使用< / EM>:

NAME  bar|foo$

然而,它可能并不意味着你认为它意味着什么。尾随上下文运算符的优先级低于交替运算符,因此只要扩展位于模式的末尾,就会将其解析为已写入

NAME  (bar|foo)$

我强烈建议不要使用这样的定义。 (事实上​​,我通常不鼓励使用定义,部分原因是因为所有这些怪癖。)以 $ 结尾的定义被插入到引用模式中而不被括号括起来(以便< kbd> $ 可以视为运营商)。这会导致各种意外行为。例如,如果你写:

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 */

这些扩展不太可能是您想要的,而且阅读代码的任何人都不太可能期望这些结果。