gpt4 book ai didi

regex - 这个 perl6 语法是坏了,还是暴露了一个错误?

转载 作者:行者123 更新时间:2023-12-04 11:47:47 24 4
gpt4 key购买 nike

下面是一个基于更大语法的测试用例——目标是解析 Unity3D Assets 文件中使用的 YAML 子集。有趣的功能是键控数组匹配器。这个匹配器循环,匹配 data[i]: val<array-name(index)><indexer-and-value(index, name)> . <array-name>被重载,所以第一次调用时,它会匹配任何名称。随后的迭代——当索引不为零时——将只匹配看到的相同名称。

问题的关键在于,当 index>0 时,数组应该总是有一个已知的名称,并且应该作为参数传递给匹配器。不是——解释器给出以下错误:

Cannot resolve caller array-name(Match.new(...): 1, Nil, 1); none of these signatures match:
(Prefab $: Int $ where { ... }, $prevName, Int $indent, *%_)
(Prefab $: Int $idx, Match $ (@ (Any $prevName, *@)), Int $indent, *%_)
(Prefab $: Int $idx, @ (Any $prevName, *@), Int $indent, *%_)

所以索引是 1 但之前没有匹配的名称。该参数是 Nil ,这是没有意义的。注意该函数中被注释掉的 block : #{ } .如果未注释,则测试用例将停止失败。没有基于最长匹配的分支( | 运算符或 proto 匹配器),因此在匹配器中添加额外内容不应更改解析。

测试输入包含在测试用例中。这里是:
#use Grammar::Tracer;
#use Grammar::Debugger;

grammar Prefab {
token TOP {
<key> ':' <value=hash-multiline(1)> \n
}

token key { \w+ }

token kvpair(Int $indent=0) {
[
|| <key> ':' <hash-multiline($indent+1)>
|| <keyed-array($indent)>
|| <key> ': ' (\w+)
]
}

token keyed-array(Int $indent) {
# Keys are built in to the list:
# look for arrayname[0] first, then match subsequent lines more strictly, based on name[idx]
:my $idx = 0;
[
<array-name($idx, $<array-name>, $indent)>
<indexer-and-value($idx++, $indent)>
#{ } # XXX this fixes it, somehow
] +% \n

}
multi token array-name(0, $prevName, Int $indent) {
# the first element doesn't need to match indentation
\w+
}

multi token array-name(Int $idx, Match $ ([$prevName, *@]), Int $indent) {
<.indent($indent)>
$prevName
}
# todo: Can I remove this overload? In testing, the parameter was sometimes an array, sometimes a Match
multi token array-name(Int $idx, [$prevName, *@], Int $indent) {
<.indent($indent)>
$prevName
}

# arr[2]: foo
# ^^^^^^^^ match this
token indexer-and-value(Int $idx, Int $indent) {
'[' ~ ']' $idx
[
|| ':' <hash-multiline($indent+1)>
|| ': ' \w+
]
}


token hash-multiline(Int $indent=0) {
# Note: the hash does not need a newline if it's over after the first (inline) kv-pair!
# optional first line which is on the same line as the previous text:
[
|| [<kvpair($indent)>] [ \n <.indent($indent)> <kvpair($indent)> ]*
|| [ \n <.indent($indent)> <kvpair($indent)> ]+
]
}

multi token indent(0) {
^^ <?>
}
multi token indent(Int $level) {
^^ ' ' ** {2*$level}
}
}

sub MAIN() {
say so Prefab.parse($*kv-list);
}

my $*kv-list = q:to/END/;
Renderer:
m_Color[0]: red
END

最佳答案

timotimo 解释了 IRC 上的问题——匹配变量($/$0$1 和命名匹配)不是全局的。当匹配器开始时,匹配变量已经被填充。由于性能问题,它们大多*在匹配器主体的其余部分中根本没有更新。但是,当看到代码块(甚至是空 block )时,匹配变量会更新。所以“bug”解决方法实际上是一个有效的解决方案——包括一个空 block 来强制匹配变量更新。

* $0似乎已更新并立即可用。可能其他编号的比赛也是如此。

更新:似乎唯一没有立即可用的匹配变量是当您在类似代码的上下文中使用它们而不使用 block 时,例如在不同匹配器的参数列表中。在这里,匹配变量在上一次匹配之后立即可用:

my regex word { \w+ };
say 'hellohello' ~~ /<word> $<word>/

但是这个用作参数的例子失败了:
my regex repeated($x) { [$x]+ };
say 'ooxoo' ~~ / ^ <repeated('o')> . <repeated($<repeated>)> $ /

除非您添加一个 block 来强制更新命名匹配变量:
my regex repeated($x) { [$x]+ };
say 'ooxoo' ~~ / ^ <repeated('o')> . {} <repeated($<repeated>)> $ /

关于regex - 这个 perl6 语法是坏了,还是暴露了一个错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46130716/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com