rpn-calculator 0.3.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67b5ea07408d666e0b0b1f0e564b989773f7e095
4
- data.tar.gz: 37623c7573e54025ff442b97c7c024b6ea09a9e7
3
+ metadata.gz: 72f8ad5a6504d98bb59d0bfcbac6e918dee44743
4
+ data.tar.gz: e34bb42f596a78a62ee1c94e570c89bc9e3dbd64
5
5
  SHA512:
6
- metadata.gz: e84986323f02c63a8dfa0cac0a144ff0ddb4916a83489a8f91088d2e0dbf24bd3d857749f1d8338bb9e971526f6c8b351b4f36851b855cee9c02a08b6ec43547
7
- data.tar.gz: eacb1e523c7b9d4d98c4468ae8982ba251f19409c0a9256859be731ede0a108fba549c3b22e44cfea3cf36eb2edb0643993827ab6032e9c293b1099220721d08
6
+ metadata.gz: 6f1355c0cd90e80345918f66771eb4311b8a983e1fee0bb09ffdbebfa75623cf337f24f4e410424d434f5d69daa2b5d17e300428c9908e611d5750689391acae
7
+ data.tar.gz: 55a42ddf85c9efbbf32b34e67acd1bc35d60d3abd4d1dab846e802512e44a0e006d0d35d061eebe85698d6260fe976c6d9a736f606096003b0c287f1bcd06890
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'rpn-calculator'
4
4
 
5
- RPNCalculator.start
5
+ RPNCalculator.start_cli_tool
@@ -10,20 +10,24 @@ module RPNCalculator
10
10
  '/' => Operation::Division
11
11
  }.freeze
12
12
  ALLOWED_OPERATORS = OPERATION_CLASSES.keys.freeze
13
- INVALID_ARGUMENTS_REGEX = /[^\d\s\+\-\/\*\.]/.freeze
13
+ INVALID_ARGUMENTS_REGEX = /[^\d\s\.#{Regexp.quote(ALLOWED_OPERATORS.join)}]/
14
+ OPERATION_PROCESSOR = OperationProcessor.new(OPERATION_CLASSES).freeze
15
+ INPUT_PROCESSOR = InputProcessor.new(
16
+ OPERATION_PROCESSOR,
17
+ Input::Validator.new(INVALID_ARGUMENTS_REGEX),
18
+ Input::Parser.new(ALLOWED_OPERATORS)
19
+ ).freeze
14
20
 
15
21
  module_function
16
22
 
17
- def start
18
- operation_processor = OperationProcessor.new(
19
- OPERATION_CLASSES,
20
- Input::Validator.new(INVALID_ARGUMENTS_REGEX),
21
- Input::Parser.new(ALLOWED_OPERATORS)
22
- )
23
-
23
+ def start_cli_tool
24
24
  # Here is where we could read and write to another input
25
25
  # using stdin and stdout by default
26
- processor = IoProcessor.new(IoInterface::Standard.new, operation_processor)
26
+ processor = CLI.new(IoInterface::Standard.new, INPUT_PROCESSOR)
27
27
  processor.start
28
28
  end
29
+
30
+ def calculate(expression)
31
+ INPUT_PROCESSOR.process(expression)
32
+ end
29
33
  end
@@ -1,14 +1,14 @@
1
1
  module RPNCalculator
2
- class IoProcessor
3
- def initialize(io_interface, operation_processor)
2
+ class CLI
3
+ def initialize(io_interface, input_processor)
4
4
  @io_interface = io_interface
5
5
  @input_stack = []
6
- @operation_processor = operation_processor
6
+ @input_processor = input_processor
7
7
  end
8
8
 
9
9
  def start
10
- while (input = io_interface.read_input)
11
- processor_result = operation_processor.process(input_stack, input)
10
+ while (input_expression = io_interface.read_input)
11
+ processor_result = input_processor.process(input_expression, input_stack)
12
12
 
13
13
  if processor_result.valid?
14
14
  print_result_array(processor_result.result)
@@ -21,7 +21,7 @@ module RPNCalculator
21
21
 
22
22
  private
23
23
 
24
- attr_reader :io_interface, :operation_processor, :input_stack
24
+ attr_reader :io_interface, :input_processor, :input_stack
25
25
 
26
26
  def print_result_array(result)
27
27
  io_interface.display_output(result.join(' '))
@@ -18,19 +18,19 @@ module RPNCalculator
18
18
  attr_reader :allowed_operators
19
19
 
20
20
  def input_without_whitespace(split_string)
21
- split_string.select { |e| e!= ' ' }
21
+ split_string.reject { |e| e == ' ' }
22
22
  end
23
23
 
24
24
  def parsed_input_errors(parsed_input)
25
25
  parsed_input.inject([]) do |result, element|
26
- result << element unless allowed_operators.include?(element) || is_number?(element)
26
+ result << element unless allowed_operators.include?(element) || number?(element)
27
27
  result
28
28
  end
29
29
  end
30
30
 
31
31
  def join_consecutive_numbers(split_string)
32
32
  split_string.each_with_index.inject([]) do |result, (element, index)|
33
- if index == 0 || any_operator?([split_string[index - 1], element])
33
+ if index.zero? || any_operator?([split_string[index - 1], element])
34
34
  result << element
35
35
  else
36
36
  result[-1] += element
@@ -40,14 +40,14 @@ module RPNCalculator
40
40
  end
41
41
 
42
42
  def any_operator?(elements)
43
- elements.any? { |e| !is_number_or_period?(e) }
43
+ elements.any? { |e| !number_or_period?(e) }
44
44
  end
45
45
 
46
- def is_number_or_period?(number_string)
47
- number_string == '.' || is_number?(number_string)
46
+ def number_or_period?(number_string)
47
+ number_string == '.' || number?(number_string)
48
48
  end
49
49
 
50
- def is_number?(number_string)
50
+ def number?(number_string)
51
51
  true if Float(number_string)
52
52
  rescue ArgumentError
53
53
  false
@@ -0,0 +1,32 @@
1
+ module RPNCalculator
2
+ class InputProcessor
3
+ def initialize(operation_processor, input_validator, input_parser)
4
+ @input_validator = input_validator
5
+ @input_parser = input_parser
6
+ @operation_processor = operation_processor
7
+ end
8
+
9
+ def process(input_expression, previous_operations = [])
10
+ validator_result = input_validator.validate(input_expression)
11
+ return invalid_processor_result(validator_result) unless validator_result.valid?
12
+
13
+ parser_result = input_parser.parse(input_expression)
14
+ return invalid_processor_result(parser_result) unless parser_result.valid?
15
+
16
+ operation_result = operation_processor.process(
17
+ previous_operations + parser_result.result
18
+ )
19
+ return invalid_processor_result(operation_result) unless operation_result.valid?
20
+
21
+ Result::Processor.new(operation_result.result)
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :input_validator, :input_parser, :operation_processor
27
+
28
+ def invalid_processor_result(result)
29
+ Result::Processor.new([], result.error)
30
+ end
31
+ end
32
+ end
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:+))
9
+ Result::Operation.new(operation_string, operands.reduce(&:+))
10
10
  end
