+ -
当前位置:首页 → 问答吧 → 用PERL如何实现括号的正确匹配,相当于数学中的小括号,请多发表意见!!!

用PERL如何实现括号的正确匹配,相当于数学中的小括号,请多发表意见!!!

时间:2010-10-23

来源:互联网

本帖最后由 minirain 于 2010-10-23 22:46 编辑

如式子:
表达式1、{{名称为括号A ...}}......字符串{{......}};
             A                      A                 B      B
表达式2、{{...... .......{{...........}}...........}}
              A               B             B           A
其中A、B为正确匹配的括号名称,......为字符串,一段文字有很多表达示1和表达式2组成,用Perl 正则表达式如何实现括号({{)与回括号(}})AA、BB正确匹配呢?
如表达式1、用$kk =~ s/\{\{  ([^\}]+) \}\}/&Fuction($1)/gxe;  适合表达式1的情况但不适合表达式2的情况;
表达式2、用$kk =~ s/\{\{ (.*) \}\}/&Fuction($1)/gxe;  适合表达式2的情况但不适合表达式1的正确匹配;

与数学优先级高的小括号计算式表达式一样:
1、(2+3)×(4-8)
2、5×(3+8×(3+4))
不知道计算机或者计算器是如何正确匹配计算式小括号配对的???
请大家多给建议或意见!
谢谢大家了!
minirain
20101023

作者: minirain   发布时间: 2010-10-23

再复杂也不过是个树,像lisp那样

作者: zhlong8   发布时间: 2010-10-23



QUOTE:
再复杂也不过是个树,像lisp那样
zhlong8 发表于 2010-10-23 22:45




    请问如何实现呢?谢谢!

作者: minirain   发布时间: 2010-10-23

以前实现 scheme 的 read 的时候写个类似的。[current, parent] 这样的结构,遇到 '(' 就新加一层变成
[new_current, [current, parent]],遇到 ')' 就消除一层……还要再具体吗

作者: zhlong8   发布时间: 2010-10-23



QUOTE:
以前实现 scheme 的 read 的时候写个类似的。[current, parent] 这样的结构,遇到 '(' 就新加一层变成
[ne ...
zhlong8 发表于 2010-10-23 22:53




    能给个用PERL程序实现的例子,可以吗?

作者: minirain   发布时间: 2010-10-23

本帖最后由 zhlong8 于 2010-10-23 23:57 编辑

package T
  1. package T;

  2. use 5.012;
  3. use warnings;

  4. sub new {
  5.     my($class, $parent) = @_;
  6.     bless {
  7.         current => [],
  8.         parent => $parent
  9.     }, $class;
  10. }

  11. sub dec {
  12.     my $self = shift;
  13.     push @{$self->{parent}{current}}, $self->{current};
  14.     $self->{parent};
  15. }

  16. sub add {
  17.     my($self, $val) = @_;
  18.     push @{$self->{current}}, $val;
  19. }

  20. sub top {
  21.     bless {current => [], parent=> []}, shift;
  22. }

  23. 1;
复制代码
实现
  1. use 5.012;
  2. use strict;
  3. use warnings;
  4. use T;
  5. use Data::Dumper;
  6. use Regexp::Common;

  7. sub parse {
  8.     my $tree = T->top;
  9.     for (@_) {
  10.         given ($_) {
  11.             when ('(') {$tree = T->new($tree)}
  12.             when (')') {$tree = $tree->dec;}
  13.             default {$tree->add($_);}
  14.         }
  15.     }
  16.     say Dumper $tree;
  17. }

  18. sub tokenize {  #功能非常有限
  19.     my $str = shift;
  20.     say "got $str";
  21.     my @all;
  22.     while ($str =~ /\G\s*(\(|\)|$RE{num}{int}|$RE{num}{real}|\w+|[+\-*\/])\s*/g) {
  23.         push @all, $1;
  24.     }
  25.     say "return @all";
  26.     @all;
  27. }

  28. #(define a (+ 343 (* 3323 a)))
  29. parse '(', 'define', 'a', '(', '+', '343', '(', '*', '3323', 'a', ')', ')', ')';
  30. #或者
  31. parse tokenize '(define a (+ 343 (* 3323 a)))'
复制代码
输出
  1. $VAR1 = bless( {
  2.                  'parent' => [],
  3.                  'current' => [
  4.                                 [
  5.                                   'define',
  6.                                   'a',
  7.                                   [
  8.                                     '+',
  9.                                     '343',
  10.                                     [
  11.                                       '*',
  12.                                       '3323',
  13.                                       'a'
  14.                                     ]
  15.                                   ]
  16.                                 ]
  17.                               ]
  18.                }, 'T' );
复制代码
有个Parse::RecDescent 模块,不过我不会用
还有 Regexp::Common::balanced

作者: zhlong8   发布时间: 2010-10-23

回复 minirain


    这个,单纯只用正则确实不容易啊,如果用堆栈的方式,可能会容易一些

作者: 珞水的大叔   发布时间: 2010-10-23

回复 珞水的大叔


    发现大叔太NB了,8月18到10月23总共65天在线855小时。
855/(65*24) = 54.81%

作者: zhlong8   发布时间: 2010-10-23

回复 zhlong8


    嘿嘿嘿嘿……

作者: 珞水的大叔   发布时间: 2010-10-23