在 Perl 中解析逻辑表达式并将其转换为树

发布于 2024-10-09 01:50:04 字数 552 浏览 3 评论 0原文

我有复杂的逻辑表达式,如下所示:

((((!((cond1) || (cond2) || (cond3)) && (cond4))) && (cond5)) <= (((cond6) || (cond7) || (cond8)) || (cond9)))

每行有几十个表达式。允许的逻辑符号是 ||&&!<=<= 表示引导,如 a <= b 表示 b 引导到 a。

我需要仔细检查这些声明并检查条件,因为其中一些不再有效。我希望能够将其解析为一棵树,然后检查每个叶子(其中每个叶子都是一个条件),删除不需要的叶子并重新构建完整且正确的表达式。

我知道树的每个节点都是由一对第一个括号和关闭它的括号定义的,但我不知道如何识别这些对以及如何识别它们之间的逻辑符号。

! 之外的所有符号都位于两个表达式之间。

I have complex logical expression that look like this:

((((!((cond1) || (cond2) || (cond3)) && (cond4))) && (cond5)) <= (((cond6) || (cond7) || (cond8)) || (cond9)))

Each line has several dozens of expressions. The allowed logical signs are ||, &&, ! and <=. <= means leads, as in a <= bmeans that b leads to a.

I need to go over those statements and check the conditions, since some of them are no longer valid. I want to be able to parse it to a tree, then check each of it leafs (where each leaf is a condition), delete the unwanted leafs and build the full and correct expressions back.

I know that each node of the tree is defined by a pair of the first bracket and the bracket that closes it, but I don't know how to identify such pairs and how to identify the logical sign between them.

All signs except for ! come between two expressions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ゞ记忆︶ㄣ 2024-10-16 01:50:04

听起来像是 Parse::RecDescent 的情况:

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

my $text = '((((!((cond1) || (cond2) || (cond3)) && (cond4))) && (cond5)) <= (((cond6) || (cond7) || (cond8)) || (cond9)))';

#$::RD_TRACE=1;

my $grammar = q{

startrule: expr

expr: operand operation(s?)
    { $return = @{$item[2]} ? { 'operations' => $item[2], 'lvalue' => $item[1] } : $item[1] }

operation: /\|\||&&|<=/ operand
    { $return = { 'op' => $item[1], 'rvalue' => $item[2] } }

operand: '(' expr ')'
    { $return = $item[2] }

operand: '!' operand
    { $return = { 'op' => '!', 'value' => $item[2] } }

operand: /\w+/

};

my $parser = Parse::RecDescent->new($grammar);
my $result = $parser->startrule($text) or die "Couldn't parse!\n";

use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
print Dumper $result;

语法,英语:

整体事物是一种表达。表达式是一个操作数,后跟零个或多个二元运算符及其操作数。每个操作数都是带括号的表达式“!”后跟一个操作数或一个单词(例如cond1)。

生成的树中的每个节点都采用以下形式之一:

  • cond1 - 条件
  • { 'op' =>; '!', '值' => '节点' } - !应用于另一个节点
  • { 'lvalue' =>; '节点', '操作' => [ 一项或多项:{ 'op' => 'binop', '右值' => 'node' } ] } - 代表节点 binop 节点 binop 节点的一系列一个或多个操作...

我没有破坏一系列二进制操作(例如 ((cond1) || (cond2) | | (cond3))) 到二叉树中,因为您没有提供有关优先级或关联性的信息。

您的示例的输出是:

$VAR1 = {
  'lvalue' => {
    'lvalue' => {
      'lvalue' => {
        'op' => '!',
        'value' => {
          'lvalue' => 'cond1',
          'operations' => [
            {
              'op' => '||',
              'rvalue' => 'cond2'
            },
            {
              'op' => '||',
              'rvalue' => 'cond3'
            }
          ]
        }
      },
      'operations' => [
        {
          'op' => '&&',
          'rvalue' => 'cond4'
        }
      ]
    },
    'operations' => [
      {
        'op' => '&&',
        'rvalue' => 'cond5'
      }
    ]
  },
  'operations' => [
    {
      'op' => '<=',
      'rvalue' => {
        'lvalue' => {
          'lvalue' => 'cond6',
          'operations' => [
            {
              'op' => '||',
              'rvalue' => 'cond7'
            },
            {
              'op' => '||',
              'rvalue' => 'cond8'
            }
          ]
        },
        'operations' => [
          {
            'op' => '||',
            'rvalue' => 'cond9'
          }
        ]
      }
    }
  ]
};

Sounds like a case for Parse::RecDescent:

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

my $text = '((((!((cond1) || (cond2) || (cond3)) && (cond4))) && (cond5)) <= (((cond6) || (cond7) || (cond8)) || (cond9)))';

#$::RD_TRACE=1;

my $grammar = q{

startrule: expr

expr: operand operation(s?)
    { $return = @{$item[2]} ? { 'operations' => $item[2], 'lvalue' => $item[1] } : $item[1] }

operation: /\|\||&&|<=/ operand
    { $return = { 'op' => $item[1], 'rvalue' => $item[2] } }

operand: '(' expr ')'
    { $return = $item[2] }

operand: '!' operand
    { $return = { 'op' => '!', 'value' => $item[2] } }

operand: /\w+/

};

my $parser = Parse::RecDescent->new($grammar);
my $result = $parser->startrule($text) or die "Couldn't parse!\n";

use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1;
print Dumper $result;

The grammar, in English:

The whole thing is an expression. An expression is an operand followed by zero or more binary operators and their operands. Each operand is either a parenthesized expression, '!' followed by an operand, or a word (e.g. cond1).

Every node in the produced tree is in one of the following forms:

  • cond1 - a condition
  • { 'op' => '!', 'value' => 'node' } - ! applied to another node
  • { 'lvalue' => 'node', 'operations' => [ one or more of: { 'op' => 'binop', 'rvalue' => 'node' } ] } - series of one or more operations representing node binop node binop node ...

I didn't break series of binary operations (e.g. ((cond1) || (cond2) || (cond3))) into a binary tree because you provided no information about precedence or associativity.

Output for your example is:

$VAR1 = {
  'lvalue' => {
    'lvalue' => {
      'lvalue' => {
        'op' => '!',
        'value' => {
          'lvalue' => 'cond1',
          'operations' => [
            {
              'op' => '||',
              'rvalue' => 'cond2'
            },
            {
              'op' => '||',
              'rvalue' => 'cond3'
            }
          ]
        }
      },
      'operations' => [
        {
          'op' => '&&',
          'rvalue' => 'cond4'
        }
      ]
    },
    'operations' => [
      {
        'op' => '&&',
        'rvalue' => 'cond5'
      }
    ]
  },
  'operations' => [
    {
      'op' => '<=',
      'rvalue' => {
        'lvalue' => {
          'lvalue' => 'cond6',
          'operations' => [
            {
              'op' => '||',
              'rvalue' => 'cond7'
            },
            {
              'op' => '||',
              'rvalue' => 'cond8'
            }
          ]
        },
        'operations' => [
          {
            'op' => '||',
            'rvalue' => 'cond9'
          }
        ]
      }
    }
  ]
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文