当前位置: 首页 > 知识库问答 >
问题:

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

梁丘璞瑜
2023-03-14

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

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 ;

我真的只是希望语法从输入中创建一个列表/哈希表树。代码的输出是:

「
    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似乎在解码这样一个事实,即字段描述符由多个字段描述符组成,但实际上似乎并没有将它们放入列表中。我可以说$fds ,但我不能说$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

共有1个答案

魏鸿禧
2023-03-14

我知道你现在都准备好了,但这里有一个答案可以总结一下,供其他人以后阅读。

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

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

(前提是解析成功parse并且表兄弟返回解析树。)

代码的输出。。。看起来还可以。perl6似乎在解码字段描述符由多个字段描述符组成的事实,但实际上似乎并没有将它们放入列表中。我可以说$fds;,但我不能说$fds[0];。为什么前者“起作用”,而后者不起作用?

请参阅我对SO问题“如何访问匹配中的捕获?”的回答。

使用规则而不是令牌会更好吗?

令牌和规则之间的唯一区别是,默认情况下解释令牌/规则中包含的空白。

(标记中的空白被完全忽略。规则中的空白表示“输入中的这一点可能有空白”。)

我真的需要actions类吗[?]

如果您想系统地后处理解析树,则只需要使用操作类。

我不能让perl“自动”填充解析树,而不必指定一类操作吗?

是的。每当您调用parse并且解析成功时,它的返回值就是解析树。

更新:可能的解决方案

让我们完全避开操作,只需将其解析为一棵树:

没错。如果您想要的只是解析树,那么您不需要操作类,也不需要调用makemake

相反,如果您想要另一棵树,例如抽象语法树,那么您可能会发现使用内置的makemake例程很方便。如果您使用makemake,您很可能会发现将它们与单独的操作类结合使用是合适的,而不仅仅是将它们直接嵌入到语法的规则/标记/正则表达式中。

 类似资料:
  • 作为实践,我正在尝试解析一些作为shell命令输出的标准文本。 我想使用Perl6语法,我想在单独的令牌或正则表达式中捕获每个字段。因此,我做了以下语法: 我的想法是,正则表达式找到一个关键字,然后开始收集所有数据,直到下一个关键字。然而,每次我都会得到“池”:- 我不知道当它找到一个关键字时,如何让它停止吃掉字符,然后将其视为另一个关键字。

  • 我在XText中定义了我的DSL,它自动生成了Java版本的语言解析器和代码生成框架,这真的很酷。 问题是我的DSL被使用多种语言的项目所消耗。你可以想象我们可能至少需要用C#、Java和Ruby来解析DSL。 所以问题是:有没有办法在xtext的帮助下为多种语言生成解析器?

  • 我正在尝试使用Perl6语法实现Markdown解析器,但被块引号卡住了。块引号段落不能用嵌套大括号表示,因为它是一个特定格式行的列表。但从语义上讲,它是一个嵌套的标记。 基本上可以归结为以下定义: mdBQLine令牌的实际实现与此无关。唯一需要注意的是,mdBQLineBody键包含实际引用的带有

  • 亲爱的Antlr4社区, 解析似乎很顺利: 但是,我得到以下错误消息: 错误是: [1]交换量子精确和正态分布的定义。但是交换在第一个输入中引入了一个错误: 因为在这种情况下,'6'只被视为一个正态分布,而不是一个全精确值。 [2]尝试为Quanteact(数量的花括号)创建一个上下文,这样lexer只在这个有限的上下文中提供Quanteact符号。但是我没有为此找到ANTLR4原语。 所以似乎什

  • 我正在使用Windows 7和10。我想知道如何在Perl6中创建一个弹出窗口来向用户提供信息?类似Linux的发送通知或Windows Pro msg(没有网络) 非常感谢,-T

  • 我在日语语法方面遇到了很大的麻烦。我有一个小的代币字典的单词,需要与5种类型的文档匹配。一种类型一个字典:例如Job,该人员的字典将包含。我需要读这本字典,为它创造一个JAPE规则。这是我第一次尝试 Phase:JobTitle 输入:查找 选项:control=appelt、debug=true 有没有办法自动创建JAPE规则,只用于在字典中搜索到文档的标记?