linuxyouxia |
2011-12-16 09:59 |
中缀表达式长了也容易看晕,继续看有缩进的S-表达式 mt_infix/mt_polish要通过avs调用,需要自己写个程序调用后直接返回字符串= = (Windows下通过命令行把表达式当参数传过去需要转义;*nix下要调用Wine,麻烦) 转中缀表达式Perl脚本
- #!/usr/bin/env perl
use strict; use warnings;
my @rpnstack;
my %opsymbol = ( '+' => \&mathop, '*' => \&mathop, '/' => \&mathop, '-' => \&mathop, '^' => \&mathop, '%' => \&mathop, '?' => \&ifop, '==' => \&mathop, '=' => \&mathop, '!=' => \&mathop, '<=' => \&mathop, '<' => \&mathop, '>=' => \&mathop, '>' => \&mathop, '&' => \&mathop, '|' => \&mathop, '&!' => \&mathop, '°' => \&mathop, '@' => \&mathop, '&u' => \&mathop, '|u' => \&mathop, '°u' => \&mathop, '@u' => \&mathop, '~u' => &funop(1), '<<' => \&mathop, '<<u' => \&mathop, '>>' => \&mathop, '>>u' => \&mathop, '&s' => \&mathop, '|s' => \&mathop, '°s' => \&mathop, '@s' => \&mathop, '~s' => &funop(1), '<<s' => \&mathop, '>>s' => \&mathop, 'cos' => &funop(1), 'sin' => &funop(1), 'tan' => &funop(1), 'log' => &funop(1), 'exp' => &funop(1), 'abs' => &funop(1), 'atan' => &funop(1), 'acos' => &funop(1), 'asin' => &funop(1), 'round' => &funop(1), 'clip' => &funop(3), 'min' => &funop(2), 'max' => &funop(2), 'ceil' => &funop(1), 'floor' => &funop(1), 'trunc' => &funop(1) );
sub poprpn { my $res = pop @rpnstack; if (!defined($res)) { print "$_: The user has not input sufficient values!\n"; $res = '*undef*'; } elsif (defined($opsymbol{$res})) { push(@rpnstack, $res); print "$_: The user has not input sufficient values!\n"; $res = '*undef*'; } return $res; }
sub funop { my $argc = shift; return sub { my $opstr = shift; $_ = $opstr; my $res = &poprpn; for (my $i = 2; $i <= $argc; $i++) { my $element = &poprpn; $res = "$element ".$res; } return "$opstr($res)"; } }
sub mathop { my $opstr = shift; $_ = $opstr; my $item1 = &poprpn; my $item2 = &poprpn; return "($item2 $opstr $item1)"; }
sub ifop { $_ = '?'; my $item1 = &poprpn; my $item2 = &poprpn; my $item3 = &poprpn; return "($item3 ? $item2 : $item1)"; } my @instr = split /(?<=")|(?=")/, $ARGV[0]; my $rpnexp = ''; my $state = 1; foreach my $to (@instr) { if ($state == 0 ) { if ($to eq '"') { $state = 1; next; } } elsif ($state == 1) { if ($to eq '"') { $state = 0; next; } $to =~ s/\+|\\/ /g; } $rpnexp = $rpnexp."$to "; } my @rpnstr = split /\s+/, $rpnexp;
foreach my $token (@rpnstr) { my $action = $opsymbol{$token}; if (defined($action)) { my $res = &$action($token); push(@rpnstack, $res); } else { push(@rpnstack, $token); } }
while (defined(my $exp = pop @rpnstack)) { print "$exp\n"; }
顺便想到了,可以给avisynth写个REPL程序 |
|