使用Parse :: RecDescent解析带有嵌套括号的字符串 [英] Parsing string with nested parentheses using Parse::RecDescent

查看:124
本文介绍了使用Parse :: RecDescent解析带有嵌套括号的字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 Parse::RecDescent 生成可以解析括号的解析器表达式和一元运算符?.

到目前为止,我创建解析器时失败了,因为规则expression是左递归的:

What I have so far is failing when I create the parser because the rule expression is left-recursive:

use strict;
use warnings;
use Parse::RecDescent;

my $test = <<END;
((foo)? bar)
END

my $grammar = q(
    parse: expression(s)
    expression: string | parend | expression(s)
    parend : "(" (string | expression) ")" /\??/
    string : /\w+/ /\??/

);
my $parser = Parse::RecDescent->new($grammar);
my $result = $parser->parse($test);
if($result){
    print $result;
}else{
    print STDERR "Invalid grammar\n";
}

推荐答案

首先,您从最低优先级转到最高优先级.

First, you go from lowest priority to highest priority.

parse  : expr /\Z/

expr   : list

list   : unary(s?)

unary  : unary '?'
       | term

term   : '(' expr ')'
       | STRING

STRING : /\w+/

当然

unary  : unary '?'
       | term

无效,因为它是左递归的. 操作员关联性和在Parse :: RecDescent中消除左递归可以帮助您摆脱它.我们得到

doesn't work because it's left-recursive. Operator Associativity and Eliminating Left-Recursion in Parse::RecDescent can help you get rid of it. We get

unary  : term unary_(s?)
unary_ : '?'

但这不会为我们构建正确的树.因此,让我们首先弄平"(s?)".

But that's not going to construct the right tree for us. So let's start by flattinging out the "(s?)".

unary  : term unary_
unary_ : '?' unary_
       |

然后,我们可以使用子规则args创建正确的树.

Then we can use subrule args to create the right tree.

unary  : term unary_[ $item[1] ]
unary_ : '?' unary_[ [ 'postfix?' => $arg[0] ] ]
       | { $arg[0] }


一起:


All together:

use strict;
use warnings;
use Data::Dumper      qw( Dumper );
use Parse::RecDescent qw( );

my $grammar = <<'END';
   {
      use strict;
      use warnings;
   }

   parse  : expr /\Z/ { $item[1] }

   expr   : list

   list   : unary(s?) { [ $item[0] => @{ $item[1] } ] }

   unary  : term unary_[ $item[1] ]
   unary_ : '?' unary_[ [ 'postfix?' => $arg[0] ] ]
          | { $arg[0] }

   term   : '(' expr ')' { $item[2] }
          | STRING { [ string => $item[1] ] }

   STRING : /\w+/

END

my $parser = Parse::RecDescent->new($grammar)
   or die "Invalid grammar\n";
my $tree = $parser->parse("((foo bar)? baz)\n")
   or die "Invalid text\n";
print(Dumper($tree));

这篇关于使用Parse :: RecDescent解析带有嵌套括号的字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