class DDQL::Operator
Attributes
associativity[R]
name[R]
precedence[R]
return_type[R]
symbol[R]
type[R]
Public Class Methods
new(symbol, name, type, precedence, right, return_type)
click to toggle source
# File lib/ddql/operator.rb, line 5 def initialize(symbol, name, type, precedence, right, return_type) @symbol = symbol @name = name @type = type @precedence = precedence @associativity = right ? :right : :left @return_type = return_type end
Public Instance Methods
any_type?()
click to toggle source
# File lib/ddql/operator.rb, line 14 def any_type? return_type == :any end
boolean?()
click to toggle source
# File lib/ddql/operator.rb, line 18 def boolean? return_type == :boolean end
comparison?()
click to toggle source
# File lib/ddql/operator.rb, line 22 def comparison? (infix? || postfix?) && boolean? end
complex_comparison?()
click to toggle source
# File lib/ddql/operator.rb, line 26 def complex_comparison? comparison? && !simple_comparison? end
infix?()
click to toggle source
# File lib/ddql/operator.rb, line 30 def infix? @name == :infixoperator || @type == :infix end
left?()
click to toggle source
# File lib/ddql/operator.rb, line 34 def left? !right? end
math?()
click to toggle source
# File lib/ddql/operator.rb, line 38 def math? math_op?(symbol) end
parse(parser, token, expression: nil)
click to toggle source
# File lib/ddql/operator.rb, line 42 def parse(parser, token, expression: nil) case type when :infix; parse_infix(parser, token, expression) when :prefix; parse_prefix(parser, token, expression) when :postfix; parse_postfix(parser, token, expression) else raise "unsupported operator type[#{type}]" end end
pattern()
click to toggle source
# File lib/ddql/operator.rb, line 52 def pattern symbol end
postfix?()
click to toggle source
# File lib/ddql/operator.rb, line 56 def postfix? @name == :postfixoperator || @type == :postfix end
prefix?()
click to toggle source
# File lib/ddql/operator.rb, line 60 def prefix? @name == :prefixoperator || @type == :prefix end
register(hash)
click to toggle source
# File lib/ddql/operator.rb, line 64 def register(hash) hash[symbol] = self hash end
right?()
click to toggle source
# File lib/ddql/operator.rb, line 69 def right? @associativity == :right end
simple_comparison?()
click to toggle source
# File lib/ddql/operator.rb, line 73 def simple_comparison? case symbol when "==", "=", "!=", "<=", "<", ">=", ">" true else false end end
type?(incoming)
click to toggle source
# File lib/ddql/operator.rb, line 82 def type?(incoming) type == incoming end
Private Instance Methods
boolean_stmt(left, op, right)
click to toggle source
# File lib/ddql/operator.rb, line 88 def boolean_stmt(left, op, right) # the following avoids unnecessarily deeply nested statements while left.key?(:lstatement) && !left.key?(:rstatement) left = left[:lstatement] end while right.key?(:lstatement) && !right.key?(:rstatement) right = right[:lstatement] end { lstatement: left, boolean_operator: op[:op], rstatement: right, } end
math_op?(str)
click to toggle source
# File lib/ddql/operator.rb, line 103 def math_op?(str) case str when '+', '-', '*', '/', '%', '^' true else false end end
merged_negation(left, right, op)
click to toggle source
# File lib/ddql/operator.rb, line 112 def merged_negation(left, right, op) needs_statement_wrapper = lambda do |expr| (expr.key?(:lstatement) && expr.key?(:op_not)) || !expr.key?(:lstatement) end left = {lstatement: left} if needs_statement_wrapper[left] right = {rstatement: right} if needs_statement_wrapper[right] left.merge(boolean_operator: op[:op]).merge(right) end
parse_infix(parser, token, expression)
click to toggle source
# File lib/ddql/operator.rb, line 122 def parse_infix(parser, token, expression) precedence = self.precedence precedence -= 0.05 if right? next_expression = parser.parse(precedence: precedence) op_expression = token.as_hash if math? && next_expression&.dig(:left, :factor) && next_expression.size == 1 return op_expression.merge(left: expression, right: next_expression[:left]) end if token.and? || token.or? return boolean_stmt(expression, op_expression, next_expression) end if expression.key?(:op_not) || next_expression.key?(:op_not) return merged_negation(expression, next_expression, op_expression) end if next_expression&.key?(:lstatement) && expression&.key?(:lstatement) left = expression.merge(boolean_operator: op_expression[:op], rstatement: next_expression[:lstatement]) return next_expression.key?(:rstatement) ? left.merge( boolean_operator: next_expression[:boolean_operator][:op], rstatement: next_expression[:rstatement] ) : left end expression = {left: expression} unless redundant?(expression, :left) next_expression = {right: next_expression} unless redundant?(next_expression, :right) expression.merge(op_expression).merge(next_expression) end
parse_postfix(parser, token, expression)
click to toggle source
# File lib/ddql/operator.rb, line 155 def parse_postfix(parser, token, expression) op_expression = token.as_hash if expression && !expression.empty? expression = {left: expression} unless expression.key?(:left) expression.merge(op_expression) else op_expression end end
parse_prefix(parser, token, _expression)
click to toggle source
# File lib/ddql/operator.rb, line 165 def parse_prefix(parser, token, _expression) op_expression = token.type.as_hash(token.data) next_expression = parser.parse(precedence: precedence) if next_expression.key?(:lstatement) && !next_expression.key?(:rstatement) next_expression = next_expression[:lstatement] elsif next_expression.key?(:rstatement) && !next_expression.key?(:lstatement) next_expression = next_expression[:rstatement] elsif op_expression[:op].key?(:op_not) && next_expression.key?(:op_not) next_expression.delete(:op_not) return next_expression end op_expression[:op].merge(next_expression) end
redundant?(expression, *keys)
click to toggle source
# File lib/ddql/operator.rb, line 179 def redundant?(expression, *keys) expression.keys == keys end