我如何使用 perl6 语法创建一个解析树?

How do I just create a parse tree with perl6 grammar?

我正在尝试创建语法。到目前为止,这是我的代码:

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 ;

我真的只是想让语法根据输入创建一个 lists/hash 表树。代码的输出是:

「
    name string;
    age  int;」
 field-descriptor => 「
    name string;」
  ws => 「
」
  ws => 「   」
  field-name => 「name」
  ws => 「 」
  field-type => 「string」
 field-descriptor => 「
    age  int;」
  ws => 「
」
  ws => 「   」
  field-name => 「age」
  ws => 「 」
  ws => 「 」
  field-type => 「int」

看起来还不错。 perl6 似乎正在解码 field-descriptors 由多个 field-descriptor 组成的事实,但它实际上似乎并没有将它们放入列表中。我可以say $fds;,但我做不到say $fds[0];。为什么前者"work",而后者没有?

我必须承认我对正在发生的事情的了解相当薄弱。我会更好地使用规则而不是令牌吗?我真的需要一个动作吗 class;我不能让 perl "automagically" 为我填充解析树而不必指定 class 操作吗?

更新:可能的解决方案

假设我们只想解析:

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

我知道你现在已经准备好了,但这里有一个总结,供其他人稍后阅读。

How do I just create a parse tree with perl6 grammar?

它非常简单:只需使用调用内置解析例程之一的 return 值。

(前提是解析成功parse和表亲return一个parse tree。)

The output from the code ... looks fairly good. perl6 seems to be decoding the fact that field-descriptors is composed of multiple field-descriptor, but it doesn't actually seem to put them into a list. I can do say $fds;, but I can't do say $fds[0];. Why does the former "work", but the latter doesn't?

查看我对 SO 问题的回答

Would I be better of using rules instead of tokens?

令牌和规则之间的唯一区别是默认解释您包含在 token/rule 中的空白。

(token 中的空白完全被忽略。rule 中的空白表示“在这一点上可以有空白输入"。)

Do I really need an actions class[?]

没有

如果你想系统地post处理解析树,只需要操作class。

can't I just get perl to "automagically" populate the parse tree for me without having to specify a class of actions?

是的。任何时候你调用 parse 并且解析成功它的 return 值是一个解析树。

Update: possible solution

Let's eschew actions completely, and just parse it into a tree:

没错。如果您只需要解析树,那么您不需要操作 class 也不需要调用 makemade.

相反,如果您想要另一棵树,例如 Abstract Syntax Tree,那么您可能会发现使用内置的 makemade 例程很方便。如果您使用 makemade,您可能会发现将它们与单独的操作 class 结合使用是合适的,而不是直接将它们嵌入语法的 rules/tokens/regexes 中。