Raku 正则表达式:最长令​​牌匹配不一致

Raku regex: Inconsistent longest token matching

Raku 的正则表达式应匹配最长的标记。

事实上,在这段代码中可以看到这种行为:

raku -e "'AA' ~~ m/A {say 1}|AA {say 2}/"
# 2

但是,当文本在变量中时,它似乎不会以相同的方式工作:

raku -e "my $a = 'A'; my $b = 'AA'; 'AA' ~~ m/$a {say 1}|$b {say 2}/"
# 1

为什么他们的工作方式不同?有没有一种方法可以使用变量并仍然匹配最长的标记?

这里有两件事在起作用。

首先是“最长令牌”的含义。当有交替时(使用 | 或使用 proto 正则表达式暗示),每个分支的 声明前缀 被提取。声明性表示 Raku 正则表达式语言的子集,可以通过 finite state machine. The declarative prefix is determined by taking regex elements until a non-declarative element is encountered. You can read more and find some further references in the docs.

匹配

要理解为什么会这样,稍微绕一下可能会有所帮助。构建解析器的一种常见方法是编写分词器,它将输入文本分解为一系列“标记”,然后是从这些标记中识别更大(可能是递归的)结构的解析器。标记化通常使用有限状态机执行,因为它能够快速减少搜索 space。使用 Raku 语法,我们不自己编写分词器;相反,它会自动从语法中为我们提取(更准确地说,每个交替点都会计算一个分词器)。

其次,Raku 正则表达式是主要 Raku 语言中的一种嵌套语言,用它一次性解析并同时编译。 (这与大多数语言不同,在大多数语言中,正则表达式作为我们将字符串传递给的库提供。)最长的标记计算发生在编译时。但是,变量是在运行时插入的。因此,正则表达式中的变量插值是 non-declarative,因此不被视为最长标记匹配的一部分。