我正在尝试创建一个语法。这是我的代码到目前为止:如何用perl6语法创建一个分析树?
use Text::Table::Simple; # zef install Text::Table::Simple
my $desc = q:to"FIN";
record person
name string;
age int;
end-record
FIN
grammar rec {
token TOP { <ws>* 'record' \s+ <rec-name> <field-descriptors> <ws> 'end-record' <ws> }
token rec-name { \S+ }
token field-descriptors { <field-descriptor>* }
token field-descriptor { <ws>* <field-name> <ws>+ <field-type> <ws>* ';' }
token field-name { \S+ }
token field-type { <[a..z]>+ }
token ws { <[\r\n\t\ ]> }
}
class recActions {
method field-descriptors($/) { $/.make: $/; }
method field-descriptor($/) { $/.make: $/; }
method field-name($/) { $/.make: $/ }
method field-type($/) { $/.make: $/ }
}
my $r = rec.parse($desc, :actions(recActions));
#say $r;
my $inp = q:to"FIN";
adam 26
joe 23
mark 51
FIN
sub splitter($line) {
my @lst = split /\s+/, $line;
}
sub matrixify(&splitter, $data)
{
my @d = (split /\n/, (trim-trailing $data)).map(-> $x { splitter $x ; });
#@d.say;
#my @cols = <name age>;
#say lol2table(@cols, @d).join("\n");
@d;
}
#my @cols =<A B>;
#my @rows = ([1,2], [3,4]);
#say lol2table(@cols, @rows).join("\n");
my @m = matrixify &splitter, $inp;
sub tabulate($rec-desc, @matrix)
{
my $fds = $rec-desc<field-descriptors>;
#say %fds<field-name>;
say $fds;
my @cols = $rec-desc.<field-descriptors>.map(-> $fd { say $fd; $fd.<field-name> ; 1;});
#say $rec-desc.<field-descriptors>;
#say @cols;
}
tabulate $r, @m ;
我真的只是想让语法从输入创建一个列表/散列表的树。从代码的输出是:
这看起来相当不错。 perl6似乎解码了这样的事实,即field-descriptors
由多个field-descriptor
组成,但实际上它似乎并未将它们放入列表中。我可以做say $fds;
,但我不能做say $fds[0];
。为什么前者“工作”,但后者却不行?
我必须承认对发生的事情掌握得相当薄弱。我会更好地使用规则而不是令牌吗?我真的需要一个动作类吗?我不能只是让perl自动为我填充分析树,而不必指定一类操作?
更新:可能的解决方案
假设我们只想解析:
my $desc = q:to"FIN";
record person
name string;
age int;
end-record
FIN
和字段名和类型,我们发现报告。我打算做一个小的简化到我上面写的语法:
grammar rec {
token TOP { <ws>* 'record' \s+ <rec-name> <field-descriptor>+ <ws> 'end-record' <ws> }
token rec-name { \S+ }
token field-descriptor { <ws>* <field-name> <ws>+ <field-type> <ws>* ';' }
token field-name { \S+ }
token field-type { <[a..z]>+ }
token ws { <[\r\n\t\ ]> }
}
让我们完全回避动作,只是解析成一棵树:
my $r1 = rec.parse($desc);
现在让我们来检查我们的手艺,和打印出来的名称和类型的,我们已经解析了每个字段:
for $r1<field-descriptor> -> $fd { say "Name: $fd<field-name>, Type: $fd<field-type>"; }
我们的产量是因为我们预计:
Name: name, Type: string
Name: age, Type: int
我注意到,下面的工作,虽然:'$ fds [0]'所以我想我必须越来越近。 –
blippy
http://stackoverflow.com/a/40799024/1077672有帮助吗? – raiph
'$ /。make:$ /'实际上是一个无操作。你还需要对'.parse'的结果调用'.made'或'.ast'来获取操作类的结果。 –