【问题标题】:Raku regex: Inconsistent longest token matchingRaku 正则表达式:不一致的最长令牌匹配
【发布时间】:2021-02-01 01:38:09
【问题描述】:

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

为什么它们以不同的方式工作?有没有办法使用变量并且仍然匹配最长的令牌?

【问题讨论】:

    标签: regex raku rakudo regex-alternation


    【解决方案1】:

    这里有两件事在起作用。

    第一个是“最长令牌”的意思。当存在交替时(使用| 或使用proto 正则表达式暗示),提取每个分支的声明性前缀。声明性是指可以通过finite state machine 匹配的Raku 正则表达式语言的子集。声明性前缀是通过采用正则表达式元素来确定的,直到遇到非声明性元素。你可以read more and find some further references in the docs

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

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

    【讨论】:

    • 另外,Raku 的表现力的本质意味着定义一个将完整的正则表达式作为参数的正则表达式标记longest(或shortest)相当容易。 (也就是说,它不一定是优化的,因为至少天真的方法需要完整地跟踪每场比赛),但你 can 的事实非常酷)。另外,在我制作那个模块时,请 brb。
    • 所以 Raku 在 RHS 涉及变量的情况下进行“文本顺序”匹配而不是“最长标记”匹配?对四个正则表达式 /$a {say 1}|$b {say 2}//$a {say 1}||$b {say 2}//$b {say 2}||$a {say 1}//$b {say 2}|$a {say 1}/ 的快速测试表明这是真的。
    • @jubilatious1。我认为这里的关键是乔纳森所说的:The declarative prefix is determined by taking regex elements **until** a non-declarative element is encountered 例如,这两个匹配项因变量的位置而不同:'AAAA' ~~ m/$a A {say 1}|$b AA {say 2}/ 表示 1(不处理任何标记,因此它表现为文本顺序)。而'AAAA' ~~ m/A $a {say 1}|AA $b {say 2}/ 说 2 因为 AAA 标记已被处理,所以它选择第二次更改,更长
    • 如果最长的声明性前缀的长度相等(可能为零)并且如果最长的文字平局也无法解决问题(它不能解决问题),则源顺序被用作平局一个零长度前缀)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 2020-06-20
    • 2020-11-06
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 2012-02-28
    相关资源
    最近更新 更多