我正在尝试创建一个语法。到目前为止,这是我的代码:
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
我知道你现在都准备好了,但这里有一个答案可以总结一下,供其他人以后阅读。
如何使用perl6语法创建解析树?
它非常简单:只需使用调用内置解析例程之一的返回值。
(前提是解析成功parse
并且表兄弟返回解析树。)
代码的输出。。。看起来还可以。perl6似乎在解码字段描述符由多个字段描述符组成的事实,但实际上似乎并没有将它们放入列表中。我可以说$fds;,但我不能说$fds[0];。为什么前者“起作用”,而后者不起作用?
请参阅我对SO问题“如何访问匹配中的捕获?”的回答。
使用规则而不是令牌会更好吗?
令牌和规则之间的唯一区别是,默认情况下解释令牌/规则中包含的空白。
(标记中的空白被完全忽略。规则中的空白表示“输入中的这一点可能有空白”。)
我真的需要actions类吗[?]
不
如果您想系统地后处理解析树,则只需要使用操作类。
我不能让perl“自动”填充解析树,而不必指定一类操作吗?
是的。每当您调用parse
并且解析成功时,它的返回值就是解析树。
更新:可能的解决方案
让我们完全避开操作,只需将其解析为一棵树:
没错。如果您想要的只是解析树,那么您不需要操作类,也不需要调用make
或make
。
相反,如果您想要另一棵树,例如抽象语法树,那么您可能会发现使用内置的make
和make
例程很方便。如果您使用make
和make
,您很可能会发现将它们与单独的操作类结合使用是合适的,而不仅仅是将它们直接嵌入到语法的规则/标记/正则表达式中。
作为实践,我正在尝试解析一些作为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规则,只用于在字典中搜索到文档的标记?