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)))';
Grammar in English:
All this expression. An expression is an operand followed by zero or more binary operators and their operands. Each operand is an expression in parentheses, '!' followed by an operand or word (e.g. cond1 ).
Each node in the created tree is in one of the following forms:
cond1 - condition{ 'op' => '!', 'value' => 'node' } -! applies to another node{ 'lvalue' => 'node', 'operations' => [ one or more of: { 'op' => 'binop', 'rvalue' => 'node' } ] } - a series of one or more operations, representing node binop node binop node ...
I did not break a number of binary operations (for example, ((cond1) || (cond2) || (cond3)) ) into a binary tree because you did not provide any information about priority or associativity.
The output for your example:
$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' } ] } } ] };
ysth
source share