rox-rollout 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +45 -0
  3. data/.gitignore +8 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE +50 -0
  6. data/README_DEVELOP.md +19 -0
  7. data/Rakefile +16 -0
  8. data/_archive/.document +5 -0
  9. data/_archive/.rspec +1 -0
  10. data/_archive/Gemfile +15 -0
  11. data/_archive/Gemfile.lock +87 -0
  12. data/_archive/README.md +32 -0
  13. data/_archive/README.rdoc +19 -0
  14. data/_archive/Rakefile +50 -0
  15. data/_archive/lib/expr_function_definition.rb +52 -0
  16. data/_archive/lib/function_definition.rb +48 -0
  17. data/_archive/lib/function_token.rb +12 -0
  18. data/_archive/lib/object_extends.rb +12 -0
  19. data/_archive/lib/ruby_interpreter.rb +292 -0
  20. data/_archive/lib/stack.rb +48 -0
  21. data/_archive/lib/string_extends.rb +14 -0
  22. data/_archive/spec/ruby_interpreter_spec.rb +203 -0
  23. data/_archive/spec/spec_helper.rb +30 -0
  24. data/_archive/spec/stack_spec.rb +77 -0
  25. data/bin/console +14 -0
  26. data/bin/setup +8 -0
  27. data/e2e/container.rb +38 -0
  28. data/e2e/custom_props.rb +55 -0
  29. data/e2e/rox_e2e_test.rb +159 -0
  30. data/e2e/test_vars.rb +24 -0
  31. data/lib/rox.rb +5 -0
  32. data/lib/rox/core/client/buid.rb +82 -0
  33. data/lib/rox/core/client/device_properties.rb +45 -0
  34. data/lib/rox/core/client/internal_flags.rb +20 -0
  35. data/lib/rox/core/client/sdk_settings.rb +5 -0
  36. data/lib/rox/core/configuration/configuration.rb +5 -0
  37. data/lib/rox/core/configuration/configuration_fetched_args.rb +23 -0
  38. data/lib/rox/core/configuration/configuration_fetched_invoker.rb +37 -0
  39. data/lib/rox/core/configuration/configuration_parser.rb +85 -0
  40. data/lib/rox/core/configuration/fetcher_error.rb +13 -0
  41. data/lib/rox/core/configuration/fetcher_status.rb +10 -0
  42. data/lib/rox/core/configuration/models/experiment_model.rb +5 -0
  43. data/lib/rox/core/configuration/models/target_group_model.rb +5 -0
  44. data/lib/rox/core/consts/build.rb +8 -0
  45. data/lib/rox/core/consts/environment.rb +42 -0
  46. data/lib/rox/core/consts/property_type.rb +29 -0
  47. data/lib/rox/core/context/merged_context.rb +16 -0
  48. data/lib/rox/core/core.rb +131 -0
  49. data/lib/rox/core/entities/flag.rb +26 -0
  50. data/lib/rox/core/entities/flag_setter.rb +39 -0
  51. data/lib/rox/core/entities/variant.rb +56 -0
  52. data/lib/rox/core/impression/impression_args.rb +5 -0
  53. data/lib/rox/core/impression/impression_invoker.rb +41 -0
  54. data/lib/rox/core/impression/models/experiment.rb +14 -0
  55. data/lib/rox/core/impression/models/reporting_value.rb +5 -0
  56. data/lib/rox/core/logging/logging.rb +17 -0
  57. data/lib/rox/core/logging/no_op_logger.rb +11 -0
  58. data/lib/rox/core/network/configuration_fetch_result.rb +5 -0
  59. data/lib/rox/core/network/configuration_fetcher.rb +38 -0
  60. data/lib/rox/core/network/configuration_fetcher_base.rb +25 -0
  61. data/lib/rox/core/network/configuration_fetcher_roxy.rb +29 -0
  62. data/lib/rox/core/network/configuration_source.rb +9 -0
  63. data/lib/rox/core/network/request.rb +46 -0
  64. data/lib/rox/core/network/request_configuration_builder.rb +48 -0
  65. data/lib/rox/core/network/request_data.rb +5 -0
  66. data/lib/rox/core/network/response.rb +16 -0
  67. data/lib/rox/core/properties/custom_property.rb +18 -0
  68. data/lib/rox/core/properties/custom_property_type.rb +18 -0
  69. data/lib/rox/core/properties/device_property.rb +11 -0
  70. data/lib/rox/core/register/registerer.rb +35 -0
  71. data/lib/rox/core/reporting/error_reporter.rb +152 -0
  72. data/lib/rox/core/repositories/custom_property_repository.rb +61 -0
  73. data/lib/rox/core/repositories/experiment_repository.rb +21 -0
  74. data/lib/rox/core/repositories/flag_repository.rb +49 -0
  75. data/lib/rox/core/repositories/roxx/experiments_extensions.rb +82 -0
  76. data/lib/rox/core/repositories/roxx/properties_extensions.rb +26 -0
  77. data/lib/rox/core/repositories/target_group_repository.rb +17 -0
  78. data/lib/rox/core/roxx/core_stack.rb +22 -0
  79. data/lib/rox/core/roxx/evaluation_result.rb +28 -0
  80. data/lib/rox/core/roxx/node.rb +11 -0
  81. data/lib/rox/core/roxx/parser.rb +143 -0
  82. data/lib/rox/core/roxx/regular_expression_extensions.rb +33 -0
  83. data/lib/rox/core/roxx/string_tokenizer.rb +68 -0
  84. data/lib/rox/core/roxx/symbols.rb +14 -0
  85. data/lib/rox/core/roxx/token_type.rb +30 -0
  86. data/lib/rox/core/roxx/tokenized_expression.rb +119 -0
  87. data/lib/rox/core/roxx/value_compare_extensions.rb +137 -0
  88. data/lib/rox/core/security/signature_verifier.rb +18 -0
  89. data/lib/rox/core/utils/periodic_task.rb +12 -0
  90. data/lib/rox/core/utils/type_utils.rb +9 -0
  91. data/lib/rox/server/client/sdk_settings.rb +5 -0
  92. data/lib/rox/server/client/server_properties.rb +20 -0
  93. data/lib/rox/server/flags/rox_flag.rb +19 -0
  94. data/lib/rox/server/flags/rox_variant.rb +8 -0
  95. data/lib/rox/server/logging/server_logger.rb +35 -0
  96. data/lib/rox/server/rox_options.rb +27 -0
  97. data/lib/rox/server/rox_server.rb +83 -0
  98. data/lib/rox/version.rb +3 -0
  99. data/rox.gemspec +29 -0
  100. metadata +184 -0
