class Grammar is Match {}

使用 grammar 声明的每种类型,并且没有明确声明其超类,都将成为 Grammar 的子类。

grammar Identifier {
    token TOP       { <initial> <rest>* }
    token initial   { <+myletter +[_]> }
    token rest      { <+myletter +mynumber +[_]> }
    token myletter  { <[A..Za..z]> }
    token mynumber  { <[0..9]> }
}
 
say Identifier.isa(Grammar);                # OUTPUT: «True␤» 
my $match = Identifier.parse('W4anD0eR96');
say ~$match;                                # OUTPUT: «W4anD0eR96␤»

更多有关 语法的文档 可用。

方法§

方法 parse§

method parse($target:$rule = 'TOP',  Capture() :$args = \(), Mu :$actions = Mu*%opt)

解析 $target,如果它不是 Str,则将其强制转换为 Str,使用 $rule 作为起始规则。如果提供了其他 $args,则将它们传递给起始规则。

grammar RepeatChar {
    token start($character) { $character+ }
}
 
say RepeatChar.parse('aaaaaa':rule('start'), :args(\('a')));
say RepeatChar.parse('bbbbbb':rule('start'), :args(\('b')));
 
# OUTPUT: 
# 「aaaaaa」 
# 「bbbbbb」

如果提供了名为 actions 的命名参数,则将其用作动作对象,也就是说,对于每个成功的正则表达式匹配,如果存在同名方法,则在动作对象上调用该方法,并将匹配对象作为唯一的定位参数传递。

my $actions = class { method TOP($/{ say "7" } };
grammar { token TOP { a { say "42" } b } }.parse('ab':$actions);
# OUTPUT: «42␤7␤»

其他命名参数用作匹配选项,因此你可以指定诸如 :pos(4) 之类的内容,以从第五个(基于 0)字符开始解析。所有 匹配副词 都被允许,但并非所有副词都会生效。正则表达式有几种类型的副词,其中一些在编译时应用,例如 :s:i。你无法将它们传递给 .parse,因为正则表达式已经编译过了。但是,你可以传递那些影响运行时行为的副词,例如 :pos:continue

say RepeatChar.parse('bbbbbb':rule('start'), :args(\('b')), :pos(4)).Str;
# OUTPUT: «bb␤» 

方法 parse 仅在匹配结束时光标到达目标字符串末尾时才成功。如果你想在中间停止,请使用 方法 subparse

语法中的顶级正则表达式将被允许回溯。

成功时返回 Match,失败时返回 Nil

方法 subparse§

method subparse($target:$rule = 'TOP'Capture() :$args = \(),  Mu :$actions = Mu*%opt)

方法 parse 完全相同,除了光标不必到达字符串末尾才能成功。也就是说,它不必匹配整个字符串。

请注意,与 方法 parse 不同,subparse 始终 返回 Match,如果语法未能匹配,则将是失败的匹配(因此为假)。

grammar RepeatChar {
    token start($character) { $character+ }
}
 
say RepeatChar.subparse('bbbabb':rule('start'), :args(\('b')));
say RepeatChar.parse(   'bbbabb':rule('start'), :args(\('b')));
say RepeatChar.subparse('bbbabb':rule('start'), :args(\('a')));
say RepeatChar.subparse('bbbabb':rule('start'), :args(\('a')), :pos(3));
 
 
# OUTPUT: 
# 「bbb」 
# Nil 
# #<failed match> 
# 「a」

方法 parsefile§

method parsefile(Str(Cool$filename:$enc*%opts)

读取文件 $filename 编码为 $enc,并解析它。所有命名参数都传递给 方法 parse

grammar Identifiers {
    token TOP        { [<identifier><.ws>]+ }
    token identifier { <initial> <rest>* }
    token initial    { <+myletter +[_]> }
    token rest       { <+myletter +mynumber +[_]> }
    token myletter   { <[A..Za..z]> }
    token mynumber   { <[0..9]> }
}
 
say Identifiers.parsefile('users.txt':enc('UTF-8'))
    .Str.trim.subst(/\n/',':g);
 
# users.txt : 
# TimToady 
# lizmat 
# jnthn 
# moritz 
# zoffixznet 
# MasterDuke17 
 
# OUTPUT: «TimToady,lizmat,jnthn,moritz,zoffixznet,MasterDuke17␤»

类型图§

Grammar 的类型关系
raku-type-graph Grammar Grammar Match Match Grammar->Match Mu Mu Any Any Any->Mu Capture Capture Capture->Any Cool Cool Cool->Any Match->Capture Match->Cool

展开上面的图表