问题描述
Raku的正则表达式预期与最长的令牌匹配。
实际上,此行为在以下代码中可见:
c.Close()
但是,当文本位于变量中时,它似乎不能以相同的方式起作用:
raku -e "'AA' ~~ m/A {say 1}|AA {say 2}/"
# 2
为什么它们以不同的方式工作?有没有办法使用变量并且仍然匹配最长的令牌?
解决方法
这里有两件事在起作用。
第一个是“最长令牌”的含义。如果存在交替(使用|
或使用proto
正则表达式隐含),则会提取每个分支的声明性前缀。声明性表示可以由finite state machine匹配的Raku regex语言的子集。声明性前缀是通过使用正则表达式元素确定的,直到遇到非声明性元素为止。您可以read more and find some further references in the docs。
要了解为什么事情会这样,绕一小圈可能会有所帮助。构建解析器的一种常见方法是编写一个令牌解析器,它将输入文本分解为一系列“令牌”,然后是一个解析器,用于从这些令牌中识别更大的(也许是递归的)结构。令牌化通常使用有限状态机执行,因为它能够快速缩减搜索空间。使用Raku语法,我们不会自己编写令牌生成器。取而代之的是,它会自动为我们从语法中提取出来(更准确地说,每个替换点都会计算出标记符)。
第二,Raku regexes是主要Raku语言中的一种嵌套语言,与之一次性解析并同时编译。 (这与大多数语言不同,后者将正则表达式作为我们传递字符串的库提供。)最长的令牌计算在编译时进行。但是,变量是在运行时插值的。因此,正则表达式中的变量插值是非声明性的,因此不被视为最长标记匹配的一部分。