class MSFLVisitors::Parsers::MSFLParser
Constants
- OPERATORS_TO_NODE_CLASS
Attributes
dataset[RW]
Public Class Methods
new(dataset = nil)
click to toggle source
# File lib/msfl_visitors/parsers/msfl_parser.rb, line 43 def initialize(dataset = nil) @dataset = dataset end
Public Instance Methods
parse(obj, lhs = false)
click to toggle source
# File lib/msfl_visitors/parsers/msfl_parser.rb, line 22 def parse(obj, lhs = false) case obj when Float, Fixnum MSFLVisitors::Nodes::Number.new obj when Hash parse_hash obj, lhs when MSFL::Types::Set parse_set obj, lhs when Symbol, String, NilClass MSFLVisitors::Nodes::Word.new obj.to_s else fail ArgumentError, "Invalid NMSFL, unable to parse type: #{obj.class}." end end
Private Instance Methods
hash_dispatch(key, value, lhs = false)
click to toggle source
A key/value pair needs to be parsed and handled while iterating across the Hash that the key/value pair belong to lhs is for when the field is a parent of the actual operator node ex. { year: { gte: 2010 } } needs to be converted to (gte(year, 2010)) – infix operators to RPN
# File lib/msfl_visitors/parsers/msfl_parser.rb, line 76 def hash_dispatch(key, value, lhs = false) if OPERATORS_TO_NODE_CLASS.include? key # Detect the node type, forward the lhs if it was passed in (essentially when the operator is a binary op) case key when :foreign args = [hash_dispatch(:dataset, value[:dataset]), hash_dispatch(:filter, value[:filter])] when :partial args = [hash_dispatch(:given, value[:given]), MSFLVisitors::Nodes::NamedValue.new(MSFLVisitors::Nodes::Word.new("partial"), hash_dispatch(:filter, value[:filter]))] when :dataset args = [value] when :filter, :given # Explicit Filter # ex { foreign: { dataset: "person", filter: { age: 25 } } } # ex { partial: { given: { make: "Toyota" }, filter: { avg_age: 10 } } } args = value.map { |k,v| hash_dispatch(k,v) } # !!! THE CURRENT PROBLEM IS HERE!! need to test / update for a foreign in a partial's given else # fall back to a Filter Node args = [lhs, parse(value)] if lhs args ||= [parse(value)] end OPERATORS_TO_NODE_CLASS[key].new(*args) else # the key is a field # there are three possible scenarios when they key is a field # 1. the implicit equality scenario, where the right side is a value # { make: "toyota" } # # 2. the explicit comparison scenario # { value: { gte: 2000 } } # # 3. the containment scenario # { model: { in: ["Corolla", "Civic", "Mustang"] } } # # 2 & 3 are just hashes and can be parsed using the same method lhs = MSFLVisitors::Nodes::Field.new key # the node type generated by parsing value can use the lhs node when appropriate and otherwise ignore it # although I can't think of a situation when it would ignore it. rhs = parse value, lhs if rhs.is_a? MSFLVisitors::Nodes::Value MSFLVisitors::Nodes::Equal.new lhs, rhs else rhs end end end
parse_hash(obj, lhs = false)
click to toggle source
# File lib/msfl_visitors/parsers/msfl_parser.rb, line 51 def parse_hash(obj, lhs = false) nodes = Array.new obj.each do |k, v| nodes << hash_dispatch(k, v, lhs) end # If there's exactly one node in nodes and it's a filter node we don't want to wrap it in yet # another filter node, so we just return the filter node if nodes.count == 1 && nodes.first.is_a?(MSFLVisitors::Nodes::Filter) nodes.first else MSFLVisitors::Nodes::Filter.new nodes end end
parse_set(obj, lhs = false)
click to toggle source
# File lib/msfl_visitors/parsers/msfl_parser.rb, line 65 def parse_set(obj, lhs = false) nodes = MSFL::Types::Set.new([]) obj.each do |item| nodes << parse(item) end MSFLVisitors::Nodes::Set.new nodes end