11
11
 
12
12
  private
@@ -21,10 +21,6 @@ module RPNCalculator
21
21
  operands.size == 2
22
22
  end
23
23
 
24
- def float_operands
25
- operands.map { |operator| Float(operator) }
26
- end
27
-
28
24
  def invalid_operation_result(operation)
29
25
  Result::Operation.new(operation, [], operands)
30
26
  end
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:/))
9
+ Result::Operation.new(operation_string, operands.reduce(&:/))
10
10
  end
11
11
 
12
12
  private
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:*))
9
+ Result::Operation.new(operation_string, operands.reduce(&:*))
10
10
  end
11
11
 
12
12
  private
@@ -6,7 +6,7 @@ module RPNCalculator
6
6
  def result
7
7
  return invalid_operation_result(operation_string) unless valid?
8
8
 
9
- Result::Operation.new(operation_string, float_operands.reduce(&:-))
9
+ Result::Operation.new(operation_string, operands.reduce(&:-))
10
10
  end
11
11
 
12
12
  private
@@ -1,44 +1,34 @@
1
1
  module RPNCalculator
2
2
  class OperationProcessor
3
- def initialize(operation_classes, input_validator, input_parser)
4
- @input_validator = input_validator
5
- @input_parser = input_parser
3
+ def initialize(operation_classes)
6
4
  @operation_classes = operation_classes
7
5
  @operation_symbols = @operation_classes.keys
8
6
  end
9
7
 
10
- # Refator needed, process should receive parsed input
11
- def process(previous_operations, input)
12
- validator_result = input_validator.validate(input)
13
- return Result::Processor.new([], validator_result.error) unless validator_result.valid?
14
-
15
- parser_result = input_parser.parse(input)
16
- return Result::Processor.new([], parser_result.error) unless parser_result.valid?
17
-
18
- process_operations(previous_operations + parser_result.parsed_elements)
19
- end
20
-
21
- private
22
-
23
- attr_reader :input_validator, :input_parser, :operation_classes, :operation_symbols
24
-
25
- def process_operations(operations)
26
- result_stack = operations.inject([]) do |stack, element|
8
+ def process(parsed_expression)
9
+ result_stack = parsed_expression.inject([]) do |stack, element|
27
10
  if operation_symbols.include?(element)
28
- result = operation_classes.fetch(element)
29
- .operate([stack.pop, stack.pop].reverse)
11
+ result = operation_classes.fetch(element).operate(stack.pop(2))
30
12
  return invalid_processor_result(result) unless result.valid?
