Paste: RPN calculator

Author: slava
Mode: factor
Date: Tue, 18 Aug 2009 00:37:36
Plain Text |
! Copyright (C) 2009 Slava Pestov
! See http://factorcode.org/license.txt for BSD license.
USING: accessors combinators io kernel lists math math.parser
sequences splitting ;
IN: rpn

SINGLETONS: add-insn sub-insn mul-insn div-insn ;
TUPLE: push-insn value ;

GENERIC: eval-insn ( stack insn -- stack )

: binary-op ( stack quot: ( x y -- z ) -- stack )
    [ uncons uncons ] dip dip cons ; inline

M: add-insn eval-insn drop [ + ] binary-op ;
M: sub-insn eval-insn drop [ - ] binary-op ;
M: mul-insn eval-insn drop [ * ] binary-op ;
M: div-insn eval-insn drop [ / ] binary-op ;
M: push-insn eval-insn value>> swons ;

: rpn-tokenize ( string -- string' )
    " " split harvest sequence>list ;

: rpn-parse ( string -- tokens )
    rpn-tokenize [
        {
            { "+" [ add-insn ] }
            { "-" [ sub-insn ] }
            { "*" [ mul-insn ] }
            { "/" [ div-insn ] }
            [ string>number push-insn boa ]
        } case
    ] lmap ;

: print-stack ( list -- )
    [ number>string print ] leach ;

: rpn-eval ( tokens -- )
    nil [ eval-insn ] foldl print-stack ;

: rpn ( -- )
    "RPN> " write flush
    readln [ rpn-parse rpn-eval rpn ] when* ;

Annotation: Python

Author: earl
Mode: python
Date: Tue, 18 Aug 2009 13:59:24
Plain Text |
# Copyright (C) 2009 Andreas Bolka
# See http://factorcode.org/license.txt for BSD license.
import operator

def mk_push(token):
    return lambda stack: push_insn(stack, int(token))

def binary_op(stack, op):
    stack.append(op(stack.pop(), stack.pop())); return stack

def add_insn(stack): return binary_op(stack, operator.add)
def sub_insn(stack): return binary_op(stack, operator.sub)
def mul_insn(stack): return binary_op(stack, operator.mul)
def div_insn(stack): return binary_op(stack, operator.div)
def push_insn(stack, value): stack.append(value); return stack

def eval_insn(stack, fn):
    return fn(stack)

def rpn_tokenize(string):
    return string.split()

def rpn_parse(string):
    return map(lambda token: {'+': add_insn,
                              '-': sub_insn,
                              '*': mul_insn,
                              '/': div_insn}.get(token, mk_push(token)),
               rpn_tokenize(string))

def print_stack(stack):
    for item in stack: print item

def rpn_eval(tokens):
    print_stack(reduce(eval_insn, tokens, []))

def rpn():
    try:
        while True: rpn_eval(rpn_parse(raw_input('RPN> ')))
    except EOFError:
        pass

New Annotation

Summary:
Author:
Mode:
Body: