keisan 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +49 -1
  3. data/keisan.gemspec +1 -0
  4. data/lib/keisan.rb +30 -0
  5. data/lib/keisan/ast/assignment.rb +44 -17
  6. data/lib/keisan/ast/block.rb +60 -0
  7. data/lib/keisan/ast/boolean.rb +5 -5
  8. data/lib/keisan/ast/builder.rb +10 -207
  9. data/lib/keisan/ast/cell.rb +60 -0
  10. data/lib/keisan/ast/constant_literal.rb +9 -0
  11. data/lib/keisan/ast/exponent.rb +6 -6
  12. data/lib/keisan/ast/function.rb +12 -8
  13. data/lib/keisan/ast/indexing.rb +25 -15
  14. data/lib/keisan/ast/line_builder.rb +230 -0
  15. data/lib/keisan/ast/list.rb +28 -1
  16. data/lib/keisan/ast/literal.rb +0 -8
  17. data/lib/keisan/ast/logical_and.rb +1 -1
  18. data/lib/keisan/ast/logical_or.rb +1 -1
  19. data/lib/keisan/ast/multi_line.rb +28 -0
  20. data/lib/keisan/ast/node.rb +32 -24
  21. data/lib/keisan/ast/number.rb +31 -31
  22. data/lib/keisan/ast/operator.rb +12 -4
  23. data/lib/keisan/ast/parent.rb +4 -4
  24. data/lib/keisan/ast/plus.rb +10 -10
  25. data/lib/keisan/ast/string.rb +3 -3
  26. data/lib/keisan/ast/times.rb +8 -8
  27. data/lib/keisan/ast/unary_identity.rb +1 -1
  28. data/lib/keisan/ast/unary_inverse.rb +7 -7
  29. data/lib/keisan/ast/unary_minus.rb +5 -5
  30. data/lib/keisan/ast/unary_operator.rb +2 -2
  31. data/lib/keisan/ast/unary_plus.rb +2 -2
  32. data/lib/keisan/ast/variable.rb +26 -10
  33. data/lib/keisan/context.rb +5 -5
  34. data/lib/keisan/evaluator.rb +15 -8
  35. data/lib/keisan/function.rb +24 -6
  36. data/lib/keisan/functions/cbrt.rb +1 -1
  37. data/lib/keisan/functions/cos.rb +1 -1
  38. data/lib/keisan/functions/cosh.rb +1 -1
  39. data/lib/keisan/functions/cot.rb +1 -1
  40. data/lib/keisan/functions/coth.rb +1 -1
  41. data/lib/keisan/functions/csc.rb +1 -1
  42. data/lib/keisan/functions/csch.rb +1 -1
  43. data/lib/keisan/functions/default_registry.rb +53 -74
  44. data/lib/keisan/functions/diff.rb +18 -14
  45. data/lib/keisan/functions/erf.rb +15 -0
  46. data/lib/keisan/functions/exp.rb +1 -1
  47. data/lib/keisan/functions/expression_function.rb +15 -21
  48. data/lib/keisan/functions/filter.rb +13 -15
  49. data/lib/keisan/functions/if.rb +14 -20
  50. data/lib/keisan/functions/let.rb +36 -0
  51. data/lib/keisan/functions/map.rb +11 -13
  52. data/lib/keisan/functions/math_function.rb +2 -2
  53. data/lib/keisan/functions/proc_function.rb +10 -6
  54. data/lib/keisan/functions/rand.rb +2 -1
  55. data/lib/keisan/functions/range.rb +74 -0
  56. data/lib/keisan/functions/reduce.rb +12 -14
  57. data/lib/keisan/functions/registry.rb +7 -7
  58. data/lib/keisan/functions/replace.rb +8 -8
  59. data/lib/keisan/functions/sample.rb +2 -1
  60. data/lib/keisan/functions/sec.rb +1 -1
  61. data/lib/keisan/functions/sech.rb +1 -1
  62. data/lib/keisan/functions/sin.rb +1 -1
  63. data/lib/keisan/functions/sinh.rb +1 -1
  64. data/lib/keisan/functions/sqrt.rb +1 -1
  65. data/lib/keisan/functions/tan.rb +1 -1
  66. data/lib/keisan/functions/tanh.rb +1 -1
  67. data/lib/keisan/functions/while.rb +46 -0
  68. data/lib/keisan/parser.rb +121 -79
  69. data/lib/keisan/parsing/assignment.rb +1 -1
  70. data/lib/keisan/parsing/bitwise_and.rb +1 -1
  71. data/lib/keisan/parsing/bitwise_not.rb +1 -1
  72. data/lib/keisan/parsing/bitwise_not_not.rb +1 -1
  73. data/lib/keisan/parsing/bitwise_or.rb +1 -1
  74. data/lib/keisan/parsing/bitwise_xor.rb +1 -1
  75. data/lib/keisan/parsing/curly_group.rb +6 -0
  76. data/lib/keisan/parsing/divide.rb +1 -1
  77. data/lib/keisan/parsing/exponent.rb +1 -1
  78. data/lib/keisan/parsing/function.rb +1 -1
  79. data/lib/keisan/parsing/group.rb +1 -1
  80. data/lib/keisan/parsing/indexing.rb +1 -1
  81. data/lib/keisan/parsing/line_separator.rb +6 -0
  82. data/lib/keisan/parsing/logical_and.rb +1 -1
  83. data/lib/keisan/parsing/logical_equal.rb +1 -1
  84. data/lib/keisan/parsing/logical_greater_than.rb +1 -1
  85. data/lib/keisan/parsing/logical_greater_than_or_equal_to.rb +1 -1
  86. data/lib/keisan/parsing/logical_less_than.rb +1 -1
  87. data/lib/keisan/parsing/logical_less_than_or_equal_to.rb +1 -1
  88. data/lib/keisan/parsing/logical_not.rb +1 -1
  89. data/lib/keisan/parsing/logical_not_equal.rb +1 -1
  90. data/lib/keisan/parsing/logical_not_not.rb +1 -1
  91. data/lib/keisan/parsing/logical_or.rb +1 -1
  92. data/lib/keisan/parsing/minus.rb +1 -1
  93. data/lib/keisan/parsing/modulo.rb +1 -1
  94. data/lib/keisan/parsing/operator.rb +1 -1
  95. data/lib/keisan/parsing/plus.rb +1 -1
  96. data/lib/keisan/parsing/times.rb +1 -1
  97. data/lib/keisan/parsing/unary_minus.rb +1 -1
  98. data/lib/keisan/parsing/unary_operator.rb +1 -1
  99. data/lib/keisan/parsing/unary_plus.rb +1 -1
  100. data/lib/keisan/repl.rb +1 -1
  101. data/lib/keisan/tokenizer.rb +4 -9
  102. data/lib/keisan/tokens/group.rb +3 -1
  103. data/lib/keisan/tokens/line_separator.rb +11 -0
  104. data/lib/keisan/variables/default_registry.rb +0 -5
  105. data/lib/keisan/variables/registry.rb +7 -7
  106. data/lib/keisan/version.rb +1 -1
  107. metadata +27 -2
@@ -19,7 +19,7 @@ module Keisan
19
19
  end
20
20
 
21
21
  return default_registry[name] if @use_defaults && default_registry.has_name?(name)
22
- raise Keisan::Exceptions::UndefinedFunctionError.new name
22
+ raise Exceptions::UndefinedFunctionError.new name
23
23
  end
24
24
 
25
25
  def locals
@@ -28,25 +28,25 @@ module Keisan
28
28
 
29
29
  def has?(name)
30
30
  !!self[name]
31
- rescue Keisan::Exceptions::UndefinedFunctionError
31
+ rescue Exceptions::UndefinedFunctionError
32
32
  false
33
33
  end
34
34
 
35
35
  def register!(name, function, force: false)
36
- raise Keisan::Exceptions::UnmodifiableError.new("Cannot modify frozen functions registry") if frozen?
36
+ raise Exceptions::UnmodifiableError.new("Cannot modify frozen functions registry") if frozen?
37
37
  name = name.to_s
38
38
 
39
39
  if !force && @use_defaults && default_registry.has_name?(name)
40
- raise Keisan::Exceptions::UnmodifiableError.new("Cannot overwrite default function")
40
+ raise Exceptions::UnmodifiableError.new("Cannot overwrite default function")
41
41
  end
42
42
 
43
43
  case function
44
44
  when Proc
45
- self[name] = Keisan::Functions::ProcFunction.new(name, function)
46
- when Keisan::Function
45
+ self[name] = ProcFunction.new(name, function)
46
+ when Function
47
47
  self[name] = function
48
48
  else
49
- raise Keisan::Exceptions::InvalidFunctionError.new
49
+ raise Exceptions::InvalidFunctionError.new
50
50
  end
51
51
  end
52
52
 
@@ -1,17 +1,17 @@
1
1
  module Keisan
2
2
  module Functions
3
- class Replace < Keisan::Function
3
+ class Replace < Function
4
4
  def initialize
5
5
  @name = "replace"
6
6
  end
7
7
 
8
8
  def value(ast_function, context = nil)
9
- context ||= Keisan::Context.new
9
+ context ||= Context.new
10
10
  evaluate(ast_function, context).value(context)
11
11
  end
12
12
 
13
13
  def evaluate(ast_function, context = nil)
14
- context ||= Keisan::Context.new
14
+ context ||= Context.new
15
15
  expression, variable, replacement = expression_variable_replacement(ast_function)
16
16
 
17
17
  expression = expression.evaluate(context)
@@ -28,18 +28,18 @@ module Keisan
28
28
  private
29
29
 
30
30
  def expression_variable_replacement(ast_function)
31
- unless ast_function.is_a?(Keisan::AST::Function) && ast_function.name == name
32
- raise Keisan::Exceptions::InvalidFunctionError.new("Must receive replace function")
31
+ unless ast_function.is_a?(AST::Function) && ast_function.name == name
32
+ raise Exceptions::InvalidFunctionError.new("Must receive replace function")
33
33
  end
34
34
 
35
35
  unless ast_function.children.size == 3
36
- raise Keisan::Exceptions::InvalidFunctionError.new("Require 3 arguments to replace")
36
+ raise Exceptions::InvalidFunctionError.new("Require 3 arguments to replace")
37
37
  end
38
38
 
39
39
  expression, variable, replacement = *ast_function.children.map(&:deep_dup)
40
40
 
41
- unless variable.is_a?(Keisan::AST::Variable)
42
- raise Keisan::Exceptions::InvalidFunctionError.new("Replace must replace a variable")
41
+ unless variable.is_a?(AST::Variable)
42
+ raise Exceptions::InvalidFunctionError.new("Replace must replace a variable")
43
43
  end
44
44
 
45
45
  [expression, variable, replacement]
@@ -3,6 +3,7 @@ module Keisan
3
3
  class Sample < ProcFunction
4
4
  def initialize
5
5
  @name = "sample"
6
+ @arity = 1
6
7
  end
7
8
 
8
9
  # Single argument: integer in range [0, max)
@@ -12,7 +13,7 @@ module Keisan
12
13
  when 1
13
14
  args.first.sample(random: context.random)
14
15
  else
15
- raise Keisan::Exceptions::InvalidFunctionError.new
16
+ raise Exceptions::InvalidFunctionError.new
16
17
  end
17
18
  end
