keisan 0.8.0 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f2d556d5ef3e67015596fee5856e2fe0b27295b227f7d4edf8cb41c037aed98b
4
- data.tar.gz: c8c20ac6ba6a9ad27654931238a2dbafcbbbc509b58fd2a74161b7a38b3edaab
3
+ metadata.gz: 25f0cd7f7a5bd124a62c244a270bb4db0632fc0ce295d7f55fa25409eae66473
4
+ data.tar.gz: 5cdeae27276969608966b56891abe91fe8b2bddaef9f7ef3fdeb6a3fe6696176
5
5
  SHA512:
6
- metadata.gz: 9ccc5172adc0b5ebafabe3cd5846fb455ada6e1351c94deab4da5bfd38617c0e0692258e9384d760d25b88a899b46de1899b1688850bfac8ddcdd432091ddf50
7
- data.tar.gz: cb2ca195319a744f3ee9b56ef7df14d8dfcf36dbcafcbe1e675a858f232457d39cb3fe96d7f056a26746630d4a7f1c47a8fe6fc75a880683cd2120428a448ff6
6
+ metadata.gz: 32d761e97663ad54bc37d2e3894875068daa8567ae521dd877879a94f66417c752cc338eba7f1a06bbe23f2a1455fce7751690323fcf4948f243d8254c69f1b4
7
+ data.tar.gz: 6c62bfc43752fe4918022e0217227c4a31d1fae6225bf70d65bc61afb025dbef5af74597055b1216a4ef9d261252e2f2d9ac26467319e33c4c842a2764711053
data/.travis.yml CHANGED
@@ -1,7 +1,9 @@
1
1
  sudo: false
2
2
  language: ruby
3
+ before_install:
4
+ - gem install bundler
3
5
  rvm:
4
- - 2.3.6
5
- - 2.4.3
6
- - 2.5.0
7
- before_install: gem install bundler -v 1.16.1
6
+ - 2.4.9
7
+ - 2.5.7
8
+ - 2.6.5
9
+ - 2.7.0
data/README.md CHANGED
@@ -340,7 +340,7 @@ calculator.evaluate("[2, 3, 7, 11].has_element(11)")
340
340
 
341
341
  ##### Bitwise operations
342
342
 
343
- The basic bitwise operations, NOT `~`, OR `|`, XOR `^`, and AND `&` are also available for use
343
+ The basic bitwise operations, NOT `~`, OR `|`, XOR `^`, AND `&`, and left/right bitwise shifts (`<<` and `>>`) are also available for use
344
344
 
