Class: RegexOperator
- Inherits:
-
Object
- Object
- RegexOperator
- Defined in:
- lib/ruby_grammar_builder/regex_operator.rb
Overview
RegexOperator is used to provide complicated combining behavior that is not possible to implement in PatternBase#do_evaluate_self
Each PatternBase when evaluated produces a RegexOperator and a regexstring RegexOperator::evaluate takes that array and produces a single regexstring
Direct Known Subclasses
Instance Attribute Summary collapse
-
#association ⇒ :left, :right
right associative is processed first.
-
#precedence ⇒ number
The precedence of the operator, lower numbers are processed earlier.
Class Method Summary collapse
-
.evaluate(arr) ⇒ String
Evaluate the array of RegexStrings and RegexOperators.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
Compares for equality.
-
#do_evaluate_self(arr_left, arr_right) ⇒ Array<RegexOperator,String>
abstract
<Description>.
-
#fold_left(arr) ⇒ Array<(String,Array<String,RegexOperator>)>
<Description>.
-
#fold_right(arr) ⇒ Array<(String,Array<String,RegexOperator>)>
<Description>.
Instance Attribute Details
#association ⇒ :left, :right
right associative is processed first
47 48 49 |
# File 'lib/ruby_grammar_builder/regex_operator.rb', line 47 def association @association end |
#precedence ⇒ number
Returns The precedence of the operator, lower numbers are processed earlier.
44 45 46 |
# File 'lib/ruby_grammar_builder/regex_operator.rb', line 44 def precedence @precedence end |
Class Method Details
.evaluate(arr) ⇒ String
Evaluate the array of RegexStrings and RegexOperators
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/ruby_grammar_builder/regex_operator.rb', line 56 def self.evaluate(arr) # grab all operators and sort by precedence and association ops = arr.reject { |v| v.is_a?(String) }.sort do |a, b| if a.precedence == b.precedence next 0 if a.association == b.association next -1 if a.association == :left next 1 end a.precedence - b.precedence end ops.each do |op| # TODO: consolidate left and right paths split = [] if op.association == :right elems = break_right(arr) { |elem| elem == op } next if elems[0].empty? split = [elems[0][0..-2], elems[1]] else elems = break_left(arr) { |elem| elem == op } next if elems[1].empty? split = [elems[0], elems[1][1..-1]] end arr = op.do_evaluate_self(split[0], split[1]) end if arr.length != 1 puts "evaluate did not result in a length of 1" raise "see above error" end arr.first end |
Instance Method Details
#==(other) ⇒ Boolean
Compares for equality
117 118 119 120 121 122 123 |
# File 'lib/ruby_grammar_builder/regex_operator.rb', line 117 def ==(other) return false unless other.instance_of?(self.class) return false unless @precedence == other.precedence return false unless @association == other.association true end |
#do_evaluate_self(arr_left, arr_right) ⇒ Array<RegexOperator,String>
override to provide evaluate the operator
arr_left and arr_right contain the entire parse array use #fold_left and #fold_right to collect only the portions that this operator is responsible for
<Description>
106 107 108 |
# File 'lib/ruby_grammar_builder/regex_operator.rb', line 106 def do_evaluate_self(arr_left, arr_right) # rubocop:disable Lint/UnusedMethodArgument raise NotImplementedError end |
#fold_left(arr) ⇒ Array<(String,Array<String,RegexOperator>)>
the leftover portion is not suitable for evaluation (it begins or ends with a RegexOperator or is an empty string)
<Description>
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/ruby_grammar_builder/regex_operator.rb', line 134 def fold_left(arr) # go left until: # - the precedence of self is greater than the token being tested # - the precedence is the same and the association of self is :left fold = (arr.reverse.take_while do |t| next true if t.is_a? String next true if t.precedence > @precedence next false if t.precedence < @precedence next false if @association == :left true end).reverse if fold.empty? || !fold[0].is_a?(String) || !fold[-1].is_a?(String) puts "fold_left generated an invalid fold expression" raise "see above error" end # [0..-(fold.length+1)] peels the elements that are a part of fold off the end # of arr [RegexOperator.evaluate(fold), arr[0..-(fold.length+1)]] end |
#fold_right(arr) ⇒ Array<(String,Array<String,RegexOperator>)>
the leftover portion is not suitable for evaluation (it begins or ends with a RegexOperator or is an empty string)
<Description>
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/ruby_grammar_builder/regex_operator.rb', line 161 def fold_right(arr) # go right until: # - the precedence of self is greater than the token being tested # - the precedence is the same and the association of self is :right fold = arr.take_while do |t| next true if t.is_a? String next true if t.precedence > @precedence next false if t.precedence < @precedence next false if @association == :right true end if fold.empty? || !fold[0].is_a?(String) || !fold[-1].is_a?(String) puts "fold_right generated an invalid fold expression" raise "see above error" end [RegexOperator.evaluate(fold), arr[(fold.length)..-1]] end |