« MINIX本 | Main | 中はLISPです »

2007.11.02

電卓

Higher-Order Perl、から。

Perlで逆ポーランドの電卓を作ろうという話題

#!/bin/perl
use strict;

my @stack;
my $actions = {
    '+' => sub { push @stack, pop(@stack) + pop(@stack) },
    '*' => sub { push @stack, pop(@stack) * pop(@stack) },
    '-' => sub { my $s = pop(@stack); push @stack, pop(@stack) - $s },
    '/' => sub { my $s = pop(@stack); push @stack, pop(@stack) / $s },
    'NUMBER' => sub {push @stack, $_[0] },
    '_DEFAULT_' => sub { die "Unrecognized token '$_[0]'; aborting" }
};

my $result = evaluate($ARGV[0], $actions);
print "Result: $result\n";

sub evaluate {
    my ($expr, $actions) = @_;
    my @tokens = split /\s+/, $expr;
    
    for my $token (@tokens) {
        my $type;
        if ($token =~ /^\d+$/) {
            $type = 'NUMBER';
        }

        my $action = $actions->{$type} || $actions->{$token} || $actions->{_DEFAULT_};

        $action->($token, $type, $actions);
    }
    return pop(@stack);
}

ざっとこんな感じ。
my $action = $actions->{$type} || $actions->{$token} || $actions->{_DEFAULT_};
この辺りがLLぽい。一つめのハッシュが駄目なら、次のハッシュ。

class calclator {
public:
  int calc(std::vector tokens) {
    std::vector::iterator it;
    for(it=tokens.begin();it!=tokens.end();it++) {
      if(it->type() == NUMBER) {
        st.push(*it);
      } else if(it->type() == OPERATOR) {
        token op2 = st.top(); st.pop();
        token op1 = st.top(); st.pop();
        st.push((*it)(op1, op2));
      } else {
        std::cout << "error" << std::endl;
      }
    }
    token result = st.top();
    st.pop();
    return result.value();
  }
  
private:
  std::stack st;
};

一応C++でもそれっぽくできて動いたけど、なんかダサイ。
スタックに、文字列でも数字でも入れられるようにしようとしたのが失敗。逆ポーランド記法ではスタックに入るのは数字のみと気がついたのは、完成間近。それに気がついたとたんやる気がなくなった。なんでもほいほいpushできるLLすげー。普通の会社でC++で開発していて、やべー設計間違ってるって時、どうしてるんだろうな。

'+'のアクションで、std::plusが使えそうだったけど上手く行かなかった。今日はstd::stackが使えるようになったので良しとしよう。一日一歩。

Perl、入出力込みで数時間。(丸写しだけどね)
C++、3日がかりで、入力はソースに直書き。

むう、そろそろC++挫折しそうになってきた。

|

« MINIX本 | Main | 中はLISPです »

Comments

The comments to this entry are closed.

TrackBack


Listed below are links to weblogs that reference 電卓:

« MINIX本 | Main | 中はLISPです »