1 /*******************************************************************************
2 * Reverse Polish Notation calculator. *
3 * Copyright (c) 2007-2008, Samuel Fredrickson <kinghajj@gmail.com> *
4 * All rights reserved. *
6 * Redistribution and use in source and binary forms, with or without *
7 * modification, are permitted provided that the following conditions are met: *
8 * * Redistributions of source code must retain the above copyright *
9 * notice, this list of conditions and the following disclaimer. *
10 * * Redistributions in binary form must reproduce the above copyright *
11 * notice, this list of conditions and the following disclaimer in the *
12 * documentation and/or other materials provided with the distribution. *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS *
15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY *
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR *
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
25 ******************************************************************************/
27 /*******************************************************************************
28 * Calculator.cpp - non-command Calculator methods. *
29 ******************************************************************************/
32 #include <boost/tokenizer.hpp>
34 using namespace boost
;
38 void Calculator::Eval(string s
)
40 typedef tokenizer
< char_separator
<char> > Tokens
;
41 char_separator
<char> sep(" \t\n");
42 Tokens
tokens(s
, sep
);
44 if(!HasStack()) return;
46 for(Tokens::iterator tok
= tokens
.begin();
47 tok
!= tokens
.end() && status
== Continue
;
50 Commands::iterator foundCommand
= commands
.find(*tok
);
51 Operators::iterator foundOperator
= operators
.find(*tok
);
52 Variables::iterator foundVariable
= variables
.find(*tok
);
55 // if the token is a number, push it.
56 if(istringstream(*tok
) >> val
)
57 CurrentStack().push_front(val
);
59 // if the token is a command, perform it.
60 else if(foundCommand
!= commands
.end())
62 const Command
& command
= foundCommand
->second
;
64 args
.reserve(command
.NumArgs());
66 // collect a list of tokens that will be the arguments to the
68 while(tok
!= tokens
.end() && args
.size() != command
.NumArgs())
69 args
.push_back(*++tok
);
71 // only perform a command if we can give it enough arguments.
72 if(args
.size() == command
.NumArgs())
73 command
.Perform(*this, args
);
76 // if the token is an operator and that stack has at least two items,
77 // then perform that operator.
78 else if(foundOperator
!= operators
.end() && StackSize() > 1)
80 Value b
= TopmostItem(); CurrentStack().pop_front();
81 Value a
= TopmostItem(); CurrentStack().pop_front();
82 CurrentStack().push_front(foundOperator
->second(a
, b
));
85 // if the token is a variable, push the variable onto the stack.
86 else if(foundVariable
!= variables
.end())
87 CurrentStack().push_front(foundVariable
->second
);
89 // otherwise, if the stack has at least one item, set a new variable
90 // whose name is the token and value is the top item.
91 else variables
[*tok
] = TopmostItem();
95 // displays the top item of the stack if there is one.
96 // I tried to write this as a friend operator<<(), but I got errors for
97 // accessing private data, which is what friend functions are supposed to be
99 void Calculator::Display() const
101 Print(TopmostItem());