18
19
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Function.new([argument], "sin") * Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "cos"), -2])
11
+ AST::Function.new([argument], "sin") * AST::Exponent.new([AST::Function.new([argument], "cos"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- -Keisan::AST::Function.new([argument], "sinh") * Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "cosh"), -2])
11
+ -AST::Function.new([argument], "sinh") * AST::Exponent.new([AST::Function.new([argument], "cosh"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Function.new([argument], "cos")
11
+ AST::Function.new([argument], "cos")
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Function.new([argument], "cosh")
11
+ AST::Function.new([argument], "cosh")
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Exponent.new([argument, Rational(-1,2)]) / 2
11
+ AST::Exponent.new([argument, Rational(-1,2)]) / 2
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "cos"), -2])
11
+ AST::Exponent.new([AST::Function.new([argument], "cos"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -8,7 +8,7 @@ module Keisan
8
8
  protected
9
9
 
10
10
  def self.derivative(argument)
11
- Keisan::AST::Exponent.new([Keisan::AST::Function.new([argument], "cosh"), -2])
11
+ AST::Exponent.new([AST::Function.new([argument], "cosh"), -2])
12
12
  end
13
13
  end
14
14
  end
@@ -0,0 +1,46 @@
1
+ module Keisan
2
+ module Functions
3
+ class While < Keisan::Function
4
+ def initialize
5
+ super("while", 2)
6
+ end
7
+
8
+ def value(ast_function, context = nil)
9
+ validate_arguments!(ast_function.children.count)
10
+ evaluate(ast_function, context)
11
+ end
12
+
13
+ def evaluate(ast_function, context = nil)
14
+ validate_arguments!(ast_function.children.count)
15
+ context ||= Keisan::Context.new
16
+ simplify(ast_function, context)
17
+ end
18
+
19
+ def simplify(ast_function, context = nil)
20
+ validate_arguments!(ast_function.children.count)
21
+ context ||= Context.new
22
+ while_loop(ast_function.children[0], ast_function.children[1], context)
23
+ end
24
+
25
+ private
26
+
27
+ def while_loop(logical_node, body_node, context)
28
+ current = Keisan::AST::Null.new
29
+
30
+ while logical_node_evaluates_to_true(logical_node, context)
31
+ current = body_node.evaluated(context)
32
+ end
33
+
34
+ current
35
+ end
36
+
37
+ def logical_node_evaluates_to_true(logical_node, context)
38
+ bool = logical_node.evaluated(context)
39
+ unless bool.is_a?(AST::Boolean)
40
+ raise Keisan::Exceptions::InvalidFunctionError.new("while condition must evaluate to a boolean")
41
+ end
42
+ bool.value(context)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,31 +1,68 @@
1
1
  module Keisan
2
2
  class Parser
3
+ KEYWORDS = %w(let).freeze
4
+
3
5
  attr_reader :tokens, :components
4
6
 
5
7
  def initialize(string: nil, tokens: nil)
6
8
  if string.nil? && tokens.nil?
7
- raise Keisan::Exceptions::InternalError.new("Invalid arguments")
9
+ raise Exceptions::InternalError.new("Invalid arguments")
8
10
  end
9
11
 
10
12
  if !string.nil?
11
13
  @tokens = Tokenizer.new(string).tokens
12
14
  else
13
- raise Keisan::Exceptions::InternalError.new("Invalid argument: tokens = #{tokens}") if tokens.nil? || !tokens.is_a?(Array)
15
+ raise Exceptions::InternalError.new("Invalid argument: tokens = #{tokens}") if tokens.nil? || !tokens.is_a?(Array)
14
16
  @tokens = tokens
15
17
  end
16
18
 
17
19
  @components = []
18
20
 
19
- parse_components!
20
- remove_unary_identity!
21
+ if multi_line?
22
+ parse_multi_line!
23
+ elsif @tokens.first&.is_a?(Tokens::Word) && KEYWORDS.include?(@tokens.first.string)
24
+ parse_keyword!
25
+ else
26
+ parse_components!
27
+ remove_unary_identity!
28
+ end
21
29
  end
22
30
 
23
31
  def ast
24
- @ast ||= Keisan::AST::Builder.new(parser: self).ast
32
+ @ast ||= AST::Builder.new(parser: self).ast
25
33
  end
26
34
 
27
35
  private
28
36
 
37
+ def multi_line?
38
+ @tokens.any? {|token| token.is_a?(Tokens::LineSeparator)}
39
+ end
40
+
41
+ def parse_multi_line!
42
+ line_parsers = @tokens.split {|token| token.is_a?(Tokens::LineSeparator)}.map {|tokens| self.class.new(tokens: tokens)}
43
+ @components = []
44
+ line_parsers.each.with_index do |line_parser, i|
45
+ @components += line_parser.components
46
+ if i < line_parsers.count - 1
47
+ @components << Parsing::LineSeparator.new
48
+ end
49
+ end
50
+ end
51
+
52
+ def parse_keyword!
53
+ keyword = tokens.first.string
54
+ arguments = if tokens[1].is_a?(Tokens::Group)
55
+ tokens[1].sub_tokens.split {|token| token.is_a?(Tokens::Comma)}.map {|argument_tokens|
56
+ Parsing::Argument.new(argument_tokens)
57
+ }
58
+ else
59
+ Parsing::Argument.new(tokens[1..-1])
60
+ end
61
+ @components = [
62
+ Parsing::Function.new(keyword, arguments)
63
+ ]
64
+ end
65
+
29
66
  def parse_components!
30
67
  @unparsed_tokens = tokens.dup
31
68
 
@@ -39,10 +76,14 @@ module Keisan
39
76
 
40
77
  def remove_unary_identity!
41
78
  @components = @components.select do |component|
42
- !component.is_a?(Keisan::Parsing::Operator) || !(component.node_class <= Keisan::AST::UnaryIdentity)
79
+ !component.is_a?(Parsing::Operator) || !(component.node_class <= AST::UnaryIdentity)
43
80
  end
44
81
  end
45
82
 
83
+ def is_start_of_line?
84
+ @components.empty? || @components.last.is_a?(Parsing::LineSeparator)
85
+ end
86
+
46
87
  # Elements are groups of tokens separated by (non-unary) operators
47
88
  # The following are basic elements:
48
89
  # number
@@ -54,7 +95,9 @@ module Keisan
54
95
  # and any number of indexing groups (square groups) at the back
55
96
  #
56
97
  def add_token_to_components!(token)
57
- if @components.empty? || @components[-1].is_a?(Parsing::Operator)
98
+ if token.is_a?(Tokens::LineSeparator)
99
+ @components << Parsing::LineSeparator.new
100
+ elsif is_start_of_line? || @components[-1].is_a?(Parsing::Operator)
58
101
  # Expect an element or a unary operator
59
102
  if token.type == :operator
60
103
  # Here it must be a unary operator
@@ -64,17 +107,6 @@ module Keisan
64
107
  add_element_to_components!(token)
65
108
  end
66
109
 
67
- elsif @components[-1].is_a?(Parsing::UnaryOperator)
68
- # Expect an element or another unary operator
69
- case token.type
70
- when :operator
71
- add_unary_operator_to_components!(token)
72
- when :number, :string, :word, :group, :null, :boolean
73
- add_element_to_components!(token)
74
- else
75
- raise Keisan::Exceptions::ParseError.new("Expected an element, received #{token.string}")
76
- end
77
-
78
110
  elsif @components[-1].is_a?(Parsing::Element)
79
111
  # A word followed by a "round group" is actually a function: e.g. sin(x)
80
112
  if @components[-1].is_a?(Parsing::Variable) && token.type == :group && token.group_type == :round
@@ -83,11 +115,11 @@ module Keisan
83
115
  elsif token.type == :group && token.group_type == :square
84
116
  add_indexing_to_components!(token)
85
117
  elsif token.type == :dot
86
- @components << Keisan::Parsing::Dot.new
87
- else
88
- # Expect an operator
89
- raise Keisan::Exceptions::ParseError.new("Expected an operator, received #{token.string}") unless token.type == :operator
118
+ @components << Parsing::Dot.new
119
+ elsif token.type == :operator
90
120
  add_operator_to_components!(token)
121
+ else
122
+ raise Exceptions::ParseError.new("Expected an operator, received #{token.string}")
91
123
  end
92
124
 
93
125
  elsif @components[-1].is_a?(Parsing::Dot)
@@ -96,68 +128,86 @@ module Keisan
96
128
  when :word
97
129
  @components[-1] = Parsing::DotWord.new(token.string)
98
130
  else
99
- raise Keisan::Exceptions::ParseError.new("A word must follow a dot, received #{token.string}")
131
+ raise Exceptions::ParseError.new("A word must follow a dot, received #{token.string}")
100
132
  end
101
133
 
102
134
  elsif @components[-1].is_a?(Parsing::DotWord)
103
- # Expect a round group
104
- if token.type == :group && token.group_type == :round
135
+ add_token_after_dot_word!(token)
136
+
137
+ else
138
+ raise Exceptions::ParseError.new("Token cannot be parsed, #{token.string}")
139
+ end
140
+ end
141
+
142
+ def add_token_after_dot_word!(token)
143
+ case token.type
144
+ when :group
145
+ case token.group_type
146
+ when :round
147
+ # Here it is a method call
105
148
  name = @components[-1].name
106
149
  @components[-1] = Parsing::DotOperator.new(name, arguments_from_group(token))
107
- elsif token.type == :dot
108
- @components << Keisan::Parsing::Dot.new
109
- elsif token.type == :group && token.group_type == :square
150
+ when :square
151
+ # Here we are indexing after method call
110
152
  add_indexing_to_components!(token)
111
153
  else
112
- raise Keisan::Exceptions::ParseError.new("Expected arguments to dot operator, received #{token.string}")
154
+ raise Exceptions::ParseError.new("Cannot take curly braces after function call")
113
155
  end
156
+ when :dot
157
+ # Chaining method calls
158
+ @components << Parsing::Dot.new
159
+ when :operator
160
+ # End of method call, move on to operator
161
+ add_operator_to_components!(token)
114
162
  else
115
- raise Keisan::Exceptions::ParseError.new("Token cannot be parsed, #{token.string}")
163
+ raise Exceptions::ParseError.new("Expected arguments to dot operator, received #{token.string}")
116
164
  end
117
165
  end
118
166
 
119
167
  def add_unary_operator_to_components!(token)
120
168
  case token.operator_type
121
169
  when :+
122
- @components << Keisan::Parsing::UnaryPlus.new
170
+ @components << Parsing::UnaryPlus.new
123
171
  when :-
124
- @components << Keisan::Parsing::UnaryMinus.new
172
+ @components << Parsing::UnaryMinus.new
125
173
  when :"~"
126
- @components << Keisan::Parsing::BitwiseNot.new
174
+ @components << Parsing::BitwiseNot.new
127
175
  when :"~~"
128
- @components << Keisan::Parsing::BitwiseNotNot.new
176
+ @components << Parsing::BitwiseNotNot.new
129
177
  when :"!"
130
- @components << Keisan::Parsing::LogicalNot.new
178
+ @components << Parsing::LogicalNot.new
131
179
  when :"!!"
132
- @components << Keisan::Parsing::LogicalNotNot.new
180
+ @components << Parsing::LogicalNotNot.new
133
181
  else
134
- raise Keisan::Exceptions::ParseError.new("Unhandled unary operator type #{token.operator_type}")
182
+ raise Exceptions::ParseError.new("Unhandled unary operator type #{token.operator_type}")
135
183
  end
136
184
  end
137
185
 
138
186
  def add_element_to_components!(token)
139
187
  case token
140
- when Keisan::Tokens::Number
141
- @components << Keisan::Parsing::Number.new(token.value)
142
- when Keisan::Tokens::String
143
- @components << Keisan::Parsing::String.new(token.value)
144
- when Keisan::Tokens::Null
145
- @components << Keisan::Parsing::Null.new
146
- when Keisan::Tokens::Word
147
- @components << Keisan::Parsing::Variable.new(token.string)
148
- when Keisan::Tokens::Boolean
149
- @components << Keisan::Parsing::Boolean.new(token.value)
150
- when Keisan::Tokens::Group
188
+ when Tokens::Number
189
+ @components << Parsing::Number.new(token.value)
190
+ when Tokens::String
191
+ @components << Parsing::String.new(token.value)
192
+ when Tokens::Null
193
+ @components << Parsing::Null.new
194
+ when Tokens::Word
195
+ @components << Parsing::Variable.new(token.string)
196
+ when Tokens::Boolean
197
+ @components << Parsing::Boolean.new(token.value)
198
+ when Tokens::Group
151
199
  case token.group_type
152
200
  when :round
153
- @components << Keisan::Parsing::RoundGroup.new(token.sub_tokens)
201
+ @components << Parsing::RoundGroup.new(token.sub_tokens)
154
202
  when :square
155
203
  @components << Parsing::List.new(arguments_from_group(token))
204
+ when :curly
205
+ @components << Parsing::CurlyGroup.new(token.sub_tokens)
156
206
  else
157
- raise Keisan::Exceptions::ParseError.new("Unhandled group type #{token.group_type}")
207
+ raise Exceptions::ParseError.new("Unhandled group type #{token.group_type}")
158
208
  end
159
209
  else
160
- raise Keisan::Exceptions::ParseError.new("Unhandled operator type #{token.operator_type}")
210
+ raise Exceptions::ParseError.new("Unhandled operator type #{token.operator_type}")
161
211
  end
162
212
  end
163
213
 
@@ -165,54 +215,46 @@ module Keisan
165
215
  case token.operator_type
166
216
  # Assignment
167
217
  when :"="
168
- @components << Keisan::Parsing::Assignment.new
218
+ @components << Parsing::Assignment.new
169
219
  # Arithmetic
170
220
  when :+
171
- @components << Keisan::Parsing::Plus.new
221
+ @components << Parsing::Plus.new
172
222
  when :-
173
- @components << Keisan::Parsing::Minus.new
223
+ @components << Parsing::Minus.new
174
224
  when :*
175
- @components << Keisan::Parsing::Times.new
225
+ @components << Parsing::Times.new
176
226
  when :/
177
- @components << Keisan::Parsing::Divide.new
227
+ @components << Parsing::Divide.new
178
228
  when :**
179
- @components << Keisan::Parsing::Exponent.new
229
+ @components << Parsing::Exponent.new
180
230
  when :%
181
- @components << Keisan::Parsing::Modulo.new
231
+ @components << Parsing::Modulo.new
182
232
  # Bitwise
183
233
  when :"&"
184
- @components << Keisan::Parsing::BitwiseAnd.new
234
+ @components << Parsing::BitwiseAnd.new
185
235
  when :"|"
186
- @components << Keisan::Parsing::BitwiseOr.new
236
+ @components << Parsing::BitwiseOr.new
187
237
  when :"^"
188
- @components << Keisan::Parsing::BitwiseXor.new
189
- when :"~"
190
- @components << Keisan::Parsing::BitwiseNot.new
191
- when :"~~"
192
- @components << Keisan::Parsing::BitwiseNotNot.new
238
+ @components << Parsing::BitwiseXor.new
193
239
  # Logical
194
240
  when :"=="
195
- @components << Keisan::Parsing::LogicalEqual.new
241
+ @components << Parsing::LogicalEqual.new
196
242
  when :"!="
197
- @components << Keisan::Parsing::LogicalNotEqual.new
243
+ @components << Parsing::LogicalNotEqual.new
198
244
  when :"&&"
199
- @components << Keisan::Parsing::LogicalAnd.new
245
+ @components << Parsing::LogicalAnd.new
200
246
  when :"||"
201
- @components << Keisan::Parsing::LogicalOr.new
202
- when :"!"
203
- @components << Keisan::Parsing::LogicalNot.new
204
- when :"!!"
205
- @components << Keisan::Parsing::LogicalNotNot.new
247
+ @components << Parsing::LogicalOr.new
206
248
  when :">"
207
- @components << Keisan::Parsing::LogicalGreaterThan.new
249
+ @components << Parsing::LogicalGreaterThan.new
208
250
  when :"<"
209
- @components << Keisan::Parsing::LogicalLessThan.new
251
+ @components << Parsing::LogicalLessThan.new
210
252
  when :">="
211
- @components << Keisan::Parsing::LogicalGreaterThanOrEqualTo.new
253
+ @components << Parsing::LogicalGreaterThanOrEqualTo.new
212
254
  when :"<="
213
- @components << Keisan::Parsing::LogicalLessThanOrEqualTo.new
255
+ @components << Parsing::LogicalLessThanOrEqualTo.new
214
256
  else
215
- raise Keisan::Exceptions::ParseError.new("Unhandled operator type #{token.operator_type}")
257
+ raise Exceptions::ParseError.new("Unhandled operator type #{token.operator_type}")
216
258
  end
217
259
  end
218
260
 
@@ -229,7 +271,7 @@ module Keisan
229
271
  if token.sub_tokens.empty?
230
272
  []
231
273
  else
232
- token.sub_tokens.split {|sub_token| sub_token.is_a?(Keisan::Tokens::Comma)}.map do |sub_tokens|
274
+ token.sub_tokens.split {|sub_token| sub_token.is_a?(Tokens::Comma)}.map do |sub_tokens|
233
275
  Parsing::Argument.new(sub_tokens)
234
276
  end
235
277
  end