级别: 圣骑士
- 注册时间:
- 2006-08-17
- 在线时间:
- 146小时
- 发帖:
- 215
|
中缀表达式长了也容易看晕,继续看有缩进的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程序 [ 此帖被linuxyouxia在2011-12-16 11:07重新编辑 ]
|