31
13
  stack.push(result.result)
32
14
  else
33
- stack.push(element)
15
+ stack.push(as_float(element))
34
16
  end
35
17
  stack
36
18
  end
37
19
  Result::Processor.new(result_stack)
38
20
  end
39
21
 
22
+ private
23
+
24
+ attr_reader :operation_classes, :operation_symbols
25
+
40
26
  def invalid_processor_result(result)
41
27
  Result::Processor.new([], result.error)
42
28
  end
29
+
30
+ def as_float(num_string)
31
+ Float(num_string)
32
+ end
43
33
  end
44
34
  end
@@ -0,0 +1,21 @@
1
+ module RPNCalculator
2
+ module Result
3
+ class Input
4
+ def initialize
5
+ raise 'Can not instantiate abstract class'
6
+ end
7
+
8
+ def valid?
9
+ raise 'must implement in subclass'
10
+ end
11
+
12
+ def error
13
+ raise 'must implement in subclass'
14
+ end
15
+
16
+ def result
17
+ raise 'must implement in subclass'
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,6 +1,8 @@
1
+ require 'rpn-calculator/result/input'
2
+
1
3
  module RPNCalculator
2
4
  module Result
3
- class Parser
5
+ class Parser < Input
4
6
  def initialize(parsed_elements = [], invalid_elements = [])
5
7
  @parsed_elements = parsed_elements
6
8
  @invalid_elements = invalid_elements
@@ -14,10 +16,14 @@ module RPNCalculator
14
16
  "Invalid operators or numbers: #{invalid_element_list}" unless valid?
15
17
  end
16
18
 
17
- attr_reader :parsed_elements, :invalid_elements
19
+ def result
20
+ @parsed_elements
21
+ end
18
22
 
19
23
  private
20
24
 
25
+ attr_reader :invalid_elements
26
+
21
27
  def invalid_element_list
22
28
  invalid_elements.join(', ')
23
29
  end
@@ -1,6 +1,8 @@
1
+ require 'rpn-calculator/result/input'
2
+
1
3
  module RPNCalculator
2
4
  module Result
3
- class Processor
5
+ class Processor < Input
4
6
  def initialize(result = [], error = nil)
5
7
  @result = result
6
8
  @error = error
@@ -1,6 +1,8 @@
1
+ require 'rpn-calculator/result/input'
2
+
1
3
  module RPNCalculator
2
4
  module Result
3
- class Validator
5
+ class Validator < Input
4
6
  def initialize(invalid_characters = [])
5
7
  @invalid_characters = invalid_characters
6
8
  end
@@ -13,6 +15,10 @@ module RPNCalculator
13
15
  "Invalid characters: #{invalid_character_list}" unless valid?
14
16
  end
15
17
 
18
+ def result
19
+ []
20
+ end
21
+
16
22
  private
17
23
 
18
24
  attr_reader :invalid_characters
@@ -1,3 +1,3 @@
1
1
  module RPNCalculator
2
- VERSION = '0.3.0'.freeze
2
+ VERSION = '0.4.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rpn-calculator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mario Celi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-29 00:00:00.000000000 Z
11
+ date: 2017-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -34,17 +34,19 @@ extra_rdoc_files: []
34
34
  files:
35
35
  - bin/rpn-calculator
36
36
  - lib/rpn-calculator.rb
37
+ - lib/rpn-calculator/cli.rb
37
38
  - lib/rpn-calculator/input/parser.rb
38
39
  - lib/rpn-calculator/input/validator.rb
40
+ - lib/rpn-calculator/input_processor.rb
39
41
  - lib/rpn-calculator/io_interface/abstract.rb
40
42
  - lib/rpn-calculator/io_interface/standard.rb
41
- - lib/rpn-calculator/io_processor.rb
42
43
  - lib/rpn-calculator/operation/addition.rb
43
44
  - lib/rpn-calculator/operation/base.rb
44
45
  - lib/rpn-calculator/operation/division.rb
45
46
  - lib/rpn-calculator/operation/multiplication.rb
46
47
  - lib/rpn-calculator/operation/subtraction.rb
47
48
  - lib/rpn-calculator/operation_processor.rb
49
+ - lib/rpn-calculator/result/input.rb
48
50
  - lib/rpn-calculator/result/operation.rb
49
51
  - lib/rpn-calculator/result/parser.rb
50
52
  - lib/rpn-calculator/result/processor.rb
@@ -62,7 +64,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
62
64
  requirements:
63
65
  - - ">="
64
66
  - !ruby/object:Gem::Version
65
- version: '0'
67
+ version: 1.9.3
66
68
  required_rubygems_version: !ruby/object:Gem::Requirement
67
69
  requirements:
68
70
  - - ">="