class Rox::Core::Parser
Attributes
global_context[RW]
Public Class Methods
new(user_unhandled_error_invoker)
click to toggle source
# File lib/rox/core/roxx/parser.rb, line 17 def initialize(user_unhandled_error_invoker) @operators_map = {} @global_context = nil set_basic_operators @user_unhandled_error_invoker = user_unhandled_error_invoker ValueCompareExtensions.new(self).extend RegularExpressionExtensions.new(self).extend end
Public Instance Methods
add_operator(operator, &block)
click to toggle source
# File lib/rox/core/roxx/parser.rb, line 26 def add_operator(operator, &block) @operators_map[operator] = block end
evaluate_expression(expression, context = nil)
click to toggle source
# File lib/rox/core/roxx/parser.rb, line 30 def evaluate_expression(expression, context = nil) stack = CoreStack.new tokens = TokenizedExpression.new(expression, @operators_map.keys).tokens reverse_tokens = tokens.reverse begin reverse_tokens.each do |token| node = token case node.type when NodeTypes::RAND stack.push(node.value) when NodeTypes::RATOR handler = @operators_map[node.value] handler&.call(self, stack, context) else return EvaluationResult.new(nil) end end result = stack.pop result = nil if result == TokenType::UNDEFINED EvaluationResult.new(result) rescue Rox::Core::UserspaceHandlerException => e @user_unhandled_error_invoker.invoke(e.exception_source, e.exception_trigger, e.exception) Logging.logger.warn("Roxx Exception: Failed evaluate expression, user unhandled expression: #{e}") EvaluationResult.new(nil) rescue StandardError => e Logging.logger.warn("Roxx Exception: Failed evaluate expression: #{e}") EvaluationResult.new(nil) end end
set_basic_operators()
click to toggle source
# File lib/rox/core/roxx/parser.rb, line 62 def set_basic_operators add_operator('isUndefined') do |_parser, stack, _context| op1 = stack.pop if op1.is_a?(TokenType) stack.push(op1 == TokenType::UNDEFINED) else stack.push(false) end end add_operator('now') do |_parser, stack, _context| stack.push((Time.now.to_f * 1000).to_i) end add_operator('and') do |_parser, stack, _context| op1 = stack.pop op2 = stack.pop op1 = false if op1 == TokenType::UNDEFINED op2 = false if op2 == TokenType::UNDEFINED raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1) && Utils.boolean?(op2) stack.push(op1 && op2) end add_operator('or') do |_parser, stack, _context| op1 = stack.pop op2 = stack.pop op1 = false if op1 == TokenType::UNDEFINED op2 = false if op2 == TokenType::UNDEFINED raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1) && Utils.boolean?(op2) stack.push(op1 || op2) end add_operator('ne') do |_parser, stack, _context| op1 = stack.pop op2 = stack.pop op1 = false if op1 == TokenType::UNDEFINED op2 = false if op2 == TokenType::UNDEFINED stack.push(op1 != op2) end add_operator('eq') do |_parser, stack, _context| op1 = stack.pop op2 = stack.pop op1 = false if op1 == TokenType::UNDEFINED op2 = false if op2 == TokenType::UNDEFINED stack.push(op1 == op2) end add_operator('not') do |_parser, stack, _context| op1 = stack.pop op1 = false if op1 == TokenType::UNDEFINED raise ArgumentError, 'should be boolean' unless Utils.boolean?(op1) stack.push(!op1) end add_operator('ifThen') do |_parser, stack, _context| condition_expression = stack.pop true_expression = stack.pop false_expression = stack.pop raise ArgumentError, 'should be boolean' unless Utils.boolean?(condition_expression) if condition_expression stack.push(true_expression) else stack.push(false_expression) end end add_operator('inArray') do |_parser, stack, _context| op1 = stack.pop op2 = stack.pop if op2.is_a?(Array) stack.push(op2.include?(op1)) else stack.push(false) end end add_operator('md5') do |_parser, stack, _context| op1 = stack.pop if op1.is_a?(String) stack.push(Digest::MD5.hexdigest(op1)) else stack.push(TokenType::UNDEFINED) end end add_operator('concat') do |_parser, stack, _context| op1 = stack.pop op2 = stack.pop if op1.is_a?(String) && op2.is_a?(String) stack.push("#{op1}#{op2}") else stack.push(TokenType::UNDEFINED) end end add_operator('b64d') do |_parser, stack, _context| op1 = stack.pop if op1.is_a?(String) decoded = Base64.decode64(op1) decoded = decoded.force_encoding('UTF-8') stack.push(decoded) else stack.push(TokenType::UNDEFINED) end end end