345
345
  ```ruby
346
346
  calculator = Keisan::Calculator.new
@@ -485,6 +485,7 @@ calculator.evaluate("puts x**2") # prints "25\n" to STDOUT
485
485
 
486
486
  #### Bitwise operators
487
487
  - `&`, `|`, `^`: bitwise **and**, **or**, **xor** operators
488
+ - `<<`, `>>` bitwise shift operators
488
489
  - `~`: unary bitwise not
489
490
 
490
491
  #### Indexing of arrays/hashes
data/keisan.gemspec CHANGED
@@ -21,10 +21,12 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.required_ruby_version = ">= 2.3.0"
23
23
 
24
- spec.add_development_dependency "coveralls"
25
- spec.add_development_dependency "bundler", "~> 1.14"
26
- spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_dependency "cmath", "~> 1.0"
25
+
26
+ spec.add_development_dependency "bundler", "~> 2.0"
27
+ spec.add_development_dependency "rake", "~> 13.0"
27
28
  spec.add_development_dependency "rspec", "~> 3.0"
28
29
  spec.add_development_dependency "pry"
29
30
  spec.add_development_dependency "pry-stack_explorer"
31
+ spec.add_development_dependency "simplecov"
30
32
  end
data/lib/keisan.rb CHANGED
@@ -37,6 +37,8 @@ require "keisan/ast/bitwise_operator"
37
37
  require "keisan/ast/bitwise_and"
38
38
  require "keisan/ast/bitwise_or"
39
39
  require "keisan/ast/bitwise_xor"
40
+ require "keisan/ast/bitwise_left_shift"
41
+ require "keisan/ast/bitwise_right_shift"
40
42
  require "keisan/ast/logical_operator"
41
43
  require "keisan/ast/logical_and"
42
44
  require "keisan/ast/logical_or"
@@ -78,10 +80,12 @@ require "keisan/tokens/assignment"
78
80
  require "keisan/tokens/arithmetic_operator"
79
81
  require "keisan/tokens/logical_operator"
80
82
  require "keisan/tokens/bitwise_operator"
83
+ require "keisan/tokens/bitwise_shift"
81
84
  require "keisan/tokens/word"
82
85
  require "keisan/tokens/line_separator"
83
86
  require "keisan/tokens/unknown"
84
87
 
88
+ require "keisan/string_and_group_parser"
85
89
  require "keisan/tokenizer"
86
90
 
87
91
  require "keisan/parsing/component"
@@ -128,6 +132,8 @@ require "keisan/parsing/bitwise_or"
128
132
  require "keisan/parsing/bitwise_xor"
129
133
  require "keisan/parsing/bitwise_not"
130
134
  require "keisan/parsing/bitwise_not_not"
135
+ require "keisan/parsing/bitwise_left_shift"
136
+ require "keisan/parsing/bitwise_right_shift"
131
137
  require "keisan/parsing/logical_operator"
132
138
  require "keisan/parsing/logical_less_than"
133
139
  require "keisan/parsing/logical_greater_than"
@@ -0,0 +1,17 @@
1
+ module Keisan
2
+ module AST
3
+ class BitwiseLeftShift < BitwiseOperator
4
+ def self.symbol
5
+ :<<
6
+ end
7
+
8
+ def blank_value
9
+ 0
10
+ end
11
+
12
+ def evaluate(context = nil)
13
+ children[1..-1].inject(children.first.evaluate(context)) {|total, child| total << child.evaluate(context)}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ module Keisan
2
+ module AST
3
+ class BitwiseRightShift < BitwiseOperator
4
+ def self.symbol
5
+ :>>
6
+ end
7
+
8
+ def blank_value
9
+ 0
10
+ end
11
+
12
+ def evaluate(context = nil)
13
+ children[1..-1].inject(children.first.evaluate(context)) {|total, child| total >> child.evaluate(context)}
14
+ end
15
+ end
16
+ end
17
+ end
@@ -45,10 +45,18 @@ module Keisan
45
45
  raise Exceptions::NonDifferentiableError.new
46
46
  end
47
47
 
48
+ def differentiated(variable, context = nil)
49
+ deep_dup.differentiate(variable, context)
50
+ end
51
+
48
52
  def replace(variable, replacement)
49
53
  self
50
54
  end
51
55
 
56
+ def replaced(variable, replacement)
57
+ deep_dup.replace(variable, replacement)
58
+ end
59
+
52
60
  def coerce(other)
53
61
  [other.to_node, self]
54
62
  end
@@ -132,6 +140,14 @@ module Keisan
132
140
  BitwiseOr.new([self, other.to_node])
133
141
  end
134
142
 
143
+ def <<(other)
144
+ BitwiseLeftShift.new([self, other.to_node])
145
+ end
146
+
147
+ def >>(other)
148
+ BitwiseRightShift.new([self, other.to_node])
149
+ end
150
+
135
151
  def >(other)
136
152
  LogicalGreaterThan.new([self, other.to_node])
137
153
  end
@@ -111,6 +111,26 @@ module Keisan
111
111
  end
112
112
  end
113
113
 
114
+ def <<(other)
115
+ other = other.to_node
116
+ case other
117
+ when Number
118
+ Number.new(value << other.value)
119
+ else
120
+ super
121
+ end
122
+ end
123
+
124
+ def >>(other)
125
+ other = other.to_node
126
+ case other
127
+ when Number
128
+ Number.new(value >> other.value)
129
+ else
130
+ super
131
+ end
132
+ end
133
+
114
134
  def >(other)
115
135
  other = other.to_node
116
136
  case other
@@ -13,6 +13,8 @@ module Keisan
13
13
  "%": [2, 85, :left], # Modulo
14
14
  "+": [2, 80, :left], # Plus
15
15
  # "-": [2, 80, :left], # Minus
16
+ "<<": [2, 75, :left], # Bitwise left shift
17
+ ">>": [2, 75, :left], # Bitwise right shift
16
18
  "&": [2, 70, :left], # Bitwise and
17
19
  "^": [2, 65, :left], # Bitwise xor
18
20
  "|": [2, 65, :left], # Bitwise or
@@ -19,7 +19,7 @@ module Keisan
19
19
  @children = [child.simplify(context)]
20
20
  case child
21
21
  when Number
22
- Number.new(Rational(1,child.value(context))).simplify(context)
22
+ Number.new(child.value**-1)
23
23
  else
24
24
  (child ** -1).simplify(context)
25
25
  end
@@ -13,7 +13,13 @@ module Keisan
13
13
 
14
14
  def value(context = nil)
15
15
  context ||= Context.new
16
- variable_node_from_context(context).value(context)
16
+ node = variable_node_from_context(context)
17
+ case node
18
+ when Variable
19
+ node
20
+ else
21
+ node.value(context)
22
+ end
17
23
  end
18
24
 
19
25
  def unbound_variables(context = nil)
@@ -78,9 +84,7 @@ module Keisan
78
84
 
79
85
  def variable_node_from_context(context)
80
86
  variable = context.variable(name)
81
- if variable.is_a?(Cell)
82
- variable = variable.node
83
- end
87
+ variable = variable.node if variable.is_a?(Cell)
84
88
  variable
85
89
  end
86
90
  end
@@ -4,7 +4,9 @@ module Keisan
4
4
  module Functions
5
5
  class CMathFunction < MathFunction
6
6
  def initialize(name, proc_function = nil)
7
- super(name, proc_function || Proc.new {|arg| CMath.send(name, arg)})
7
+ super(name, proc_function || Proc.new {|arg|
8
+ CMath.send(name, arg)
9
+ })
8
10
  end
9
11
  end
10
12
  end
@@ -5,7 +5,11 @@ module Keisan
5
5
 
6
6
  def initialize(name, arguments, expression, transient_definitions)
7
7
  super(name, arguments.count)
8
- @expression = expression.deep_dup
8
+ if expression.is_a?(::String)
9
+ @expression = AST::parse(expression)
10
+ else
11
+ @expression = expression.deep_dup
12
+ end
9
13
  @arguments = arguments
10
14
  @transient_definitions = transient_definitions
11
15
  end
@@ -70,17 +74,20 @@ module Keisan
70
74
 
71
75
  local = local_context_for(context)
72
76
 
73
- # expression.differentiate(variable, context)
74
-
75
- argument_values = ast_function.children.map {|child| child.evaluate(local)}
77
+ argument_values = ast_function.children.map {|child| child.evaluated(local)}
76
78
 
77
79
  argument_derivatives = ast_function.children.map do |child|
78
- child.differentiate(variable, context)
80
+ child.differentiated(variable, context)
79
81
  end
80
82
 
83
+ partial_derivatives = calculate_partial_derivatives(context)
84
+
81
85
  AST::Plus.new(
82
86
  argument_derivatives.map.with_index {|argument_derivative, i|
83
- partial_derivative = partial_derivatives[i].replace(argument_variables[i], argument_values[i])
87
+ partial_derivative = partial_derivatives[i]
88
+ argument_variables.each.with_index {|argument_variable, j|
89
+ partial_derivative = partial_derivative.replaced(argument_variable, argument_values[j])
90
+ }
84
91
  AST::Times.new([argument_derivative, partial_derivative])
85
92
  }
86
93
  )
@@ -92,9 +99,9 @@ module Keisan
92
99
  @argument_variables ||= arguments.map {|argument| AST::Variable.new(argument)}
93
100
  end
94
101
 
95
- def partial_derivatives
96
- @partial_derivatives ||= argument_variables.map.with_index do |variable, i|
97
- partial_derivative = expression.differentiate(variable)
102
+ def calculate_partial_derivatives(context)
103
+ argument_variables.map.with_index do |variable, i|
104
+ partial_derivative = expression.differentiated(variable, context)
98
105
  end
99
106
  end
100
107
 
@@ -28,7 +28,7 @@ module Keisan
28
28
 
29
29
  ast_function.instance_variable_set(
30
30
  :@children,
31
- ast_function.children.map {|child| child.evaluate(context).to_node}
31
+ ast_function.children.map {|child| child.simplify(context).to_node}
32
32
  )
33
33
 
34
34
  if ast_function.children.all? {|child| child.well_defined?(context)}
@@ -44,7 +44,7 @@ module Keisan
44
44
 
45
45
  ast_function.instance_variable_set(
46
46
  :@children,
47
- ast_function.children.map {|child| child.evaluate(context)}
47
+ ast_function.children.map {|child| child.simplify(context)}
48
48
  )
49
49
 
50
50
  if ast_function.children.all? {|child| child.is_a?(AST::ConstantLiteral)}
@@ -10,19 +10,19 @@ module Keisan
10
10
  evaluate(ast_function, context).value(context)
11
11
  end
12
12
 
13
- def evaluate(ast_function, context = nil)
13
+ def simplify(ast_function, context = nil)
14
14
  context ||= Context.new
15
15
  expression, variable, replacement = expression_variable_replacement(ast_function)
16
16
 
17
- expression = expression.evaluate(context)
18
- replacement = replacement.evaluate(context)
17
+ expression = expression.simplify(context)
18
+ replacement = replacement.simplify(context)
19
19
 
20
- expression.replace(variable, replacement).evaluate(context)
20
+ expression.replace(variable, replacement).simplify(context)
21
21
  end
22
22
 
23
- def simplify(ast_function, context = nil)
23
+ def evaluate(ast_function, context = nil)
24
24
  context ||= Context.new
25
- evaluate(ast_function, context).simplify(context)
25
+ simplify(ast_function, context).evaluate(context)
26
26
  end
27
27
 
28
28
  private
data/lib/keisan/parser.rb CHANGED
@@ -241,6 +241,8 @@ module Keisan
241
241
  :"&" => Parsing::BitwiseAnd,
242
242
  :"|" => Parsing::BitwiseOr,
243
243
  :"^" => Parsing::BitwiseXor,
244
+ :<< => Parsing::BitwiseLeftShift,
245
+ :>> => Parsing::BitwiseRightShift,
244
246
  :"==" => Parsing::LogicalEqual,
245
247
  :"!=" => Parsing::LogicalNotEqual,
246
248
  :"&&" => Parsing::LogicalAnd,
@@ -0,0 +1,9 @@
1
+ module Keisan
2
+ module Parsing
3
+ class BitwiseLeftShift < BitwiseOperator
4
+ def node_class
5
+ AST::BitwiseLeftShift
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Keisan
2
+ module Parsing
3
+ class BitwiseRightShift < BitwiseOperator
4
+ def node_class
5
+ AST::BitwiseRightShift
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,193 @@
1
+ module Keisan
2
+ class StringAndGroupParser
3
+ class Portion
4
+ attr_reader :start_index, :end_index
5
+
6
+ def initialize(start_index)
7
+ @start_index = start_index
8
+ end
9
+ end
10
+
11
+ class StringPortion < Portion
12
+ attr_reader :string
13
+
14
+ def initialize(expression, start_index)
15
+ super(start_index)
16
+
17
+ @string = expression[start_index]
18
+ @end_index = start_index + 1
19
+
20
+ while @end_index < expression.size
21
+ if expression[@end_index] == quote_type
22
+ @string << quote_type
23
+ @end_index += 1
24
+ # Successfully parsed the string
25
+ return
26
+ end
27
+
28
+ n, c = process_next_character(expression, @end_index)
29
+ @string << c
30
+ @end_index += n
31
+ end
32
+
33
+ raise Keisan::Exceptions::TokenizingError.new("Tokenizing error, no closing quote #{quote_type}")
34
+ end
35
+
36
+ def size
37
+ string.size
38
+ end
39
+
40
+ def to_s
41
+ string
42
+ end
43
+
44
+ private
45
+
46
+ # Returns number of processed input characters, and the output character
47
+ def process_next_character(expression, index)
48
+ # escape character
49
+ if expression[index] == "\\"
50
+ return [2, escaped_character(expression[index + 1])]
51
+ else
52
+ return [1, expression[index]]
53
+ end
54
+ end
55
+
56
+ def quote_type
57
+ @string[0]
58
+ end
59
+
60
+ def escaped_character(character)
61
+ case character
62
+ when "\\", '"', "'"
63
+ character
64
+ when "a"
65
+ "\a"
66
+ when "b"
67
+ "\b"
68
+ when "r"
69
+ "\r"
70
+ when "n"
71
+ "\n"
72
+ when "s"
73
+ "\s"
74
+ when "t"
75
+ "\t"
76
+ else
77
+ raise Keisan::Exceptions::TokenizingError.new("Tokenizing error, unknown escape character: \"\\#{character}\"")
78
+ end
79
+ end
80
+ end
81
+
82
+ class GroupPortion < Portion
83
+ attr_reader :opening_brace, :closing_brace ,:portions, :size
84
+
85
+ OPENING_TO_CLOSING_BRACE = {
86
+ "(" => ")",
87
+ "{" => "}",
88
+ "[" => "]",
89
+ }
90
+
91
+ def initialize(expression, start_index)
92
+ super(start_index)
93
+
94
+ case expression[start_index]
95
+ when OPEN_GROUP_REGEX
96
+ @opening_brace = expression[start_index]
97
+ else
98
+ raise Keisan::Exceptions::TokenizingError.new("Internal error, GroupPortion did not start with brace")
99
+ end
100
+
101
+ @closing_brace = OPENING_TO_CLOSING_BRACE[opening_brace]
102
+
103
+ parser = StringAndGroupParser.new(expression, start_index: start_index + 1, ending_character: closing_brace)
104
+ @portions = parser.portions
105
+ @size = parser.size + 2
106
+
107
+ if start_index + size > expression.size || expression[start_index + size - 1] != closing_brace
108
+ raise Keisan::Exceptions::TokenizingError.new("Tokenizing error, group with opening brace #{opening_brace} did not have closing brace")
109
+ end
110
+ end
111
+
112
+ def to_s
113
+ opening_brace + portions.map(&:to_s).join + closing_brace
114
+ end
115
+ end
116
+
117
+ class OtherPortion < Portion
118
+ attr_reader :string
119
+
120
+ def initialize(expression, start_index)
121
+ super(start_index)
122
+
123
+ case expression[start_index]
124
+ when STRING_CHARACTER_REGEX, OPEN_GROUP_REGEX, CLOSED_GROUP_REGEX
125
+ raise Keisan::Exceptions::TokenizingError.new("Internal error, OtherPortion should not have string/braces at start")
126
+ else
127
+ index = start_index + 1
128
+ end
129
+
130
+ while index < expression.size
131
+ case expression[index]
132
+ when STRING_CHARACTER_REGEX, OPEN_GROUP_REGEX, CLOSED_GROUP_REGEX
133
+ break
134
+ else
135
+ index += 1
136
+ end
137
+ end
138
+
139
+ @end_index = index
140
+ @string = expression[start_index...end_index]
141
+ end
142
+
143
+ def size
144
+ string.size
145
+ end
146
+
147
+ def to_s
148
+ string
149
+ end
150
+ end
151
+
152
+ # An ordered array of "portions", which
153
+ attr_reader :portions, :size
154
+
155
+ STRING_CHARACTER_REGEX = /["']/
156
+ OPEN_GROUP_REGEX = /[\(\{\[]/
157
+ CLOSED_GROUP_REGEX = /[\)\}\]]/
158
+
159
+ # Ending character is used as a second ending condition besides expression size
160
+ def initialize(expression, start_index: 0, ending_character: nil)
161
+ index = start_index
162
+ @portions = []
163
+
164
+ while index < expression.size && (ending_character.nil? || expression[index] != ending_character)
165
+ case expression[index]
166
+ when STRING_CHARACTER_REGEX
167
+ portion = StringPortion.new(expression, index)
168
+ index = portion.end_index
169
+ @portions << portion
170
+
171
+ when OPEN_GROUP_REGEX
172
+ portion = GroupPortion.new(expression, index)
173
+ index += portion.size
174
+ @portions << portion
175
+
176
+ when CLOSED_GROUP_REGEX
177
+ raise Keisan::Exceptions::TokenizingError.new("Tokenizing error, unexpected closing brace #{expression[start_index]}")
178
+
179
+ else
180
+ portion = OtherPortion.new(expression, index)
181
+ index += portion.size
182
+ @portions << portion
183
+ end
184
+ end
185
+
186
+ @size = index - start_index
187
+ end
188
+
189
+ def to_s
190
+ portions.map(&:to_s).join
191
+ end
192
+ end
193
+ end
@@ -1,13 +1,12 @@
1
1
  module Keisan
2
2
  class Tokenizer
3
3
  TOKEN_CLASSES = [
4
- Tokens::Group,
5
- Tokens::String,
6
4
  Tokens::Null,
7
5
  Tokens::Boolean,
8
6
  Tokens::Word,
9
7
  Tokens::Number,
10
8
  Tokens::Assignment,
9
+ Tokens::BitwiseShift,
11
10
  Tokens::LogicalOperator,
12
11
  Tokens::ArithmeticOperator,
13
12
  Tokens::BitwiseOperator,
@@ -26,8 +25,22 @@ module Keisan
26
25
 
27
26
  def initialize(expression)
28
27
  @expression = self.class.normalize_expression(expression)
29
- @scan = @expression.scan(TOKEN_REGEX)
30
- @tokens = tokenize!
28
+
29
+ portions = StringAndGroupParser.new(@expression).portions
30
+
31
+ @tokens = portions.inject([]) do |tokens, portion|
32
+ case portion
33
+ when StringAndGroupParser::StringPortion
34
+ tokens << Tokens::String.new(portion.to_s)
35
+ when StringAndGroupParser::GroupPortion
36
+ tokens << Tokens::Group.new(portion.to_s)
37
+ when StringAndGroupParser::OtherPortion
38
+ scan = portion.to_s.scan(TOKEN_REGEX)
39
+ tokens += tokenize!(scan)
40
+ end
41
+
42
+ tokens
43
+ end
31
44
  end
32
45
 
33
46
  def self.normalize_expression(expression)
@@ -45,8 +58,8 @@ module Keisan
45
58
  expression.gsub(/#[^;]*/, "")
46
59
  end
47
60
 
48
- def tokenize!
49
- @scan.map do |scan_result|
61
+ def tokenize!(scan)
62
+ scan.map do |scan_result|
50
63
  i = scan_result.find_index {|token| !token.nil?}
51
64
  token_string = scan_result[i]
52
65
  token = TOKEN_CLASSES[i].new(token_string)
@@ -13,7 +13,9 @@ module Keisan
13
13
  \% |
14
14
  \& |
15
15
  \| |
16
- \^
16
+ \^ |
17
+ \<\< |
18
+ \>\>
17
19
  )?
18
20
  \=
19
21
  (?!\=) # negative lookahead to prevent matching ==
@@ -0,0 +1,23 @@
1
+ module Keisan
2
+ module Tokens
3
+ class BitwiseShift < Operator
4
+ LEFT_SHIFT = /(?:<<)/
5
+ RIGHT_SHIFT = /(?:>>)/
6
+
7
+ REGEX = /(#{LEFT_SHIFT}|#{RIGHT_SHIFT})/
8
+
9
+ def self.regex
10
+ REGEX
11
+ end
12
+
13
+ def operator_type
14
+ case string
15
+ when LEFT_SHIFT
16
+ :<<
17
+ when RIGHT_SHIFT
18
+ :>>
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,19 +1,13 @@
1
1
  module Keisan
2
2
  module Tokens
3
3
  class Group < Token
4
- REGEX = /(\((?:[^\[\]\(\)\{\}]*+\g<1>*+)*+\)|\[(?:[^\[\]\(\)\{\}]*+\g<1>*+)*+\]|\{(?:[^\[\]\(\)\{\}]*+\g<1>*+)*+\})/
5
-
6
4
  attr_reader :sub_tokens
7
5
 
8
6
  def initialize(string)
9
- super
7
+ @string = string
10
8
  @sub_tokens = Tokenizer.new(string[1...-1]).tokens
11
9
  end
12
10
 
13
- def self.regex
14
- REGEX
15
- end
16
-
17
11
  # Either :round, :square
18
12
  def group_type
19
13
  case string[0]
@@ -1,10 +1,8 @@
1
1
  module Keisan
2
2
  module Tokens
3
3
  class String < Token
4
- REGEX = /(\"[^\"]*\"|\'[^\']*\')/
5
-
6
- def self.regex
7
- REGEX
4
+ def initialize(string)
5
+ @string = string
8
6
  end
9
7
 
10
8
  def value
@@ -1,3 +1,3 @@
1
1
  module Keisan
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.1"
3
3
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keisan
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher Locke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-23 00:00:00.000000000 Z
11
+ date: 2020-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: coveralls
14
+ name: cmath
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
19
+ version: '1.0'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.14'
33
+ version: '2.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.14'
40
+ version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  description: A library for parsing equations into an abstract syntax tree for evaluation
98
112
  email:
99
113
  - project.eutopia@gmail.com
@@ -117,8 +131,10 @@ files:
117
131
  - lib/keisan/ast/arithmetic_operator.rb
118
132
  - lib/keisan/ast/assignment.rb
119
133
  - lib/keisan/ast/bitwise_and.rb
134
+ - lib/keisan/ast/bitwise_left_shift.rb
120
135
  - lib/keisan/ast/bitwise_operator.rb
121
136
  - lib/keisan/ast/bitwise_or.rb
137
+ - lib/keisan/ast/bitwise_right_shift.rb
122
138
  - lib/keisan/ast/bitwise_xor.rb
123
139
  - lib/keisan/ast/block.rb
124
140
  - lib/keisan/ast/boolean.rb
@@ -219,10 +235,12 @@ files:
219
235
  - lib/keisan/parsing/arithmetic_operator.rb
220
236
  - lib/keisan/parsing/assignment.rb
221
237
  - lib/keisan/parsing/bitwise_and.rb
238
+ - lib/keisan/parsing/bitwise_left_shift.rb
222
239
  - lib/keisan/parsing/bitwise_not.rb
223
240
  - lib/keisan/parsing/bitwise_not_not.rb
224
241
  - lib/keisan/parsing/bitwise_operator.rb
225
242
  - lib/keisan/parsing/bitwise_or.rb
243
+ - lib/keisan/parsing/bitwise_right_shift.rb
226
244
  - lib/keisan/parsing/bitwise_xor.rb
227
245
  - lib/keisan/parsing/boolean.rb
228
246
  - lib/keisan/parsing/component.rb
@@ -266,11 +284,13 @@ files:
266
284
  - lib/keisan/parsing/unary_plus.rb
267
285
  - lib/keisan/parsing/variable.rb
268
286
  - lib/keisan/repl.rb
287
+ - lib/keisan/string_and_group_parser.rb
269
288
  - lib/keisan/token.rb
270
289
  - lib/keisan/tokenizer.rb
271
290
  - lib/keisan/tokens/arithmetic_operator.rb
272
291
  - lib/keisan/tokens/assignment.rb
273
292
  - lib/keisan/tokens/bitwise_operator.rb
293
+ - lib/keisan/tokens/bitwise_shift.rb
274
294
  - lib/keisan/tokens/boolean.rb
275
295
  - lib/keisan/tokens/colon.rb
276
296
  - lib/keisan/tokens/comma.rb
@@ -308,8 +328,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
308
328
  - !ruby/object:Gem::Version
309
329
  version: '0'
310
330
  requirements: []
311
- rubyforge_project:
312
- rubygems_version: 2.7.7
331
+ rubygems_version: 3.0.3
313
332
  signing_key:
314
333
  specification_version: 4
315
334
  summary: An equation parser and evaluator