@@ -0,0 +1,26 @@
1
+ require 'rox/core/roxx/token_type'
2
+
3
+ module Rox
4
+ module Core
5
+ class PropertiesExtensions
6
+ def initialize(parser, properties_repository)
7
+ @parser = parser
8
+ @properties_repository = properties_repository
9
+ end
10
+
11
+ def extend
12
+ @parser.add_operator('property') do |parser, stack, context|
13
+ prop_name = stack.pop.to_s
14
+ property = @properties_repository.custom_property(prop_name)
15
+
16
+ if property.nil?
17
+ stack.push(TokenType::UNDEFINED)
18
+ else
19
+ value = property.value(context)
20
+ stack.push(value.nil? ? TokenType::UNDEFINED : value)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ module Rox
2
+ module Core
3
+ class TargetGroupRepository
4
+ def initialize
5
+ @target_groups = []
6
+ end
7
+
8
+ def target_groups=(target_groups)
9
+ @target_groups = target_groups
10
+ end
11
+
12
+ def target_group(id)
13
+ @target_groups.detect { |g| g.id == id }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module Rox
2
+ module Core
3
+ class CoreStack
4
+ def initialize
5
+ @items = []
6
+ end
7
+
8
+ def push(item)
9
+ @items << item
10
+ nil
11
+ end
12
+
13
+ def pop
14
+ @items.pop
15
+ end
16
+
17
+ def peek
18
+ @items[-1]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ require 'rox/core/entities/flag'
2
+ require 'rox/core/utils/type_utils'
3
+
4
+ module Rox
5
+ module Core
6
+ class EvaluationResult
7
+ attr_reader :value
8
+
9
+ def initialize(value)
10
+ @value = value
11
+ end
12
+
13
+ def bool_value
14
+ return false if value.nil?
15
+ return value if Utils.boolean?(value)
16
+ nil
17
+ end
18
+
19
+ def string_value
20
+ return value if value.is_a? String
21
+ return nil if value.nil?
22
+ return Flag::FLAG_TRUE_VALUE if value
23
+ return Flag::FLAG_FALSE_VALUE unless value
24
+ nil
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module Rox
2
+ module Core
3
+ Node = Struct.new(:type, :value)
4
+
5
+ module NodeTypes
6
+ RAND = 'Rand'.freeze
7
+ RATOR = 'Rator'.freeze
8
+ UNKNOWN = 'Unknown'.freeze
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,143 @@
1
+ require 'digest'
2
+ require 'rox/core/roxx/core_stack'
3
+ require 'rox/core/roxx/evaluation_result'
4
+ require 'rox/core/roxx/value_compare_extensions'
5
+ require 'rox/core/roxx/regular_expression_extensions'
6
+ require 'rox/core/roxx/tokenized_expression'
7
+ require 'rox/core/utils/type_utils'
8
+ require 'rox/core/logging/logging'
9
+
10
+ module Rox
11
+ module Core
12
+ class Parser
13
+ def initialize
14
+ @operators_map = {}
15
+ set_basic_operators
16
+ ValueCompareExtensions.new(self).extend
17
+ RegularExpressionExtensions.new(self).extend
18
+ end
19
+
20
+ def add_operator(oper, &block)
21
+ @operators_map[oper] = block
22
+ end
23
+
24
+ def evaluate_expression(expression, context = nil)
25
+ stack = CoreStack.new
26
+ tokens = TokenizedExpression.new(expression, @operators_map.keys).tokens
27
+ reverse_tokens = tokens.reverse
28
+ begin
29
+ reverse_tokens.each do |token|
30
+ node = token
31
+ if node.type == NodeTypes::RAND
32
+ stack.push(node.value)
33
+ elsif node.type == NodeTypes::RATOR
34
+ handler = @operators_map[node.value]
35
+ handler.call(self, stack, context) unless handler.nil?
36
+ else
37
+ return EvaluationResult.new(nil)
38
+ end
39
+ end
40
+
41
+ result = stack.pop
42
+ result = nil if result == TokenType::UNDEFINED
43
+
44
+ EvaluationResult.new(result)
45
+ rescue StandardError => ex
46
+ Logging.logger.warn("Roxx Exception: Failed evaluate expression: #{ex}")
47
+ EvaluationResult.new(nil)
48
+ end
49
+ end
50
+
51
+ def set_basic_operators
52
+ add_operator('isUndefined') do |parser, stack, context|
53
+ op1 = stack.pop
54
+ if op1.is_a?(TokenType)
55
+ stack.push(op1 == TokenType::UNDEFINED)
56
+ else
57
+ stack.push(false)
58
+ end
59
+ end
60
+
61
+ add_operator('now') do |parser, stack, context|
62
+ stack.push((Time.now.to_f * 1000).to_i)
63
+ end
64
+
65
+ add_operator('and') do |parser, stack, context|
66
+ op1 = stack.pop
67
+ op2 = stack.pop
68
+ op1 = false if op1 == TokenType::UNDEFINED
69
+ op2 = false if op2 == TokenType::UNDEFINED
70
+ raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1) && Utils.boolean?(op2)
71
+ stack.push(op1 && op2)
72
+ end
73
+
74
+ add_operator('or') do |parser, stack, context|
75
+ op1 = stack.pop
76
+ op2 = stack.pop
77
+ op1 = false if op1 == TokenType::UNDEFINED
78
+ op2 = false if op2 == TokenType::UNDEFINED
79
+ raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1) && Utils.boolean?(op2)
80
+ stack.push(op1 || op2)
81
+ end
82
+
83
+ add_operator('ne') do |parser, stack, context|
84
+ op1 = stack.pop
85
+ op2 = stack.pop
86
+ op1 = false if op1 == TokenType::UNDEFINED
87
+ op2 = false if op2 == TokenType::UNDEFINED
88
+ stack.push(op1 != op2)
89
+ end
90
+
91
+ add_operator('eq') do |parser, stack, context|
92
+ op1 = stack.pop
93
+ op2 = stack.pop
94
+ op1 = false if op1 == TokenType::UNDEFINED
95
+ op2 = false if op2 == TokenType::UNDEFINED
96
+ stack.push(op1 == op2)
97
+ end
98
+
99
+ add_operator('not') do |parser, stack, context|
100
+ op1 = stack.pop
101
+ op1 = false if op1 == TokenType::UNDEFINED
102
+ raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1)
103
+ stack.push(!op1)
104
+ end
105
+
106
+ add_operator('ifThen') do |parser, stack, context|
107
+ condition_expression = stack.pop
108
+ true_expression = stack.pop
109
+ false_expression = stack.pop
110
+ raise ArgumentError, 'should be boolean' unless Utils.boolean?(condition_expression)
111
+ if condition_expression
112
+ stack.push(true_expression)
113
+ else
114
+ stack.push(false_expression)
115
+ end
116
+ end
117
+
118
+ add_operator('inArray') do |parser, stack, context|
119
+ op1 = stack.pop
120
+ op2 = stack.pop
121
+ if op2.is_a?(Array)
122
+ stack.push(op2.include?(op1))
123
+ else
124
+ stack.push(false)
125
+ end
126
+ end
127
+
128
+ add_operator('md5') do |parser, stack, context|
129
+ op1 = stack.pop
130
+ raise ArgumentError, 'should be string' unless op1.is_a?(String)
131
+ stack.push(Digest::MD5.hexdigest(op1))
132
+ end
133
+
134
+ add_operator('concat') do |parser, stack, context|
135
+ op1 = stack.pop
136
+ op2 = stack.pop
137
+ raise ArgumentError, 'should be string' unless op1.is_a?(String) && op2.is_a?(String)
138
+ stack.push("#{op1}#{op2}")
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,33 @@
1
+ module Rox
2
+ module Core
3
+ class RegularExpressionExtensions
4
+ def initialize(parser)
5
+ @parser = parser
6
+ end
7
+
8
+ def extend
9
+ @parser.add_operator('match') do |parser, stack, context|
10
+ text = stack.pop
11
+ pattern = stack.pop
12
+ flags = stack.pop
13
+ raise ArgumentError, 'should be string' unless text.is_a?(String) && pattern.is_a?(String) && flags.is_a?(String)
14
+
15
+ options = 0
16
+ flags.each_char do |flag|
17
+ case flag
18
+ when 'i'
19
+ options |= Regexp::IGNORECASE
20
+ when 'x'
21
+ options |= Regexp::EXTENDED
22
+ when 'm'
23
+ options |= Regexp::MULTILINE
24
+ end
25
+ end
26
+
27
+ matched = !Regexp.new(pattern, options).match(text).nil?
28
+ stack.push(matched)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,68 @@
1
+ module Rox
2
+ module Core
3
+ class StringTokenizer
4
+ def initialize(text, delim, return_delims)
5
+ @current_position = 0
6
+ @new_position = -1
7
+ @text = text
8
+ @max_position = text.length
9
+ @delimiters = delim
10
+ @ret_delims = return_delims
11
+ end
12
+
13
+ def skip_delimiters(start_pos)
14
+ raise ArgumentError, 'delimiters is nil' if @delimiters.nil?
15
+
16
+ position = start_pos
17
+ while !@ret_delims && position < @max_position
18
+ c = @text[position]
19
+ break unless delimiter?(c)
20
+ position += 1
21
+ end
22
+ position
23
+ end
24
+
25
+ def scan_token(start_pos)
26
+ position = start_pos
27
+ while position < @max_position
28
+ c = @text[position]
29
+ break if delimiter?(c)
30
+ position += 1
31
+ end
32
+
33
+ if @ret_delims && start_pos == position
34
+ c = @text[position]
35
+ position += 1 if delimiter?(c)
36
+ end
37
+
38
+ position
39
+ end
40
+
41
+ def delimiter?(char)
42
+ @delimiters.include?(char)
43
+ end
44
+
45
+ def more_tokens?
46
+ @new_position = skip_delimiters(@current_position)
47
+ @new_position < @max_position
48
+ end
49
+
50
+ def next_token(delim = nil)
51
+ delims_changed = false
52
+ unless delim.nil?
53
+ @delimiters = delim
54
+ delims_changed = true
55
+ end
56
+
57
+ @current_position = @new_position >= 0 && !delims_changed ? @new_position : skip_delimiters(@current_position)
58
+ @new_position = -1
59
+
60
+ raise ArgumentError, 'invalid operation' if @current_position >= @max_position
61
+
62
+ start = @current_position
63
+ @current_position = scan_token(@current_position)
64
+ @text[start...@current_position]
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,14 @@
1
+ module Rox
2
+ module Core
3
+ module Symbols
4
+ ROXX_UNDEFINED = 'undefined'.freeze
5
+ ROXX_TRUE = 'true'.freeze
6
+ ROXX_FALSE = 'false'.freeze
7
+ ROXX_EMPTY_STRING = '""'.freeze
8
+ ROXX_STRING_TYPE = 'StringType'.freeze
9
+ ROXX_BOOL_TYPE = 'BooleanType'.freeze
10
+ ROXX_NUMBER_TYPE = 'NumberType'.freeze
11
+ ROXX_UNDEFINED_TYPE = 'UndefinedType'.freeze
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ require 'rox/core/roxx/symbols'
2
+
3
+ module Rox
4
+ module Core
5
+ class TokenType
6
+ attr_accessor :text, :pattern
7
+
8
+ def self.from_token(token)
9
+ unless token.nil?
10
+ tested_token = token.downcase
11
+ [TokenType::STRING, TokenType::NUMBER, TokenType::BOOLEAN, TokenType::UNDEFINED].each do |token_type|
12
+ return token_type unless token_type.pattern.match(tested_token).nil?
13
+ end
14
+ end
15
+ TokenType::NOT_A_TYPE
16
+ end
17
+
18
+ def initialize(text, pattern)
19
+ @text = text
20
+ @pattern = Regexp.new(pattern)
21
+ end
22
+
23
+ NOT_A_TYPE = TokenType.new('NOT_A_TYPE', '')
24
+ STRING = TokenType.new(Symbols::ROXX_STRING_TYPE, '"((\\\\.)|[^\\\\"])*"')
25
+ NUMBER = TokenType.new(Symbols::ROXX_NUMBER_TYPE, '[\\-]{0,1}\\d+[\\.]\\d+|[\\-]{0,1}\\d+')
26
+ BOOLEAN = TokenType.new(Symbols::ROXX_BOOL_TYPE, "#{Symbols::ROXX_TRUE}|#{Symbols::ROXX_FALSE}")
27
+ UNDEFINED = TokenType.new(Symbols::ROXX_UNDEFINED_TYPE, Symbols::ROXX_UNDEFINED)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,119 @@
1
+ require 'rox/core/roxx/string_tokenizer'
2
+ require 'rox/core/roxx/node'
3
+ require 'rox/core/roxx/symbols'
4
+ require 'rox/core/roxx/token_type'
5
+
6
+ module Rox
7
+ module Core
8
+ class TokenizedExpression
9
+ DICT_START_DELIMITER = '{'.freeze
10
+ DICT_END_DELIMITER = '}'.freeze
11
+ ARRAY_START_DELIMITER = '['.freeze
12
+ ARRAY_END_DELIMITER = ']'.freeze
13
+ TOKEN_DELIMITERS = "{}[]():, \t\r\n\"".freeze
14
+ PRE_POST_STRING_CHAR = ''.freeze
15
+ STRING_DELIMITER = '"'.freeze
16
+ ESCAPED_QUOTE = '\\"'.freeze
17
+ ESCAPED_QUOTE_PLACEHOLDER = '\\RO_Q'.freeze
18
+
19
+ def initialize(expression, operators)
20
+ @expression = expression
21
+ @operators = operators
22
+ @result_list = nil
23
+ @array_accumulator = nil
24
+ @dict_accumulator = nil
25
+ @dict_key = nil
26
+ end
27
+
28
+ def tokens
29
+ tokenize(@expression)
30
+ end
31
+
32
+ def push_node(node)
33
+ if !@dict_accumulator.nil? && @dict_key.nil?
34
+ @dict_key = node.value.to_s
35
+ elsif !@dict_accumulator.nil? && !@dict_key.nil?
36
+ @dict_accumulator[@dict_key] = node.value
37
+ @dict_key = nil
38
+ elsif !@array_accumulator.nil?
39
+ @array_accumulator << node.value
40
+ else
41
+ @result_list << node
42
+ end
43
+ end
44
+
45
+ def tokenize(expression)
46
+ @result_list = []
47
+ @array_accumulator = nil
48
+ @dict_accumulator = nil
49
+ @dict_key = nil
50
+
51
+ delimiters_to_use = TokenizedExpression::TOKEN_DELIMITERS
52
+ normalized_expression = expression.gsub(TokenizedExpression::ESCAPED_QUOTE, TokenizedExpression::ESCAPED_QUOTE_PLACEHOLDER)
53
+ tokenizer = StringTokenizer.new(normalized_expression, delimiters_to_use, true)
54
+
55
+ token = nil
56
+ while tokenizer.more_tokens?
57
+ prev_token = token
58
+ token = tokenizer.next_token(delimiters_to_use)
59
+ in_string = delimiters_to_use == TokenizedExpression::STRING_DELIMITER
60
+
61
+ if !in_string && token == TokenizedExpression::DICT_START_DELIMITER
62
+ @dict_accumulator = {}
63
+ elsif !in_string && token == TokenizedExpression::DICT_END_DELIMITER
64
+ dict_result = @dict_accumulator
65
+ @dict_accumulator = nil
66
+ push_node(node_from_dict(dict_result))
67
+ elsif !in_string && token == TokenizedExpression::ARRAY_START_DELIMITER
68
+ @array_accumulator = []
69
+ elsif !in_string && token == TokenizedExpression::ARRAY_END_DELIMITER
70
+ array_result = @array_accumulator
71
+ @array_accumulator = nil
72
+ push_node(node_from_array(array_result))
73
+ elsif token == TokenizedExpression::STRING_DELIMITER
74
+ push_node(node_from_token(Symbols::ROXX_EMPTY_STRING)) if prev_token == TokenizedExpression::STRING_DELIMITER
75
+ delimiters_to_use = in_string ? TokenizedExpression::TOKEN_DELIMITERS : TokenizedExpression::STRING_DELIMITER
76
+ else
77
+ if delimiters_to_use == TokenizedExpression::STRING_DELIMITER
78
+ push_node(Node.new(NodeTypes::RAND, token.gsub(TokenizedExpression::ESCAPED_QUOTE_PLACEHOLDER, TokenizedExpression::ESCAPED_QUOTE)))
79
+ elsif !TokenizedExpression::TOKEN_DELIMITERS.include?(token) && token != TokenizedExpression::PRE_POST_STRING_CHAR
80
+ push_node(node_from_token(token))
81
+ end
82
+ end
83
+ end
84
+
85
+ @result_list
86
+ end
87
+
88
+ def node_from_array(items)
89
+ Node.new(NodeTypes::RAND, items)
90
+ end
91
+
92
+ def node_from_dict(items)
93
+ Node.new(NodeTypes::RAND, items)
94
+ end
95
+
96
+ def node_from_token(token)
97
+ return Node.new(NodeTypes::RATOR, token) if @operators.include?(token)
98
+ return Node.new(NodeTypes::RAND, true) if token == Symbols::ROXX_TRUE
99
+ return Node.new(NodeTypes::RAND, false) if token == Symbols::ROXX_FALSE
100
+ return Node.new(NodeTypes::RAND, TokenType::UNDEFINED) if token == Symbols::ROXX_UNDEFINED
101
+
102
+ token_type = TokenType.from_token(token)
103
+ return Node.new(NodeTypes::RAND, token[1...-1]) if token_type == TokenType::STRING
104
+ if token_type == TokenType::NUMBER
105
+ begin
106
+ return Node.new(NodeTypes::RAND, Integer(token))
107
+ rescue ArgumentError
108
+ begin
109
+ return Node.new(NodeTypes::RAND, Float(token))
110
+ rescue ArgumentError => ex
111
+ raise ArgumentError, "Excepted Number, got '#{token}' (#{token_type}): #{ex}"
112
+ end
113
+ end
114
+ end
115
+ Node.new(NodeTypes::UNKNOWN, nil)
116
+ end
117
+ end
118
+ end
119
+ end