reverse-polish-calculator 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.rvmrc +1 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +15 -0
- data/bin/rpc +6 -0
- data/lib/reverse-polish-calculator.rb +31 -0
- data/lib/reverse-polish-calculator/errors.rb +27 -0
- data/lib/reverse-polish-calculator/helpers.rb +11 -0
- data/lib/reverse-polish-calculator/input.rb +38 -0
- data/lib/reverse-polish-calculator/inputs.rb +79 -0
- data/lib/reverse-polish-calculator/output.rb +21 -0
- data/lib/reverse-polish-calculator/stack.rb +38 -0
- data/lib/reverse-polish-calculator/version.rb +3 -0
- data/reverse-polish-calculator.gemspec +22 -0
- data/spec/acceptance/complex_expressions_spec.rb +91 -0
- data/spec/acceptance/error_handling_spec.rb +50 -0
- data/spec/acceptance/simple_arithmetic_spec.rb +173 -0
- data/spec/acceptance/simple_trigonometric_spec.rb +89 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/aruba.rb +4 -0
- data/spec/support/string_ext.rb +5 -0
- data/spec/unit/reverse-polish-calculator/errors_spec.rb +40 -0
- data/spec/unit/reverse-polish-calculator/input_spec.rb +95 -0
- data/spec/unit/reverse-polish-calculator/inputs_spec.rb +71 -0
- data/spec/unit/reverse-polish-calculator/output_spec.rb +40 -0
- data/spec/unit/reverse-polish-calculator/stack_spec.rb +95 -0
- data/spec/unit/reverse-polish-calculator_spec.rb +18 -0
- metadata +128 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.2@reverse-polish-calculator
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Justin Ko
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# reverse-polish-calculator
|
2
|
+
|
3
|
+
This is a [RPN](http://en.wikipedia.org/wiki/Reverse_Polish_notation) (Reverse Polish Notation) command line calculator. It supports arithmetic, and *most* of the methods in Ruby's [Math](http://www.ruby-doc.org/core/classes/Math.html) module.
|
4
|
+
|
5
|
+
## Synopsis
|
6
|
+
|
7
|
+
$ rpc
|
8
|
+
$ 5 # => stack: 5.0
|
9
|
+
aggregate: 0
|
10
|
+
$ 5 # => stack: 5.0, 5.0
|
11
|
+
aggregate: 0
|
12
|
+
$ + # => calculated: 5.0 + 5.0
|
13
|
+
stack:
|
14
|
+
aggregate: 10.0
|
15
|
+
|
16
|
+
For more examples, check out the acceptance specs.
|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
gem install reverse-polish-calculator
|
21
|
+
|
22
|
+
## License
|
23
|
+
|
24
|
+
reverse-polish-calculator is released under the MIT license. See LICENSE for details.
|
25
|
+
|
26
|
+
## Copyright
|
27
|
+
|
28
|
+
Copyright (c) 2011 Justin Ko
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
task :default => ['spec:unit', 'spec:acceptance']
|
5
|
+
|
6
|
+
namespace :spec do
|
7
|
+
|
8
|
+
[:acceptance, :unit].each do |suite|
|
9
|
+
desc "Run the #{suite} specs"
|
10
|
+
RSpec::Core::RakeTask.new(suite) do |t|
|
11
|
+
t.pattern = "./spec/#{suite}/**/*_spec.rb"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
data/bin/rpc
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'reverse-polish-calculator/helpers'
|
2
|
+
require 'reverse-polish-calculator/stack'
|
3
|
+
require 'reverse-polish-calculator/inputs'
|
4
|
+
require 'reverse-polish-calculator/input'
|
5
|
+
require 'reverse-polish-calculator/errors'
|
6
|
+
require 'reverse-polish-calculator/output'
|
7
|
+
|
8
|
+
module ReversePolishCalculator
|
9
|
+
|
10
|
+
def self.start
|
11
|
+
loop_with_error_handling do
|
12
|
+
stack.add(gets.chomp)
|
13
|
+
stack.calculate
|
14
|
+
stack.output
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.stack
|
19
|
+
@stack ||= Stack.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.loop_with_error_handling
|
23
|
+
loop { yield }
|
24
|
+
rescue *Errors::Classes => exception
|
25
|
+
Errors.handle(exception)
|
26
|
+
Output.clear
|
27
|
+
stack.unswap
|
28
|
+
retry
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ReversePolishCalculator
|
2
|
+
module Errors
|
3
|
+
|
4
|
+
MethodMapping = {
|
5
|
+
NoMethodError => :no_method_error,
|
6
|
+
Math::DomainError => :math_domain_error
|
7
|
+
}
|
8
|
+
|
9
|
+
Classes = MethodMapping.keys
|
10
|
+
|
11
|
+
def self.handle(exception)
|
12
|
+
send(MethodMapping[exception.class], exception)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.no_method_error(exception)
|
16
|
+
ReversePolishCalculator.stack.remove(exception.name)
|
17
|
+
Helpers.multi_puts "Cannot calculate '#{exception.name}'"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.math_domain_error(exception)
|
21
|
+
name = exception.message.match(/"(.+)"/)[1]
|
22
|
+
ReversePolishCalculator.stack.remove(name)
|
23
|
+
Helpers.multi_puts "Bad value for '#{name}'"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ReversePolishCalculator
|
2
|
+
class Input
|
3
|
+
|
4
|
+
attr_reader :value
|
5
|
+
|
6
|
+
def initialize(value)
|
7
|
+
@value = value
|
8
|
+
exit if exited?
|
9
|
+
end
|
10
|
+
|
11
|
+
def exited?
|
12
|
+
value.downcase == 'q'
|
13
|
+
end
|
14
|
+
|
15
|
+
def invoke(input_1, input_2 = nil)
|
16
|
+
if math_method?
|
17
|
+
Output.add "calculated: #{value}(#{input_1.to_f})"
|
18
|
+
Math.send(value, input_1.to_f)
|
19
|
+
else
|
20
|
+
Output.add "calculated: #{input_1.to_f} #{value} #{input_2.to_f}"
|
21
|
+
input_1.to_f.send(value, input_2.to_f)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def math_method?
|
26
|
+
Math.respond_to?(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def operand?
|
30
|
+
!!value[/\d/]
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_f
|
34
|
+
value.to_f
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ReversePolishCalculator
|
2
|
+
module Inputs
|
3
|
+
|
4
|
+
attr_accessor :swapped
|
5
|
+
|
6
|
+
def calculate(aggregate = 0)
|
7
|
+
@operands, @trash = [], []
|
8
|
+
@aggregate = aggregate
|
9
|
+
|
10
|
+
each do |input|
|
11
|
+
if input.operand?
|
12
|
+
add_operand(input)
|
13
|
+
elsif input.math_method?
|
14
|
+
invoke_math_method(input)
|
15
|
+
else
|
16
|
+
invoke_binary_operator(input)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
empty_trash
|
21
|
+
calculation
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_operand(input)
|
25
|
+
@operands << input
|
26
|
+
@calculated = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def invoke_math_method(input)
|
30
|
+
operand = @operands.pop || @aggregate
|
31
|
+
@operands.push input.invoke(operand)
|
32
|
+
@trash << input << operand
|
33
|
+
@calculated = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def invoke_binary_operator(input)
|
37
|
+
operand_1 = @operands.pop
|
38
|
+
operand_2 = @operands.pop
|
39
|
+
|
40
|
+
unless operand_2
|
41
|
+
self.swapped = true
|
42
|
+
operand_2 = operand_1
|
43
|
+
operand_1 = @aggregate
|
44
|
+
else
|
45
|
+
self.swapped = false
|
46
|
+
end
|
47
|
+
|
48
|
+
@operands.push(if @swapped
|
49
|
+
input.invoke(operand_1, operand_2)
|
50
|
+
else
|
51
|
+
input.invoke(operand_2, operand_1)
|
52
|
+
end)
|
53
|
+
|
54
|
+
@trash << input << operand_1 << operand_2
|
55
|
+
@calculated = true
|
56
|
+
end
|
57
|
+
|
58
|
+
def calculation
|
59
|
+
if @calculated
|
60
|
+
if swapped
|
61
|
+
@operands.first
|
62
|
+
else
|
63
|
+
@aggregate + @operands.last.to_f
|
64
|
+
end
|
65
|
+
else
|
66
|
+
@aggregate
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def empty_trash
|
71
|
+
delete_if {|input| @trash.include?(input) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
map(&:to_f).join(', ')
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ReversePolishCalculator
|
2
|
+
module Output
|
3
|
+
|
4
|
+
def self.add(str)
|
5
|
+
texts.push(str)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.texts
|
9
|
+
@texts ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.display
|
13
|
+
Helpers.multi_puts(*texts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.clear
|
17
|
+
texts.clear
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ReversePolishCalculator
|
2
|
+
class Stack
|
3
|
+
|
4
|
+
attr_reader :inputs, :aggregate
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@inputs, @aggregate = [].extend(Inputs), 0
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(expression)
|
11
|
+
expression.split.each do |value|
|
12
|
+
@inputs << Input.new(value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def remove(input_value)
|
17
|
+
@inputs.delete_if do |input|
|
18
|
+
input.value == input_value.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def calculate
|
23
|
+
@aggregate = @inputs.calculate(aggregate)
|
24
|
+
end
|
25
|
+
|
26
|
+
def output
|
27
|
+
Output.add "stack: #{@inputs.inspect}"
|
28
|
+
Output.add "aggregate: #{@aggregate}"
|
29
|
+
Output.display
|
30
|
+
Output.clear
|
31
|
+
end
|
32
|
+
|
33
|
+
def unswap
|
34
|
+
inputs.swapped = false
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'reverse-polish-calculator/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'reverse-polish-calculator'
|
7
|
+
s.version = ReversePolishCalculator::VERSION
|
8
|
+
s.authors = 'Justin Ko'
|
9
|
+
s.email = 'jko170@gmail.com'
|
10
|
+
s.homepage = 'https://github.com/justinko/reverse-polish-calculator'
|
11
|
+
s.summary = 'Reverse Polish Calculator'
|
12
|
+
s.description = 'Command line RPN (Reverse Polish Notation) calculator'
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_path = 'lib'
|
18
|
+
|
19
|
+
s.add_development_dependency 'rake'
|
20
|
+
s.add_development_dependency 'rspec'
|
21
|
+
s.add_development_dependency 'aruba'
|
22
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'complex expressions' do
|
4
|
+
|
5
|
+
describe '5 1 2 + 4 * + 3 - 2 / cos' do
|
6
|
+
context 'on one line' do
|
7
|
+
it 'aggregates to 7.0' do
|
8
|
+
start
|
9
|
+
type '5 1 2 + 4 * + 3 - 2 / cos'
|
10
|
+
type 'q'
|
11
|
+
|
12
|
+
assert_exact_output <<-OUTPUT.rpc
|
13
|
+
calculated: 1.0 + 2.0
|
14
|
+
calculated: 3.0 * 4.0
|
15
|
+
calculated: 5.0 + 12.0
|
16
|
+
calculated: 17.0 - 3.0
|
17
|
+
calculated: 14.0 / 2.0
|
18
|
+
calculated: cos(7.0)
|
19
|
+
stack:
|
20
|
+
aggregate: 0.7539022543433046
|
21
|
+
|
22
|
+
OUTPUT
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'on separate lines' do
|
27
|
+
it 'aggregates to 10.0' do
|
28
|
+
start
|
29
|
+
type '5'
|
30
|
+
type '1'
|
31
|
+
type '2'
|
32
|
+
type '+'
|
33
|
+
type '4'
|
34
|
+
type '*'
|
35
|
+
type '+'
|
36
|
+
type '3'
|
37
|
+
type '-'
|
38
|
+
type '2'
|
39
|
+
type '/'
|
40
|
+
type 'cos'
|
41
|
+
type 'q'
|
42
|
+
|
43
|
+
assert_exact_output <<-OUTPUT.rpc
|
44
|
+
stack: 5.0
|
45
|
+
aggregate: 0
|
46
|
+
|
47
|
+
stack: 5.0, 1.0
|
48
|
+
aggregate: 0
|
49
|
+
|
50
|
+
stack: 5.0, 1.0, 2.0
|
51
|
+
aggregate: 0
|
52
|
+
|
53
|
+
calculated: 1.0 + 2.0
|
54
|
+
stack: 5.0
|
55
|
+
aggregate: 3.0
|
56
|
+
|
57
|
+
stack: 5.0, 4.0
|
58
|
+
aggregate: 3.0
|
59
|
+
|
60
|
+
calculated: 5.0 * 4.0
|
61
|
+
stack:
|
62
|
+
aggregate: 23.0
|
63
|
+
|
64
|
+
calculated: 23.0 + 0.0
|
65
|
+
stack:
|
66
|
+
aggregate: 23.0
|
67
|
+
|
68
|
+
stack: 3.0
|
69
|
+
aggregate: 23.0
|
70
|
+
|
71
|
+
calculated: 23.0 - 3.0
|
72
|
+
stack:
|
73
|
+
aggregate: 20.0
|
74
|
+
|
75
|
+
stack: 2.0
|
76
|
+
aggregate: 20.0
|
77
|
+
|
78
|
+
calculated: 20.0 / 2.0
|
79
|
+
stack:
|
80
|
+
aggregate: 10.0
|
81
|
+
|
82
|
+
calculated: cos(10.0)
|
83
|
+
stack:
|
84
|
+
aggregate: -0.8390715290764524
|
85
|
+
|
86
|
+
OUTPUT
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'error handling' do
|
4
|
+
|
5
|
+
describe "for an input that can't be calculated" do
|
6
|
+
it 'provides a message' do
|
7
|
+
start
|
8
|
+
type 'foo'
|
9
|
+
type '5'
|
10
|
+
type '4'
|
11
|
+
type '+'
|
12
|
+
type 'q'
|
13
|
+
|
14
|
+
assert_exact_output <<-OUTPUT.rpc
|
15
|
+
Cannot calculate 'foo'
|
16
|
+
|
17
|
+
stack: 5.0
|
18
|
+
aggregate: 0
|
19
|
+
|
20
|
+
stack: 5.0, 4.0
|
21
|
+
aggregate: 0
|
22
|
+
|
23
|
+
calculated: 5.0 + 4.0
|
24
|
+
stack:
|
25
|
+
aggregate: 9.0
|
26
|
+
|
27
|
+
OUTPUT
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'for a trigonometric method' do
|
32
|
+
context 'that is called with a non-computable value' do
|
33
|
+
it 'provides a message' do
|
34
|
+
start
|
35
|
+
type '5'
|
36
|
+
type 'acos'
|
37
|
+
type 'q'
|
38
|
+
|
39
|
+
assert_exact_output <<-OUTPUT.rpc
|
40
|
+
stack: 5.0
|
41
|
+
aggregate: 0
|
42
|
+
|
43
|
+
Bad value for 'acos'
|
44
|
+
|
45
|
+
OUTPUT
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'simple arithmetic' do
|
4
|
+
|
5
|
+
describe 'addition' do
|
6
|
+
describe '2 2 +' do
|
7
|
+
context 'on separate lines' do
|
8
|
+
it 'aggregates to 4.0' do
|
9
|
+
start
|
10
|
+
type '2'
|
11
|
+
type '2'
|
12
|
+
type '+'
|
13
|
+
type 'q'
|
14
|
+
|
15
|
+
assert_exact_output <<-OUTPUT.rpc
|
16
|
+
stack: 2.0
|
17
|
+
aggregate: 0
|
18
|
+
|
19
|
+
stack: 2.0, 2.0
|
20
|
+
aggregate: 0
|
21
|
+
|
22
|
+
calculated: 2.0 + 2.0
|
23
|
+
stack:
|
24
|
+
aggregate: 4.0
|
25
|
+
|
26
|
+
OUTPUT
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'on one line' do
|
31
|
+
it 'aggregates to 4.0' do
|
32
|
+
start
|
33
|
+
type '2 2 +'
|
34
|
+
type 'q'
|
35
|
+
|
36
|
+
assert_exact_output <<-OUTPUT.rpc
|
37
|
+
calculated: 2.0 + 2.0
|
38
|
+
stack:
|
39
|
+
aggregate: 4.0
|
40
|
+
|
41
|
+
OUTPUT
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'subtraction' do
|
48
|
+
describe '4 2 -' do
|
49
|
+
context 'on seperate lines' do
|
50
|
+
it 'aggregates to 2.0' do
|
51
|
+
start
|
52
|
+
type '4'
|
53
|
+
type '2'
|
54
|
+
type '-'
|
55
|
+
type 'q'
|
56
|
+
|
57
|
+
assert_exact_output <<-OUTPUT.rpc
|
58
|
+
stack: 4.0
|
59
|
+
aggregate: 0
|
60
|
+
|
61
|
+
stack: 4.0, 2.0
|
62
|
+
aggregate: 0
|
63
|
+
|
64
|
+
calculated: 4.0 - 2.0
|
65
|
+
stack:
|
66
|
+
aggregate: 2.0
|
67
|
+
|
68
|
+
OUTPUT
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'on one line' do
|
73
|
+
it 'aggregates to 2.0' do
|
74
|
+
start
|
75
|
+
type '4 2 -'
|
76
|
+
type 'q'
|
77
|
+
|
78
|
+
assert_exact_output <<-OUTPUT.rpc
|
79
|
+
calculated: 4.0 - 2.0
|
80
|
+
stack:
|
81
|
+
aggregate: 2.0
|
82
|
+
|
83
|
+
OUTPUT
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'multiplication' do
|
90
|
+
describe '3 2 *' do
|
91
|
+
context 'on seperate lines' do
|
92
|
+
it 'aggregates to 6.0' do
|
93
|
+
start
|
94
|
+
type '3'
|
95
|
+
type '2'
|
96
|
+
type '*'
|
97
|
+
type 'q'
|
98
|
+
|
99
|
+
assert_exact_output <<-OUTPUT.rpc
|
100
|
+
stack: 3.0
|
101
|
+
aggregate: 0
|
102
|
+
|
103
|
+
stack: 3.0, 2.0
|
104
|
+
aggregate: 0
|
105
|
+
|
106
|
+
calculated: 3.0 * 2.0
|
107
|
+
stack:
|
108
|
+
aggregate: 6.0
|
109
|
+
|
110
|
+
OUTPUT
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'on one line' do
|
115
|
+
it 'aggregates to 6.0' do
|
116
|
+
start
|
117
|
+
type '3 2 *'
|
118
|
+
type 'q'
|
119
|
+
|
120
|
+
assert_exact_output <<-OUTPUT.rpc
|
121
|
+
calculated: 3.0 * 2.0
|
122
|
+
stack:
|
123
|
+
aggregate: 6.0
|
124
|
+
|
125
|
+
OUTPUT
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe 'division' do
|
132
|
+
describe '10 2 /' do
|
133
|
+
context 'on seperate lines' do
|
134
|
+
it 'aggregates to 5.0' do
|
135
|
+
start
|
136
|
+
type '10'
|
137
|
+
type '2'
|
138
|
+
type '/'
|
139
|
+
type 'q'
|
140
|
+
|
141
|
+
assert_exact_output <<-OUTPUT.rpc
|
142
|
+
stack: 10.0
|
143
|
+
aggregate: 0
|
144
|
+
|
145
|
+
stack: 10.0, 2.0
|
146
|
+
aggregate: 0
|
147
|
+
|
148
|
+
calculated: 10.0 / 2.0
|
149
|
+
stack:
|
150
|
+
aggregate: 5.0
|
151
|
+
|
152
|
+
OUTPUT
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'on one line' do
|
157
|
+
it 'aggregates to 5.0' do
|
158
|
+
start
|
159
|
+
type '10 2 /'
|
160
|
+
type 'q'
|
161
|
+
|
162
|
+
assert_exact_output <<-OUTPUT.rpc
|
163
|
+
calculated: 10.0 / 2.0
|
164
|
+
stack:
|
165
|
+
aggregate: 5.0
|
166
|
+
|
167
|
+
OUTPUT
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'simple trigonometric' do
|
4
|
+
|
5
|
+
describe 'acos' do
|
6
|
+
describe 'given -1' do
|
7
|
+
it 'returns 3.141592653589793' do
|
8
|
+
start
|
9
|
+
type '-1'
|
10
|
+
type 'acos'
|
11
|
+
type 'q'
|
12
|
+
|
13
|
+
assert_exact_output <<-OUTPUT.rpc
|
14
|
+
stack: -1.0
|
15
|
+
aggregate: 0
|
16
|
+
|
17
|
+
calculated: acos(-1.0)
|
18
|
+
stack:
|
19
|
+
aggregate: 3.141592653589793
|
20
|
+
|
21
|
+
OUTPUT
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'asin' do
|
27
|
+
describe 'given -1' do
|
28
|
+
it 'returns -1.5707963267948966' do
|
29
|
+
start
|
30
|
+
type '-1'
|
31
|
+
type 'asin'
|
32
|
+
type 'q'
|
33
|
+
|
34
|
+
assert_exact_output <<-OUTPUT.rpc
|
35
|
+
stack: -1.0
|
36
|
+
aggregate: 0
|
37
|
+
|
38
|
+
calculated: asin(-1.0)
|
39
|
+
stack:
|
40
|
+
aggregate: -1.5707963267948966
|
41
|
+
|
42
|
+
OUTPUT
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'cos' do
|
48
|
+
describe 'given 1' do
|
49
|
+
it 'returns 0.5403023058681398' do
|
50
|
+
start
|
51
|
+
type '1'
|
52
|
+
type 'cos'
|
53
|
+
type 'q'
|
54
|
+
|
55
|
+
assert_exact_output <<-OUTPUT.rpc
|
56
|
+
stack: 1.0
|
57
|
+
aggregate: 0
|
58
|
+
|
59
|
+
calculated: cos(1.0)
|
60
|
+
stack:
|
61
|
+
aggregate: 0.5403023058681398
|
62
|
+
|
63
|
+
OUTPUT
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'tan' do
|
69
|
+
describe 'given 1' do
|
70
|
+
it 'returns 1.557407724654902' do
|
71
|
+
start
|
72
|
+
type '1'
|
73
|
+
type 'tan'
|
74
|
+
type 'q'
|
75
|
+
|
76
|
+
assert_exact_output <<-OUTPUT.rpc
|
77
|
+
stack: 1.0
|
78
|
+
aggregate: 0
|
79
|
+
|
80
|
+
calculated: tan(1.0)
|
81
|
+
stack:
|
82
|
+
aggregate: 1.557407724654902
|
83
|
+
|
84
|
+
OUTPUT
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
|
5
|
+
require 'reverse-polish-calculator'
|
6
|
+
require 'aruba/api'
|
7
|
+
|
8
|
+
Dir['./spec/support/*.rb'].map {|f| require f}
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.color_enabled = true
|
12
|
+
config.include Aruba::Api, :example_group => {
|
13
|
+
:file_path => /spec\/acceptance/
|
14
|
+
}
|
15
|
+
config.before(:suite, :example_group => {
|
16
|
+
:file_path => /spec\/unit/
|
17
|
+
}) { $in_unit_spec_suite = true }
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ReversePolishCalculator
|
4
|
+
describe Errors do
|
5
|
+
|
6
|
+
describe '.handle' do
|
7
|
+
context 'given a NoMethodError exception' do
|
8
|
+
let(:exception) { NoMethodError.new }
|
9
|
+
|
10
|
+
it 'calls .no_method_error' do
|
11
|
+
described_class.should_receive(:no_method_error).with(exception)
|
12
|
+
described_class.handle(exception)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.no_method_error' do
|
18
|
+
context 'given a NoMethodError exception' do
|
19
|
+
let(:exception) { NoMethodError.new('message', 'name') }
|
20
|
+
|
21
|
+
it 'removes the offending input from the stack' do
|
22
|
+
ReversePolishCalculator.stack.should_receive(:remove).with('name')
|
23
|
+
described_class.no_method_error(exception)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.math_domain_error' do
|
29
|
+
context 'given a Math::DomainError exception' do
|
30
|
+
let(:exception) { Math::DomainError.new('the "name"') }
|
31
|
+
|
32
|
+
it 'removes the offending input from the stack' do
|
33
|
+
ReversePolishCalculator.stack.should_receive(:remove).with('name')
|
34
|
+
described_class.math_domain_error(exception)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ReversePolishCalculator
|
4
|
+
describe Input do
|
5
|
+
|
6
|
+
describe '#exited?' do
|
7
|
+
let(:input) { described_class.allocate }
|
8
|
+
|
9
|
+
context 'with input value of "q"' do
|
10
|
+
it 'returns true' do
|
11
|
+
input.instance_variable_set('@value', 'q')
|
12
|
+
input.should be_exited
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'with input value of "Q"' do
|
17
|
+
it 'returns true' do
|
18
|
+
input.instance_variable_set('@value', 'Q')
|
19
|
+
input.should be_exited
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with input value of "foo"' do
|
24
|
+
it 'returns false' do
|
25
|
+
input.instance_variable_set('@value', 'foo')
|
26
|
+
input.should_not be_exited
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#invoke' do
|
32
|
+
context 'with input value of "+"' do
|
33
|
+
let(:input) { described_class.new('+') }
|
34
|
+
|
35
|
+
context 'given 2 inputs that have a value of "2"' do
|
36
|
+
let(:input_1) { described_class.new('2') }
|
37
|
+
let(:input_2) { described_class.new('2') }
|
38
|
+
|
39
|
+
it 'returns 4.0' do
|
40
|
+
input.invoke(input_1, input_2).should eq(4.0)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with input value of "acos"' do
|
46
|
+
let(:input) { described_class.new('acos') }
|
47
|
+
|
48
|
+
context 'given 1 input with a value of "-1"' do
|
49
|
+
let(:input_1) { described_class.new('-1') }
|
50
|
+
|
51
|
+
it 'returns 3.141592653589793' do
|
52
|
+
input.invoke(input_1).should eq(3.141592653589793)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#math_method?' do
|
59
|
+
context 'with input value of "acos"' do
|
60
|
+
it 'returns true' do
|
61
|
+
described_class.new('acos').should be_math_method
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'with input value of "foo"' do
|
66
|
+
it 'returns false' do
|
67
|
+
described_class.new('foo').should_not be_math_method
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#operand?' do
|
73
|
+
context 'with input value of "5"' do
|
74
|
+
it 'returns true' do
|
75
|
+
described_class.new('5').should be_operand
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with input value of "foo"' do
|
80
|
+
it 'returns false' do
|
81
|
+
described_class.new('foo').should_not be_operand
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#to_f' do
|
87
|
+
context 'with input value of "5"' do
|
88
|
+
it 'returns 5.0' do
|
89
|
+
described_class.new('5').to_f.should eq(5.0)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ReversePolishCalculator
|
4
|
+
describe Inputs do
|
5
|
+
let(:inputs) { [].extend(described_class) }
|
6
|
+
|
7
|
+
describe '#calculate' do
|
8
|
+
context 'given inputs: 2 2 +' do
|
9
|
+
before { add_inputs('2 2 +') }
|
10
|
+
|
11
|
+
it 'returns 4.0' do
|
12
|
+
inputs.calculate.should eq(4.0)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'given inputs: 2 +' do
|
17
|
+
before { add_inputs('2 +') }
|
18
|
+
|
19
|
+
it 'returns 2.0' do
|
20
|
+
inputs.calculate.should eq(2.0)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'given inputs: 2 2 2 + +' do
|
25
|
+
before { add_inputs('2 2 2 + +') }
|
26
|
+
|
27
|
+
it 'returns 6.0' do
|
28
|
+
inputs.calculate.should eq(6.0)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'given inputs: 2 2 + +' do
|
33
|
+
before { add_inputs('2 2 + +') }
|
34
|
+
|
35
|
+
it 'returns 4.0' do
|
36
|
+
inputs.calculate.should eq(4.0)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'given inputs: -1 acos' do
|
41
|
+
before { add_inputs('-1 acos') }
|
42
|
+
|
43
|
+
it 'returns 3.141592653589793' do
|
44
|
+
inputs.calculate.should eq(3.141592653589793)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'given inputs: cos' do
|
49
|
+
before { add_inputs('cos') }
|
50
|
+
|
51
|
+
context 'and an aggregate of 3.0' do
|
52
|
+
it 'returns 2.010007503399555' do
|
53
|
+
inputs.calculate(3.0).should eq(2.010007503399555)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#inspect' do
|
60
|
+
before { add_inputs('1 2') }
|
61
|
+
specify { inputs.inspect.should eq('1.0, 2.0') }
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_inputs(expression)
|
65
|
+
expression.split.each do |input|
|
66
|
+
inputs << Input.new(input)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ReversePolishCalculator
|
4
|
+
describe Output do
|
5
|
+
|
6
|
+
describe '.add' do
|
7
|
+
context 'given "foo"' do
|
8
|
+
it 'adds "foo" to the list of texts' do
|
9
|
+
described_class.add('foo')
|
10
|
+
described_class.texts.should include('foo')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.texts' do
|
16
|
+
it 'returns an array' do
|
17
|
+
described_class.texts.should be_an_instance_of(Array)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '.display' do
|
22
|
+
before { described_class.clear }
|
23
|
+
|
24
|
+
it 'calls Helpers.multi_puts with the list of texts' do
|
25
|
+
described_class.add('foo')
|
26
|
+
Helpers.should_receive(:multi_puts).with('foo')
|
27
|
+
described_class.display
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '.clear' do
|
32
|
+
it 'clears out the list of texts' do
|
33
|
+
described_class.add('foo')
|
34
|
+
described_class.clear
|
35
|
+
described_class.texts.should be_empty
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ReversePolishCalculator
|
4
|
+
describe Stack do
|
5
|
+
|
6
|
+
describe '#add' do
|
7
|
+
context 'given a single character' do
|
8
|
+
before { subject.add('5') }
|
9
|
+
|
10
|
+
it 'adds one input' do
|
11
|
+
subject.should have(1).inputs
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'given 3 characters between spaces' do
|
16
|
+
before { subject.add('1 2 3') }
|
17
|
+
|
18
|
+
it 'adds 3 inputs' do
|
19
|
+
subject.should have(3).inputs
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#remove' do
|
25
|
+
context 'given an input value that exists in inputs' do
|
26
|
+
before { subject.add('foo') }
|
27
|
+
|
28
|
+
it 'removes the input' do
|
29
|
+
expect do
|
30
|
+
subject.remove('foo')
|
31
|
+
end.to change(subject.inputs, :size).by(-1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#calculate' do
|
37
|
+
it 'aggregates' do
|
38
|
+
subject.inputs << Input.new('2')
|
39
|
+
subject.inputs << Input.new('2')
|
40
|
+
subject.inputs << Input.new('+')
|
41
|
+
|
42
|
+
subject.calculate
|
43
|
+
subject.aggregate.should eq(4.0)
|
44
|
+
|
45
|
+
subject.inputs << Input.new('2')
|
46
|
+
subject.inputs << Input.new('2')
|
47
|
+
subject.inputs << Input.new('+')
|
48
|
+
|
49
|
+
subject.calculate
|
50
|
+
subject.aggregate.should eq(8.0)
|
51
|
+
|
52
|
+
subject.inputs << Input.new('2')
|
53
|
+
subject.inputs << Input.new('-')
|
54
|
+
|
55
|
+
subject.calculate
|
56
|
+
subject.aggregate.should eq(6.0)
|
57
|
+
|
58
|
+
subject.inputs << Input.new('2')
|
59
|
+
subject.inputs << Input.new('*')
|
60
|
+
|
61
|
+
subject.calculate
|
62
|
+
subject.aggregate.should eq(12.0)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe '#output' do
|
67
|
+
it 'calls .add on Output, twice' do
|
68
|
+
Output.should_receive(:add).twice
|
69
|
+
subject.output
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'calls .display on Output' do
|
73
|
+
Output.should_receive(:display)
|
74
|
+
subject.output
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'calls .clear on Output' do
|
78
|
+
Output.should_receive(:clear)
|
79
|
+
subject.output
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#unswap' do
|
84
|
+
context 'with inputs.swapped set to true' do
|
85
|
+
before { subject.inputs.swapped = true }
|
86
|
+
|
87
|
+
it 'sets inputs.swapped to false' do
|
88
|
+
expect { subject.unswap }.to change {
|
89
|
+
subject.inputs.swapped }.from(true).to(false)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ReversePolishCalculator do
|
4
|
+
|
5
|
+
describe '.start' do
|
6
|
+
it 'starts the loop' do
|
7
|
+
described_class.should_receive(:loop)
|
8
|
+
described_class.start
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.stack' do
|
13
|
+
it 'returns an instance of Stack' do
|
14
|
+
described_class.stack.should be_an_instance_of(described_class::Stack)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: reverse-polish-calculator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Justin Ko
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-06-06 00:00:00 -06:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rake
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :development
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: aruba
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id003
|
49
|
+
description: Command line RPN (Reverse Polish Notation) calculator
|
50
|
+
email: jko170@gmail.com
|
51
|
+
executables:
|
52
|
+
- rpc
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- .rvmrc
|
60
|
+
- Gemfile
|
61
|
+
- LICENSE
|
62
|
+
- README.md
|
63
|
+
- Rakefile
|
64
|
+
- bin/rpc
|
65
|
+
- lib/reverse-polish-calculator.rb
|
66
|
+
- lib/reverse-polish-calculator/errors.rb
|
67
|
+
- lib/reverse-polish-calculator/helpers.rb
|
68
|
+
- lib/reverse-polish-calculator/input.rb
|
69
|
+
- lib/reverse-polish-calculator/inputs.rb
|
70
|
+
- lib/reverse-polish-calculator/output.rb
|
71
|
+
- lib/reverse-polish-calculator/stack.rb
|
72
|
+
- lib/reverse-polish-calculator/version.rb
|
73
|
+
- reverse-polish-calculator.gemspec
|
74
|
+
- spec/acceptance/complex_expressions_spec.rb
|
75
|
+
- spec/acceptance/error_handling_spec.rb
|
76
|
+
- spec/acceptance/simple_arithmetic_spec.rb
|
77
|
+
- spec/acceptance/simple_trigonometric_spec.rb
|
78
|
+
- spec/spec_helper.rb
|
79
|
+
- spec/support/aruba.rb
|
80
|
+
- spec/support/string_ext.rb
|
81
|
+
- spec/unit/reverse-polish-calculator/errors_spec.rb
|
82
|
+
- spec/unit/reverse-polish-calculator/input_spec.rb
|
83
|
+
- spec/unit/reverse-polish-calculator/inputs_spec.rb
|
84
|
+
- spec/unit/reverse-polish-calculator/output_spec.rb
|
85
|
+
- spec/unit/reverse-polish-calculator/stack_spec.rb
|
86
|
+
- spec/unit/reverse-polish-calculator_spec.rb
|
87
|
+
has_rdoc: true
|
88
|
+
homepage: https://github.com/justinko/reverse-polish-calculator
|
89
|
+
licenses: []
|
90
|
+
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0"
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: "0"
|
108
|
+
requirements: []
|
109
|
+
|
110
|
+
rubyforge_project:
|
111
|
+
rubygems_version: 1.6.2
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: Reverse Polish Calculator
|
115
|
+
test_files:
|
116
|
+
- spec/acceptance/complex_expressions_spec.rb
|
117
|
+
- spec/acceptance/error_handling_spec.rb
|
118
|
+
- spec/acceptance/simple_arithmetic_spec.rb
|
119
|
+
- spec/acceptance/simple_trigonometric_spec.rb
|
120
|
+
- spec/spec_helper.rb
|
121
|
+
- spec/support/aruba.rb
|
122
|
+
- spec/support/string_ext.rb
|
123
|
+
- spec/unit/reverse-polish-calculator/errors_spec.rb
|
124
|
+
- spec/unit/reverse-polish-calculator/input_spec.rb
|
125
|
+
- spec/unit/reverse-polish-calculator/inputs_spec.rb
|
126
|
+
- spec/unit/reverse-polish-calculator/output_spec.rb
|
127
|
+
- spec/unit/reverse-polish-calculator/stack_spec.rb
|
128
|
+
- spec/unit/reverse-polish-calculator_spec.rb
|