Class: Resyma::Core::Engine
- Inherits:
-
Object
- Object
- Resyma::Core::Engine
- Defined in:
- lib/resyma/core/algorithm/engine.rb
Overview
The engine of the matching algorithm
Constant Summary collapse
- CACHE_INDEX_TO_NODE =
"ALGO_IDX_NODE_MAP".freeze
Instance Method Summary collapse
-
#accepted_tuples(parsetree) ⇒ Set<Resyma::Core::Tuple4>
Compute accepted 4-tuples in the processed tree.
-
#assign_start!(node) ⇒ nil
Step 2 of the algorithm.
-
#assign_trans!(node) ⇒ nil
Step 3 of the algorithm.
-
#backtrack(parsetree, terminal_tuples = accepted_tuples(parsetree)) ⇒ Array<Array<Resyma::Core::Tuple4>] Derivational node sequences
Backtrack the derivational node sequence(s) of a parse tree processed by the algorithm.
-
#backtrack_for(parsetree, tuple4) ⇒ Array<Resyma::Core::Tuple4>
Backtrack the derivational node sequence terminating at the 4-tuple.
-
#initialize(automata) ⇒ Engine
constructor
Create an instance of the algorithmic engine.
-
#node_of(parsetree, id) ⇒ Resyma::Core::ParseTree?
Find the parse tree through its ID.
-
#node_type(parsetree) ⇒ :a, ...
Determine the type of the node corresponding step 2 of the algorithm.
-
#RMP(parsetree) ⇒ Set<Resyma::Core::ParseTree>
Right-most path of the tree.
-
#traverse!(parsetree) ⇒ nil
Traverse the parse tree once and modify fields for every nodes.
Constructor Details
#initialize(automata) ⇒ Engine
Create an instance of the algorithmic engine
17 18 19 20 21 22 |
# File 'lib/resyma/core/algorithm/engine.rb', line 17 def initialize(automata) automata = [automata] if automata.is_a?(Automaton) raise TypeError, "Need a list of automata" unless automata.is_a?(Array) @automata = automata end |
Instance Method Details
#accepted_tuples(parsetree) ⇒ Set<Resyma::Core::Tuple4>
Compute accepted 4-tuples in the processed tree
141 142 143 144 145 146 147 148 149 |
# File 'lib/resyma/core/algorithm/engine.rb', line 141 def accepted_tuples(parsetree) Utils.big_union(RMP(parsetree).map do |node| Utils.big_union(node.field.trans.values.map do |set_of_tuple4| set_of_tuple4.select do |tuple4| @automata[tuple4.belongs_to].accept?(tuple4.q_) end.to_set end) end) end |
#assign_start!(node) ⇒ nil
Step 2 of the algorithm
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/resyma/core/algorithm/engine.rb', line 61 def assign_start!(node) @automata.each_with_index do |automaton, idx| node.field.start[idx] = case node_type(node) when :a Set[Tuple2.new(-1, automaton.start, belongs_to: idx)] when :b node.parent.field.start[idx] when :c # @type [Resyma::Core::ParseTree] brother = node.parent.children[node.index - 1] Utils.big_union(RMP(brother).map do |node_| node_.field.trans[idx].map do |tuple4| Tuple2.new(tuple4.p_, tuple4.q_, belongs_to: idx) end end) end end end |
#assign_trans!(node) ⇒ nil
Step 3 of the algorithm
88 89 90 91 92 93 94 95 96 |
# File 'lib/resyma/core/algorithm/engine.rb', line 88 def assign_trans!(node) @automata.each_with_index do |automaton, idx| node.field.trans[idx] = node.field.start[idx].map do |tuple2| next_q = automaton.destination(tuple2.q, node) next_q and Tuple4.new(tuple2.p, tuple2.q, node.field.id, next_q, belongs_to: idx) end.compact.to_set end end |
#backtrack(parsetree, terminal_tuples = accepted_tuples(parsetree)) ⇒ Array<Array<Resyma::Core::Tuple4>] Derivational node sequences
Backtrack the derivational node sequence(s) of a parse tree processed by
the algorithm
184 185 186 |
# File 'lib/resyma/core/algorithm/engine.rb', line 184 def backtrack(parsetree, terminal_tuples = accepted_tuples(parsetree)) terminal_tuples.map { |tuple4| backtrack_for(parsetree, tuple4) } end |
#backtrack_for(parsetree, tuple4) ⇒ Array<Resyma::Core::Tuple4>
Backtrack the derivational node sequence terminating at the 4-tuple
160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/resyma/core/algorithm/engine.rb', line 160 def backtrack_for(parsetree, tuple4) if tuple4.p == -1 [tuple4] else # @type [Resyma::Core::ParseTree] prev = parsetree.cache[Engine::CACHE_INDEX_TO_NODE][tuple4.p] prev_tuple4 = prev.field.trans[tuple4.belongs_to].find do |candidate| candidate.p_ == tuple4.p && candidate.q_ == tuple4.q end backtrack_for(parsetree, prev_tuple4) + [tuple4] end end |
#node_of(parsetree, id) ⇒ Resyma::Core::ParseTree?
Find the parse tree through its ID
110 111 112 |
# File 'lib/resyma/core/algorithm/engine.rb', line 110 def node_of(parsetree, id) parsetree.cache[Engine::CACHE_INDEX_TO_NODE][id] end |
#node_type(parsetree) ⇒ :a, ...
Determine the type of the node corresponding step 2 of the algorithm
31 32 33 34 35 36 37 |
# File 'lib/resyma/core/algorithm/engine.rb', line 31 def node_type(parsetree) if parsetree.root? then :a elsif parsetree.index.zero? then :b else :c end end |
#RMP(parsetree) ⇒ Set<Resyma::Core::ParseTree>
Right-most path of the tree
46 47 48 49 50 51 52 |
# File 'lib/resyma/core/algorithm/engine.rb', line 46 def RMP(parsetree) if parsetree.leaf? Set[parsetree] else Set[parsetree] | RMP(parsetree.children.last) end end |
#traverse!(parsetree) ⇒ nil
Traverse the parse tree once and modify fields for every nodes
121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/resyma/core/algorithm/engine.rb', line 121 def traverse!(parsetree) id = 0 parsetree.cache[Engine::CACHE_INDEX_TO_NODE] = {} parsetree.depth_first_each do |tree| tree.field.id = id assign_start! tree assign_trans! tree parsetree.cache[Engine::CACHE_INDEX_TO_NODE][id] = tree id += 1 end end |