我有这个 raku 语法:
#!/usr/bin/env raku
use v6.d;
use Grammar::Tracer;
grammar Grammar {
token TOP {
<city> \v
<state-zip> \v?
}
token city {
^^ \V* $$
}
token state-zip {
^^ <state> <.ws>? <zipcode> $$ #<.ws> is [\h* | \v]
}
token state {
\w \w
}
token zipcode {
\d ** 5
}
}
class Actions {
method TOP($/) {
#works
say "city is ", $_ with $<city>.made;
say "state is ", $_ with $<state-zip><state>.made;
say "zipcode is ", $_ with $<state-zip><zipcode>.made;
#doesn't work
say "state2 is ", $_ with $<state>.made;
say "zipcode2 is ", $_ with $<zipcode>.made;
}
method city($/) { make ~$/ }
method state($/) { make ~$/ }
method zipcode($/) { make ~$/ }
}
my $address = q:to/END/;
Springfield,
IL 62704
END
Grammar.parse($address, :actions(Actions));
效果很好:
TOP
| city
| * MATCH "Springfield,"
| state-zip
| | state
| | * MATCH "IL"
| | zipcode
| | * MATCH "62704"
| * MATCH "IL 62704"
city is Springfield,
state is IL
zipcode is 62704
* MATCH "Springfield,\nIL 62704\n"
token <state-zip>
是让状态和邮政编码共存于一行还是跨越多行。请记住,这是一个 MRE,因此我正在寻找不会改变语法的答案,但会改变操作的 make / made 方面。
但是 - 为了简化我的代码,我希望能够从method TOP($/) {}
我的示例 state2 和 zipcode2 的操作中访问顶层的州和邮政编码。我一直在尝试将状态和令牌的制作值“提升”到匹配树上 - 例如可能是这样的:
# doesn't work
method TOP($/) {
make $<state>.made;
make $<zip>.made;
...
}
method state-zip($/) {
make $<state>.made;
make $<zip>.made;
}
这可能吗?
TL;DR您无法修改
Match
对象的捕获。我认为您可以做三件事: Ⓐ 修改匹配对象的.made
属性和/或 Ⓑ 修改$/
以使用其快捷方式和/或 Ⓒ 清理它?您无法修改
Match
对象的捕获你问的问题是很自然的事情。我记得我自己也想要它。
在我对如何在语法中改变捕获?),我暗示你不能改变
Match
对象的捕获。目前在乐(do)也是如此。但我现在想知道是否可以做点什么。我将在本答案的最后一部分中回到这一点。修改匹配对象的
.made
属性我现在建议您使用匹配对象的
.made
属性,method TOP
如下所示。保留原来的代码:
插入代码来创建字典,然后
make
:保留原始代码,但从匹配对象中提取
.made
:修改
$/
为使用其快捷键注意。本节是关于修改(分配/绑定)符号(变量)
$/
,以便它引用不同的对象/值。它不是关于修改已分配或绑定到的对象/值$/
。以下是上面第一部分中的代码与一些调整的组合。这样您的代码仍然可以使用
$/
常用的快捷方式。添加一个
is copy
特征,以便$/
可以重新分配参数:保持其余代码相同,直到出现以下行
make
:$/
插入对其有效负载的重新分配(或绑定).made
:现在您的代码可以切换回常用的快捷方式:
注意。当您重新分配/绑定时,
$/
您将覆盖原始绑定到原始匹配对象。所以这停止工作:在本答案的最后一部分中,我概述了该问题的可能解决方案。
清理?
也许
Match
可以为对象提供新方法,允许用户将别名添加到匹配对象中的现有捕获到其他匹配对象(前提是它们是基于相同的输入字符串构造的)?一个更黑客的想法是创建一个新类,它就像一个空的可变类
Hash
(因此可以向其中添加键),但使用Match
绑定到委托属性(has Match $original handles **;
)的现有对象进行初始化。后者将通过故障转移来对现有对象进行查找来处理无法匹配哈希中的键的任何查找Match
。(我不太确定这是否是正确的handles
表达,但想发布此更新,以便我可以去睡觉。)脚注
¹任何数据都可以分配或绑定到
$/
,而不仅仅是Match
对象。总是会出现$0
别名为 to$/[0]
、$1
to$/[1]
、$<foo>
to$/<foo>
和$<bar>
to等的情况$/<bar>
,无论分配或绑定了什么内容$/
。事实上,多年来我一直在使用$/
我脑海中所说的“数据变量”,它是“数据(解)结构”变量的缩写,这样“当前匹配对象”只是“数据变量”之一”的用途很多。你原来的代码:
创建字典的附加代码,然后
make
:您的原始代码,但从匹配对象中绘制
.made
: