keisan 0.2.1 → 0.3.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 +4 -4
- data/README.md +92 -0
- data/lib/keisan.rb +12 -0
- data/lib/keisan/ast/bitwise_and.rb +1 -5
- data/lib/keisan/ast/bitwise_or.rb +1 -5
- data/lib/keisan/ast/bitwise_xor.rb +1 -5
- data/lib/keisan/ast/builder.rb +57 -22
- data/lib/keisan/ast/exponent.rb +1 -5
- data/lib/keisan/ast/function.rb +50 -1
- data/lib/keisan/ast/logical_and.rb +1 -5
- data/lib/keisan/ast/logical_equal.rb +18 -0
- data/lib/keisan/ast/logical_greater_than.rb +4 -4
- data/lib/keisan/ast/logical_greater_than_or_equal_to.rb +4 -4
- data/lib/keisan/ast/logical_less_than.rb +4 -4
- data/lib/keisan/ast/logical_less_than_or_equal_to.rb +4 -4
- data/lib/keisan/ast/logical_not_equal.rb +18 -0
- data/lib/keisan/ast/logical_or.rb +1 -5
- data/lib/keisan/ast/modulo.rb +18 -0
- data/lib/keisan/ast/node.rb +26 -0
- data/lib/keisan/ast/operator.rb +9 -2
- data/lib/keisan/ast/plus.rb +1 -5
- data/lib/keisan/ast/priorities.rb +27 -0
- data/lib/keisan/ast/times.rb +1 -5
- data/lib/keisan/ast/variable.rb +5 -0
- data/lib/keisan/calculator.rb +1 -12
- data/lib/keisan/context.rb +20 -5
- data/lib/keisan/evaluator.rb +79 -0
- data/lib/keisan/exceptions.rb +1 -0
- data/lib/keisan/functions/default_registry.rb +0 -5
- data/lib/keisan/functions/registry.rb +7 -0
- data/lib/keisan/parser.rb +42 -29
- data/lib/keisan/parsing/dot.rb +6 -0
- data/lib/keisan/parsing/dot_operator.rb +12 -0
- data/lib/keisan/parsing/dot_word.rb +14 -0
- data/lib/keisan/parsing/logical_equal.rb +9 -0
- data/lib/keisan/parsing/logical_not_equal.rb +9 -0
- data/lib/keisan/parsing/modulo.rb +9 -0
- data/lib/keisan/tokenizer.rb +2 -1
- data/lib/keisan/tokens/arithmetic_operator.rb +4 -1
- data/lib/keisan/tokens/dot.rb +11 -0
- data/lib/keisan/tokens/logical_operator.rb +7 -1
- data/lib/keisan/variables/registry.rb +7 -0
- data/lib/keisan/version.rb +1 -1
- metadata +14 -2
@@ -14,7 +14,6 @@ module Keisan
|
|
14
14
|
|
15
15
|
def self.register_defaults!(registry)
|
16
16
|
register_builtin_math!(registry)
|
17
|
-
register_branch_methods!(registry)
|
18
17
|
register_array_methods!(registry)
|
19
18
|
register_random_methods!(registry)
|
20
19
|
end
|
@@ -30,10 +29,6 @@ module Keisan
|
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
|
-
def self.register_branch_methods!(registry)
|
34
|
-
registry.register!(:if, Proc.new {|bool, a, b=nil| bool ? a : b })
|
35
|
-
end
|
36
|
-
|
37
32
|
def self.register_array_methods!(registry)
|
38
33
|
%i(min max size).each do |method|
|
39
34
|
registry.register!(method, Proc.new {|a| a.send(method)})
|
@@ -18,6 +18,13 @@ module Keisan
|
|
18
18
|
raise Keisan::Exceptions::UndefinedFunctionError.new name
|
19
19
|
end
|
20
20
|
|
21
|
+
def has?(name)
|
22
|
+
!!self[name]
|
23
|
+
rescue Keisan::Exceptions::UndefinedFunctionError
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
# For checking if locally defined
|
21
28
|
def has_name?(name)
|
22
29
|
@hash.has_key?(name)
|
23
30
|
end
|
data/lib/keisan/parser.rb
CHANGED
@@ -73,12 +73,35 @@ module Keisan
|
|
73
73
|
# Here it is a postfix Indexing (access elements by index)
|
74
74
|
elsif token.type == :group && token.group_type == :square
|
75
75
|
add_indexing_to_components!(token)
|
76
|
+
elsif token.type == :dot
|
77
|
+
@components << Keisan::Parsing::Dot.new
|
76
78
|
else
|
77
79
|
# Expect an operator
|
78
80
|
raise Keisan::Exceptions::ParseError.new("Expected an operator, received #{token.string}") unless token.type == :operator
|
79
81
|
add_operator_to_components!(token)
|
80
82
|
end
|
81
83
|
|
84
|
+
elsif @components[-1].is_a?(Parsing::Dot)
|
85
|
+
# Expect a word
|
86
|
+
case token.type
|
87
|
+
when :word
|
88
|
+
@components[-1] = Parsing::DotWord.new(token.string)
|
89
|
+
else
|
90
|
+
raise Keisan::Exceptions::ParseError.new("A word must follow a dot, received #{token.string}")
|
91
|
+
end
|
92
|
+
|
93
|
+
elsif @components[-1].is_a?(Parsing::DotWord)
|
94
|
+
# Expect a round group
|
95
|
+
if token.type == :group && token.group_type == :round
|
96
|
+
name = @components[-1].name
|
97
|
+
@components[-1] = Parsing::DotOperator.new(name, arguments_from_group(token))
|
98
|
+
elsif token.type == :dot
|
99
|
+
@components << Keisan::Parsing::Dot.new
|
100
|
+
elsif token.type == :group && token.group_type == :square
|
101
|
+
add_indexing_to_components!(token)
|
102
|
+
else
|
103
|
+
raise Keisan::Exceptions::ParseError.new("Expected arguments to dot operator, received #{token.string}")
|
104
|
+
end
|
82
105
|
else
|
83
106
|
raise Keisan::Exceptions::ParseError.new("Token cannot be parsed, #{token.string}")
|
84
107
|
end
|
@@ -120,15 +143,7 @@ module Keisan
|
|
120
143
|
when :round
|
121
144
|
@components << Keisan::Parsing::RoundGroup.new(token.sub_tokens)
|
122
145
|
when :square
|
123
|
-
@components <<
|
124
|
-
Parsing::List.new([])
|
125
|
-
else
|
126
|
-
Parsing::List.new(
|
127
|
-
token.sub_tokens.split {|sub_token| sub_token.is_a?(Keisan::Tokens::Comma)}.map do |sub_tokens|
|
128
|
-
Parsing::Argument.new(sub_tokens)
|
129
|
-
end
|
130
|
-
)
|
131
|
-
end
|
146
|
+
@components << Parsing::List.new(arguments_from_group(token))
|
132
147
|
else
|
133
148
|
raise Keisan::Exceptions::ParseError.new("Unhandled group type #{token.group_type}")
|
134
149
|
end
|
@@ -150,6 +165,8 @@ module Keisan
|
|
150
165
|
@components << Keisan::Parsing::Divide.new
|
151
166
|
when :**
|
152
167
|
@components << Keisan::Parsing::Exponent.new
|
168
|
+
when :%
|
169
|
+
@components << Keisan::Parsing::Modulo.new
|
153
170
|
# Bitwise
|
154
171
|
when :"&"
|
155
172
|
@components << Keisan::Parsing::BitwiseAnd.new
|
@@ -162,6 +179,10 @@ module Keisan
|
|
162
179
|
when :"~~"
|
163
180
|
@components << Keisan::Parsing::BitwiseNotNot.new
|
164
181
|
# Logical
|
182
|
+
when :"=="
|
183
|
+
@components << Keisan::Parsing::LogicalEqual.new
|
184
|
+
when :"!="
|
185
|
+
@components << Keisan::Parsing::LogicalNotEqual.new
|
165
186
|
when :"&&"
|
166
187
|
@components << Keisan::Parsing::LogicalAnd.new
|
167
188
|
when :"||"
|
@@ -184,30 +205,22 @@ module Keisan
|
|
184
205
|
end
|
185
206
|
|
186
207
|
def add_function_to_components!(token)
|
187
|
-
|
188
|
-
if token.sub_tokens.empty?
|
189
|
-
@components[-1] = Parsing::Function.new(@components[-1].name, [])
|
190
|
-
else
|
191
|
-
@components[-1] = Parsing::Function.new(
|
192
|
-
@components[-1].name,
|
193
|
-
token.sub_tokens.split {|sub_token| sub_token.is_a?(Keisan::Tokens::Comma)}.map do |sub_tokens|
|
194
|
-
Parsing::Argument.new(sub_tokens)
|
195
|
-
end
|
196
|
-
)
|
197
|
-
end
|
208
|
+
@components[-1] = Parsing::Function.new(@components[-1].name, arguments_from_group(token))
|
198
209
|
end
|
199
210
|
|
200
211
|
def add_indexing_to_components!(token)
|
201
212
|
# Have an indexing
|
202
|
-
@components <<
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
213
|
+
@components << Parsing::Indexing.new(arguments_from_group(token))
|
214
|
+
end
|
215
|
+
|
216
|
+
def arguments_from_group(token)
|
217
|
+
if token.sub_tokens.empty?
|
218
|
+
[]
|
219
|
+
else
|
220
|
+
token.sub_tokens.split {|sub_token| sub_token.is_a?(Keisan::Tokens::Comma)}.map do |sub_tokens|
|
221
|
+
Parsing::Argument.new(sub_tokens)
|
222
|
+
end
|
223
|
+
end
|
211
224
|
end
|
212
225
|
end
|
213
226
|
end
|
data/lib/keisan/tokenizer.rb
CHANGED
@@ -4,8 +4,9 @@ module Keisan
|
|
4
4
|
EXPONENT = /(?:\*\*)/
|
5
5
|
TIMES = /(?:\*)/
|
6
6
|
DIVIDE = /(?:\/)/
|
7
|
+
MODULO = /(?:\%)/
|
7
8
|
PLUS_OR_MINUS = /(?:[\+\-]+)/
|
8
|
-
REGEX = /(#{EXPONENT}|#{TIMES}|#{DIVIDE}|#{PLUS_OR_MINUS})/
|
9
|
+
REGEX = /(#{EXPONENT}|#{TIMES}|#{DIVIDE}|#{MODULO}|#{PLUS_OR_MINUS})/
|
9
10
|
|
10
11
|
def self.regex
|
11
12
|
REGEX
|
@@ -20,6 +21,8 @@ module Keisan
|
|
20
21
|
:*
|
21
22
|
when DIVIDE
|
22
23
|
:/
|
24
|
+
when MODULO
|
25
|
+
:%
|
23
26
|
when PLUS_OR_MINUS
|
24
27
|
string.count("-").even? ? :+ : :-
|
25
28
|
end
|
@@ -7,9 +7,11 @@ module Keisan
|
|
7
7
|
GREATER_THAN = /(?:\>)/
|
8
8
|
AND = /(?:\&\&)/
|
9
9
|
OR = /(?:\|\|)/
|
10
|
+
EQUAL = /(?:\=\=)/
|
11
|
+
NOT_EQUAL = /(?:\!\=)/
|
10
12
|
NOT = /(?:\!+)/
|
11
13
|
|
12
|
-
REGEX = /(#{LESS_THAN_OR_EQUAL_TO}|#{GREATER_THAN_OR_EQUAL_TO}|#{LESS_THAN}|#{GREATER_THAN}|#{AND}|#{OR}|#{NOT})/
|
14
|
+
REGEX = /(#{LESS_THAN_OR_EQUAL_TO}|#{GREATER_THAN_OR_EQUAL_TO}|#{LESS_THAN}|#{GREATER_THAN}|#{AND}|#{OR}|#{EQUAL}|#{NOT_EQUAL}|#{NOT})/
|
13
15
|
|
14
16
|
def self.regex
|
15
17
|
REGEX
|
@@ -29,6 +31,10 @@ module Keisan
|
|
29
31
|
:"&&"
|
30
32
|
when OR
|
31
33
|
:"||"
|
34
|
+
when EQUAL
|
35
|
+
:"=="
|
36
|
+
when NOT_EQUAL
|
37
|
+
:"!="
|
32
38
|
when NOT
|
33
39
|
string.count("!").even? ? :"!!" : :"!"
|
34
40
|
end
|
@@ -18,6 +18,13 @@ module Keisan
|
|
18
18
|
raise Keisan::Exceptions::UndefinedVariableError.new name
|
19
19
|
end
|
20
20
|
|
21
|
+
def has?(name)
|
22
|
+
!!self[name]
|
23
|
+
rescue Keisan::Exceptions::UndefinedVariableError
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
# For checking if locally defined
|
21
28
|
def has_name?(name)
|
22
29
|
@hash.has_key?(name)
|
23
30
|
end
|
data/lib/keisan/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keisan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christopher Locke
|
@@ -125,18 +125,22 @@ files:
|
|
125
125
|
- lib/keisan/ast/list.rb
|
126
126
|
- lib/keisan/ast/literal.rb
|
127
127
|
- lib/keisan/ast/logical_and.rb
|
128
|
+
- lib/keisan/ast/logical_equal.rb
|
128
129
|
- lib/keisan/ast/logical_greater_than.rb
|
129
130
|
- lib/keisan/ast/logical_greater_than_or_equal_to.rb
|
130
131
|
- lib/keisan/ast/logical_less_than.rb
|
131
132
|
- lib/keisan/ast/logical_less_than_or_equal_to.rb
|
133
|
+
- lib/keisan/ast/logical_not_equal.rb
|
132
134
|
- lib/keisan/ast/logical_operator.rb
|
133
135
|
- lib/keisan/ast/logical_or.rb
|
136
|
+
- lib/keisan/ast/modulo.rb
|
134
137
|
- lib/keisan/ast/node.rb
|
135
138
|
- lib/keisan/ast/null.rb
|
136
139
|
- lib/keisan/ast/number.rb
|
137
140
|
- lib/keisan/ast/operator.rb
|
138
141
|
- lib/keisan/ast/parent.rb
|
139
142
|
- lib/keisan/ast/plus.rb
|
143
|
+
- lib/keisan/ast/priorities.rb
|
140
144
|
- lib/keisan/ast/string.rb
|
141
145
|
- lib/keisan/ast/times.rb
|
142
146
|
- lib/keisan/ast/unary_bitwise_not.rb
|
@@ -149,6 +153,7 @@ files:
|
|
149
153
|
- lib/keisan/ast/variable.rb
|
150
154
|
- lib/keisan/calculator.rb
|
151
155
|
- lib/keisan/context.rb
|
156
|
+
- lib/keisan/evaluator.rb
|
152
157
|
- lib/keisan/exceptions.rb
|
153
158
|
- lib/keisan/function.rb
|
154
159
|
- lib/keisan/functions/default_registry.rb
|
@@ -167,6 +172,9 @@ files:
|
|
167
172
|
- lib/keisan/parsing/boolean.rb
|
168
173
|
- lib/keisan/parsing/component.rb
|
169
174
|
- lib/keisan/parsing/divide.rb
|
175
|
+
- lib/keisan/parsing/dot.rb
|
176
|
+
- lib/keisan/parsing/dot_operator.rb
|
177
|
+
- lib/keisan/parsing/dot_word.rb
|
170
178
|
- lib/keisan/parsing/element.rb
|
171
179
|
- lib/keisan/parsing/exponent.rb
|
172
180
|
- lib/keisan/parsing/function.rb
|
@@ -174,15 +182,18 @@ files:
|
|
174
182
|
- lib/keisan/parsing/indexing.rb
|
175
183
|
- lib/keisan/parsing/list.rb
|
176
184
|
- lib/keisan/parsing/logical_and.rb
|
185
|
+
- lib/keisan/parsing/logical_equal.rb
|
177
186
|
- lib/keisan/parsing/logical_greater_than.rb
|
178
187
|
- lib/keisan/parsing/logical_greater_than_or_equal_to.rb
|
179
188
|
- lib/keisan/parsing/logical_less_than.rb
|
180
189
|
- lib/keisan/parsing/logical_less_than_or_equal_to.rb
|
181
190
|
- lib/keisan/parsing/logical_not.rb
|
191
|
+
- lib/keisan/parsing/logical_not_equal.rb
|
182
192
|
- lib/keisan/parsing/logical_not_not.rb
|
183
193
|
- lib/keisan/parsing/logical_operator.rb
|
184
194
|
- lib/keisan/parsing/logical_or.rb
|
185
195
|
- lib/keisan/parsing/minus.rb
|
196
|
+
- lib/keisan/parsing/modulo.rb
|
186
197
|
- lib/keisan/parsing/null.rb
|
187
198
|
- lib/keisan/parsing/number.rb
|
188
199
|
- lib/keisan/parsing/operator.rb
|
@@ -201,6 +212,7 @@ files:
|
|
201
212
|
- lib/keisan/tokens/bitwise_operator.rb
|
202
213
|
- lib/keisan/tokens/boolean.rb
|
203
214
|
- lib/keisan/tokens/comma.rb
|
215
|
+
- lib/keisan/tokens/dot.rb
|
204
216
|
- lib/keisan/tokens/group.rb
|
205
217
|
- lib/keisan/tokens/logical_operator.rb
|
206
218
|
- lib/keisan/tokens/null.rb
|
@@ -231,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
231
243
|
version: '0'
|
232
244
|
requirements: []
|
233
245
|
rubyforge_project:
|
234
|
-
rubygems_version: 2.6.
|
246
|
+
rubygems_version: 2.6.11
|
235
247
|
signing_key:
|
236
248
|
specification_version: 4
|
237
249
|
summary: An equation parser and evaluator
|