Class: Qipowl::Bowlers::Bowler

Inherits:
Object
  • Object
show all
Includes:
TypoLogging
Defined in:
lib/qipowl/core/bowler.rb

Overview

Base class for all the parsers.

Technically it may be instantiated, but that’s meaningless. Main operation method for it and all the descendants is #parse. It sequentially executes following private methods:

  • #defreeze
  • #roast
  • #serveup

Normally the developer does not need to interfere the #roast method which proceeds the input string. To prepare the input for +evaluation+ one overwrites #defreeze, for some afterwork the #serveup method is here.

Descendants are supposed to overwrite #method_missing for some custom processing and introduce DSL methods, which will be executed by eval inside the #roast method.

Instance variables :in and :out are here to gain an access to the last interpreted input string and the result of evaluation respectively.

Direct Known Subclasses

Cmd, Html, Ispru

Constant Summary collapse

SEPARATOR =

Internal constant for joining/splitting the strings during processing. Override on your own risk. I can′t imagine why you would need to do so.

$, || ' '

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TypoLogging

#logger, logger

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

If somebody needs to interfere the standard processing, she supposed to introduce special_handler method. The descendants will be processed before standard operation (which in fact simply collects words within an array one by one.)



70
71
72
73
74
# File 'lib/qipowl/core/bowler.rb', line 70

def method_missing method, *args, &block
  method, *args = special_handler(method, *args, &block) \
    if self.private_methods.include?(:special_handler)
  [method, args].flatten
end

Instance Attribute Details

#inObject (readonly)

Returns the value of attribute in.



40
41
42
# File 'lib/qipowl/core/bowler.rb', line 40

def in
  @in
end

#outObject (readonly)

Returns the value of attribute out.



40
41
42
# File 'lib/qipowl/core/bowler.rb', line 40

def out
  @out
end

Class Method Details

.const_missing(name) ⇒ Object

TODO:

This fails to do with DSLing words, beginning with capitals :-(

Everything is a DSL, remember? Even constants.

Returns:

  • the constant name as is



61
62
63
64
# File 'lib/qipowl/core/bowler.rb', line 61

def self.const_missing name
  raise "There was CONST [#{name}] met. Stupid programming error."
  name
end

Instance Method Details

#add_entity(section, key, value, enclosure_value = null) ⇒ Object

Adds new +entity+ in the section specified. E. g., call to

add_spice :linewide, :

in HTML implementation adds a support for specifying something like:

which is to be converted to the following:

<degrees>
  <deg>15</deg>
  <deg>30</deg>
  <deg>45</deg>
</degrees>

Parameters:

  • section (Symbol)

    the section (it must be one of Mapping.SPICES) to add new key to

  • key (Symbol)

    the name for the key

  • value (Symbol)

    the value

  • enclosure_value (Symbol) (defaults to: null)

    optional value to be added for the key into enclosures section



99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/qipowl/core/bowler.rb', line 99

def add_entity section, key, value, enclosure_value = null
  if (tags = self.class.const_get("#{section.upcase}_TAGS"))
    key = key.bowl.to_sym
    tags[key] = value.to_sym
    self.class.const_get("ENCLOSURES_TAGS")[key] = enclosure_value.to_sym if enclosure_value
    self.class.const_get("ENTITIES")[section.to_sym][key] = value.to_sym
    self.class.class_eval %Q{
      alias_method :#{key}, :∀_#{section}
    } # unless self.class.instance_methods(true).include?(key.bowl)
    @shadows = nil
  else
    logger.warn "Trying to add key “#{key}” in an invalid section “#{section}”. Ignoring…"
  end
end

#block(str) ⇒ Object (private)

Prepares blocks in the input for the execution



220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/qipowl/core/bowler.rb', line 220

def block str
  return str unless self.class.const_defined?(:BLOCK_TAGS)
  result = str.dup
  self.class::BLOCK_TAGS.each { |tag, value|
    result.gsub!(/(#{tag})(.*?)(?:#{tag}|\Z)/m) { |m|
      %Q{

#{$1} #{Base64.encode64($2).carriage(false).bowl}

}
    }
  }
  result
end

#custom(str) ⇒ Object (private)

Prepares customs in the input for the execution



236
237
238
239
240
241
242
243
# File 'lib/qipowl/core/bowler.rb', line 236

def custom str
  return str unless self.class.const_defined?(:CUSTOM_TAGS)
  result = str.dup
  self.class::CUSTOM_TAGS.each { |tag, value|
    result.gsub!(/#{tag}/m, value)
  }
  result
end

#execute(str) ⇒ Object



46
47
48
# File 'lib/qipowl/core/bowler.rb', line 46

def execute str
  @out = (serveup roast defreeze @in = str)
end

#grip(str) ⇒ Object (private)

Prepares grips in the input for the execution FIX<E There is a problem: we append a trailing space, need to remove it later!!



247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/qipowl/core/bowler.rb', line 247

def grip str
  return str unless self.class.const_defined?(:GRIP_TAGS)
  result = str.bowl
  self.class::GRIP_TAGS.each { |tag, value|
    result.gsub!(/(?:#{tag})(.*?)(?:#{tag})/m) {
      next if (args = $1).vacant?
      tag = value[:marker] if Hash === value && value[:marker]
      "⌦ #{tag} #{args}#{tag}∎⌫"
    }
  }
  result.unbowl
end

#remove_entity(entity) ⇒ Object

Removes key from both Mapping.SPICES and Mapping.SALT. See #add_spice

Parameters:

  • entity (Symbol)

    the key to be removed



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/qipowl/core/bowler.rb', line 117

def remove_entity entity
  key = entity.to_sym
  Qipowl::ENTITIES.each { |section|
    next unless (curr_sect = self.class.const_get("#{section.upcase}_TAGS") rescue nil)
    curr_tag = send(:"∃_#{section}", key)
    next unless curr_tag

    curr_sect.delete key
    self.class.const_get("ENCLOSURES_TAGS").delete key
    self.class.const_get("ENTITIES")[section.to_sym].delete key

    self.class.class_eval %Q{
      remove_method :#{key.bowl}
    }
    @shadows = nil
  }
end

#respond_to?(method, incl_priv = false) ⇒ Boolean

Everything is a DSL, remember?

Returns:

  • (Boolean)

    true



53
54
55
# File 'lib/qipowl/core/bowler.rb', line 53

def respond_to? method, incl_priv = false
  true
end

#split(str) ⇒ Object (private)



260
261
262
263
264
# File 'lib/qipowl/core/bowler.rb', line 260

def split str
  (block str).split(/\R{2,}/).map { |para|
    (grip custom para)
  }
end