我想使用Perl解析类似于Gmail提供的搜索字符串。一个示例输入是“tag:thing by:{user1 user2} {-tag:a by:user3}”。我想将它放入树结构中,例如
{and => [
"tag:thing",
{or => [
"by:user1",
"by:user2",
]},
{or => [
{not => "tag:a"},
"by:user3",
]},
}
一般规则是:
这些元素也可以组合和嵌套:例如“{by:user5 - {tag:k by:user3}} etc”。
我正在考虑编写一个无上下文语法来表示这些规则,然后将其解析为树。这不必要吗? (这是否可以使用简单的正则表达式?)
建议使用哪些模块来解析无上下文语法?
(最终这将用于使用DBIx :: Class生成数据库查询。)
答案 0 :(得分:1)
正则表达式不会很好地嵌套事物(如括号)。当你获得正则表达式计数括号并正确捕获时,你可能有一个不错的CFG解析器。 CFG可以在逻辑上保证正确的解析,而使用正则表达式解决方案,你可以留下很多魔力。我不能推荐任何Perl CFG库,但是编写一个听起来非常流行。
答案 1 :(得分:0)
如果您的查询不是树形结构,那么正则表达式将为您完成工作。
例如:
my $search = "tag:thing by:{user1 user2} {-tag:a by:user3}"
my @tokens = split /(?![^{]*})\s+/, $search;
foreach (@tokens) {
my $or = s/[{}]//g; # OR mode
my ($default_field_specifier) = /(\w+):/;
}
即使您的查询是树结构化,正则表达式也可以使递归解析更加愉快:
$_ = "by:{user1 z:{user2 3} } x {-tag:a by:user3} zz";
pos($_) = 0;
scan_query("");
sub scan_query {
my $default_specifier = shift;
while (/\G\s*((?:[-\w:]+)|(?={))({)?/gc) {
scan_query($1), next if $2;
my $query_token = $default_specifier . $1;
}
/\G\s*\}/gc;
}
正则表达非常棒:)!
答案 2 :(得分:0)
YAPP可能会做你想要的。您可以使用它来生成然后使用LALR(1)Parsing Automaton。
答案 3 :(得分:0)
Parse::Recdescent可以为这种事情生成解析器。您可能需要一些解析器的经验才能有效地使用它。