Я использую Perl для запуска через дерево, а затем вычисляют листовые узлы дерева, используя внутренние узлы в качестве операторов. Я хочу, чтобы иметь возможность печатать это в postfix-манере, и мне это удалось довольно легко с основными операндами (просто вызовите левый и правый узлы соответственно перед вызовом родителя), но у меня возникают проблемы с созданием желаемого результата для средняя функция. У меня нет проблем с печатью фактического результата вычисления, но я хочу иметь возможность печатать операторы и операнды в постфиксной нотации.Попытка разработки PostFix нотации в дереве с использованием Perl
Например, 1 + средний (3, 4, 5) будет отображаться как 1; 3 4 5 средний +.
Вот мой код:
use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Indent = 0;
$Data::Dumper::Terse = 1;
my $debug = 0;
# an arithmetic expression tree is a reference to a list, which can
# be of two kinds as follows:
# [ 'leaf', value ]
# [ 'internal', operation, leftarg, rightarg ]
# Evaluate($ex) takes an arithmetic expression tree and returns its
# evaluated value.
sub Evaluate {
my ($ex) = @_;
$debug and
print "evaluating: ", Dumper($ex), "\n";
# the kind of node is given in the first element of the array
my $node_type = $ex->[0];
# if a leaf, then the value is a number
if ($node_type eq 'leaf') {
# base case
my $value = $ex->[1];
$debug and
print "returning leaf: $value\n";
return $value;
}
# if not a leaf, then is internal,
if ($node_type ne 'internal') {
die "Eval: Strange node type '$node_type' when evaluating tree";
}
# should now have an operation and two arguments
my $operation = $ex->[1];
my $left_ex = $ex->[2];
my $right_ex = $ex->[3];
# evaluate the left and right arguments;
my $left_value = Evaluate($left_ex);
my $right_value = Evaluate($right_ex);
# if any arguments are undefined, our value is undefined.
return undef unless
defined($left_value) and defined($right_value);
my $result;
# or do it explicitly for the required operators ...
if ($operation eq 'average') {
$result = ($left_value + $right_value)/2;
}
if ($operation eq '+') {
$result = $left_value + $right_value;
} elsif ($operation eq '-') {
$result = $left_value - $right_value;
} elsif ($operation eq '*') {
$result = $left_value * $right_value;
} elsif ($operation eq 'div') {
if ($right_value != 0) {
$result = int ($left_value/$right_value);
} else {
$result = undef;
}
} elsif ($operation eq 'mod') {
$result = $left_value % $right_value;
} elsif ($operation eq '/') {
if ($right_value != 0) {
$result = $left_value/$right_value;
}
else {
$result = undef;
}
}
$debug and
print "returning '$operation' on $left_value and $right_value result: $result\n";
return $result;
}
# Display($ex, $style) takes an arithmetic expression tree and a style
# parameter ('infix' or 'postfix') and returns a string that represents
# printable form of the expression in the given style.
sub Display {
my ($ex, $style) = @_;
# the kind of node is given in the first element of the array
my $node_type = $ex->[0];
# if a leaf, then the value is a number
if ($node_type eq 'leaf') {
# base case
my $value = $ex->[1];
return $value;
}
# if not a leaf, then is internal,
if ($node_type ne 'internal') {
die "Display: Strange node type '$node_type' when evaluating tree";
}
# should now have an operation and two arguments
my $operation = $ex->[1];
my $left_ex = $ex->[2];
my $right_ex = $ex->[3];
# evaluate the left and right arguments;
my $left_value = Display($left_ex, $style);
my $right_value = Display($right_ex, $style);
my $result;
if ($operation ne 'average') {
$result = "($left_value $operation $right_value) \n $left_value $right_value $operation";
} else {
$result = "($left_value $operation $right_value) \n $left_value $right_value $operation";
}
return $result;
}
# module end;
1;
А вот тест:
use strict;
use warnings;
use Display;
use arith;
my $ex1 = [ 'leaf', 42];
my $ex2 = [ 'internal', '+', [ 'leaf', 42], [ 'leaf', 10 ] ];
my $ex3 = [ 'internal', 'average', $ex2, [ 'leaf', 1 ] ];
print "ex1 is ", Evaluate($ex1), "\n";
print "ex1: ", Display($ex1), "\n";
print "\n";
print "ex2 is ", Evaluate($ex2), "\n";
print "ex2: ", Display($ex2), "\n";
print "\n";
print "ex3 is ", Evaluate($ex3), "\n";
print "ex3: ", Display($ex3), "\n";
print "\n";
Display::Render(\$ex3);
Для того, чтобы сделать это, я понимаю, что придется изменить подпрограмму «Display», но я «Не знаю, как получить значение вывода -> значение; #, чтобы указать значения, которые не усреднены # значение значение средний операнд и т. д.
Любые идеи?
Почему a; после 1, но не после 3, 4 или 5? – ysth
В случае данного дерева, ";" указывает, что существует разделение между тем, какие значения усредняются, а какие нет. Следовательно, 1 не подвергается среднему оператору и как таковая не включается со значениями 3, 4 и 5. Таким образом, конечный результат будет 1 + (3 + 4 + 5)/2 = 5. – Sheldon
@ ysth => подумайте о ';' как 'pushmark' в астрах perl –