Class: MPS::Engines::Parser
- Inherits:
-
Object
- Object
- MPS::Engines::Parser
- Defined in:
- lib/mps/engines/mps.rb
Defined Under Namespace
Classes: Unknown
Instance Attribute Summary collapse
-
#element_classes ⇒ Object
readonly
Returns the value of attribute element_classes.
-
#interpolator_classes ⇒ Object
readonly
Returns the value of attribute interpolator_classes.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
Class Method Summary collapse
-
._apply_interpolations(elements, interpolator_classes) ⇒ Object
Apply registered interpolators to the body_str of each element.
-
.matched_element_class(str, element_classes) ⇒ Object
Returns the element class whose SIGNATURE_REGEX matches
str, or nil. -
.parse_mps_file_to_elements_hash(mps_file_path, element_classes, interpolator_classes: []) ⇒ Object
(also: parse_mps_file_to_elments_hash)
Parses
mps_file_pathinto a flat hash of ref-path => element instances.
Instance Method Summary collapse
-
#initialize(config) ⇒ Parser
constructor
A new instance of Parser.
Constructor Details
#initialize(config) ⇒ Parser
Returns a new instance of Parser.
15 16 17 18 19 20 21 22 23 24 |
# File 'lib/mps/engines/mps.rb', line 15 def initialize(config) @config = config @element_classes = ::MPS::Elements.constants .map { |k| ::MPS::Elements.const_get(k) } .select { |x| x.class == Class } @interpolator_classes = ::MPS::Interpolators.constants .map { |k| ::MPS::Interpolators.const_get(k) } .select { |x| x.class == Class } @logger = @config.logger end |
Instance Attribute Details
#element_classes ⇒ Object (readonly)
Returns the value of attribute element_classes.
12 13 14 |
# File 'lib/mps/engines/mps.rb', line 12 def element_classes @element_classes end |
#interpolator_classes ⇒ Object (readonly)
Returns the value of attribute interpolator_classes.
13 14 15 |
# File 'lib/mps/engines/mps.rb', line 13 def interpolator_classes @interpolator_classes end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
11 12 13 |
# File 'lib/mps/engines/mps.rb', line 11 def logger @logger end |
Class Method Details
._apply_interpolations(elements, interpolator_classes) ⇒ Object
Apply registered interpolators to the body_str of each element.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/mps/engines/mps.rb', line 95 def self._apply_interpolations(elements, interpolator_classes) return if interpolator_classes.empty? elements.each_value do |el| next unless el.respond_to?(:body_str) body = el.instance_variable_get(:@body_str) next unless body interpolator_classes.each do |ic| obj = ic.new new_body = body.gsub(ic::SIGNATURE_REGEX) { obj.get_str } el.instance_variable_set(:@body_str, new_body) if new_body != body body = new_body end end end |
.matched_element_class(str, element_classes) ⇒ Object
Returns the element class whose SIGNATURE_REGEX matches str, or nil.
27 28 29 |
# File 'lib/mps/engines/mps.rb', line 27 def self.matched_element_class(str, element_classes) element_classes.find { |ec| str =~ ec::SIGNATURE_REGEX } end |
.parse_mps_file_to_elements_hash(mps_file_path, element_classes, interpolator_classes: []) ⇒ Object Also known as: parse_mps_file_to_elments_hash
Parses mps_file_path into a flat hash of ref-path => element instances. Applies interpolators to body strings if interpolator_classes are provided.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 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 92 |
# File 'lib/mps/engines/mps.rb', line 33 def self.parse_mps_file_to_elements_hash(mps_file_path, element_classes, interpolator_classes: []) content = File.read(mps_file_path) wrapped = "@#{::MPS::Elements::MPS::SIGNATURE_STAMP}[]{\n#{content}\n}" base_ref = ::MPS::Constants::MPS_FILE_NAME_CLIPPER .call(File.basename(mps_file_path)).to_i open_re = ::MPS::Constants::AT_REGEXP close_re = ::MPS::Constants::END_CURLY_REGEXP elements = {} stack = [] pos = 0 while pos < wrapped.size open_m = open_re.match(wrapped, pos) close_m = close_re.match(wrapped, pos) break if open_m.nil? && close_m.nil? use_open = open_m && (close_m.nil? || open_m.begin(0) < close_m.begin(0)) if use_open ref_path = if stack.empty? [base_ref] else parent = stack.last parent[:child_counter] += 1 parent[:ref_path] + [parent[:child_counter]] end stack.push( sign: open_m[:element_sign], args: open_m[:args], body_start: open_m.end(0), child_counter: 0, ref_path: ref_path ) pos = open_m.end(0) else break if stack.empty? frame = stack.pop body_str = wrapped[frame[:body_start]...close_m.begin(0)] ref_key = frame[:ref_path].join(".") ec = matched_element_class(frame[:sign], element_classes) elements[ref_key] = if ec ec.new(args: frame[:args], refs: frame[:ref_path], body_str: body_str) else Unknown.new(frame[:sign], frame[:args], frame[:ref_path], body_str) end pos = close_m.end(0) end end _apply_interpolations(elements, interpolator_classes) unless interpolator_classes.empty? elements end |