我正在尝试编写一个令牌,允许带有匹配分隔符的嵌套内容。如果不是“(AB)”,其中(AB)应该导致至少匹配“AB”。并且(A(c)B)将返回两个匹配项“(A(c)B)”等等。
代码从其来源归结为:
#!/home/hsmyers/rakudo741/bin/perl6
use v6d;
my @tie;
class add-in {
method tie($/) { @tie.push: $/; }
}
grammar tied {
rule TOP { <line>* }
token line {
<.ws>?
[
| <tie>
| <simpleNotes>
]+
<.ws>?
}
token tie {
[
|| <.ws>? <simpleNotes>+ <tie>* <simpleNotes>* <.ws>?
|| <openParen> ~ <closeParen> <tie>
]+
}
token openParen { '(' }
token closeParen { ')' }
token simpleNotes {
[
| <[A..Ga..g,'>0..9]>
| <[|\]]>
| <blank>
]
}
}
my $text = "(c2D) | (aA) (A2 | B)>G A>F G>E (A,2 |\nD)>F A>c d>f |]";
tied.parse($text, actions => add-in.new).say;
$text.say;
for (@tie) {
s:g/\v/\\n/;
say "«$_»";
}
这给出了部分正确的结果:
«c2D»
«aA»
«(aA)»
«A2 | B»
«\nD»
«A,2 |\nD»
«(A,2 |\nD)>F A>c d>f |]»
«(c2D) | (aA) (A2 | B)>G A>F G>E (A,2 |\nD)>F A>c d>f |]»
BTW,我不关心换行符,它只是检查这种方法是否可以跨越两行文本。所以搅拌我看到的灰烬会捕获带括号和不带括号的内容,以及一两个非常贪婪的捕获。
很明显,我的代码中有一个问题。我对perl6的了解最好被描述为“初学者”,所以我请求你的帮助。我正在寻找一个通用的解决方案,或者至少是一个可以概括的例子,一如既往地欢迎建议和更正。
您还有一些额外的复杂性。例如,您将领带
定义为(…)
或只是…
。但是内部内容与该行相同。
这里有一个重写的语法,大大简化了你想要的东西。编写语法时,从小处着手,往上走是有帮助的。
grammar Tied {
rule TOP { <notes>+ %% \v+ }
token notes {
[
| <tie>
| <simple-note>
] +
%%
<.ws>?
}
token open-tie { '(' }
token close-tie { ')' }
token tie { <.open-tie> ~ <.close-tie> <notes> }
token simple-note { <[A..Ga..g,'>0..9|\]]> }
}
这里有一些文体上的注释。语法是类,通常将它们大写。标记是方法,带有kebap大小写(不过,您当然可以使用任何您想要的类型)。在tie
标记中,您会注意到我使用了
现在,我创建代币的顺序是这样的:
动作(通常与你的语法同名,加上-Action
,所以这里我使用类Teded-Actions{
TOP
中得到什么?中找到的所有联系
解析时,您需要做的就是获取Match
的. make
:
say Tied.parse("a(b(c))d");
# 「a(b(c))d」
# notes => 「a(b(c))d」
# simple-note => 「a」
# tie => 「(b(c))」 <-- there's a tie!
# notes => 「b(c)」
# simple-note => 「b」
# tie => 「(c)」 <-- there's another!
# notes => 「c」
# simple-note => 「c」
# simple-note => 「d」
say Tied.parse("a(b(c))d", actions => TiedActions).made;
# [b(c) c]
现在,如果你真的只需要领带
class Tied-Actions {
has @!ties;
method TOP ($/) { make @!ties }
method tie ($/) { @!ties.push: ~$<notes> }
}
与之前相比,这有几个缺点:虽然它可以工作,但它的可扩展性不是很好。虽然你会得到每一个平局,但你对它的上下文一无所知。此外,你必须实例化Ted-Action(即action=