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
-
.look_ahead_pos(str_scanner, regex_la) ⇒ Object
Peeks ahead in
str_scannerforregex_lawithout consuming input. -
.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) ⇒ 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
.look_ahead_pos(str_scanner, regex_la) ⇒ Object
Peeks ahead in str_scanner for regex_la without consuming input. Returns the position of the match, or string size if no match.
33 34 35 36 37 38 |
# File 'lib/mps/engines/mps.rb', line 33 def self.look_ahead_pos(str_scanner, regex_la) return str_scanner.string.size unless str_scanner.scan_until(regex_la) pos = str_scanner.pos str_scanner.unscan pos 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) ⇒ Object Also known as: parse_mps_file_to_elments_hash
Parses mps_file_path into a flat hash of ref-path => element instances.
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 93 94 95 96 97 98 |
# File 'lib/mps/engines/mps.rb', line 41 def self.parse_mps_file_to_elements_hash(mps_file_path, element_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 elements end |