Class: Rley::Parser::ParseWalkerFactory

Inherits:
Object
  • Object
show all
Defined in:
lib/rley/parser/parse_walker_factory.rb

Overview

A factory that creates an Enumerator object that itself walks through a GFGParsing object. The walker (= Enumerator) yields visit events. This class implements an external iterator for a given GFGParsing object. This is different from the internal iterators, usually implemented in Ruby with an :each method. Allows to perform a backwards traversal over the relevant parse entries. backwards traversal means that the traversal starts from the accepting (final) parse entries and goes to the initial parse entry. Relevant parse entries are parse entries that "count" in the parse (i.e. they belong to a path that leads to the accepting parse entry)

Instance Method Summary collapse

Instance Method Details

#build_walker(acceptingEntry, maxIndex, lazyWalk = false) ⇒ Enumerator

Build an Enumerator that will yield the parse entries as it walks backwards on the parse graph.

Parameters:

  • acceptingEntry (ParseEntry)

    the final ParseEntry of a successful parse.

  • maxIndex (Integer)

    the index of the last input token.

  • lazyWalk (Boolean) (defaults to: false)

    if true then take some shortcut in re-visits.

Returns:

  • (Enumerator)

    yields visit events when walking over the parse result



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
# File 'lib/rley/parser/parse_walker_factory.rb', line 54

def build_walker(acceptingEntry, maxIndex, lazyWalk = false)
  # Local context for the enumerator
  ctx = init_context(acceptingEntry, maxIndex, lazyWalk)

  walker = Enumerator.new do |receiver| # 'receiver' is a Yielder
    # At this point: current entry == accepting entry

    loop do
      event = visit_entry(ctx.curr_entry, ctx)
      receiver << event unless event.nil?

      if ctx.curr_entry.orphan? # No antecedent?...
        err_msg = "No antecedent for #{ctx.curr_entry} at rank #{ctx.entry_set_index}"
        raise StandardError, err_msg unless ctx.curr_entry.start_entry?
        break if ctx.backtrack_points.empty?
        receiver << use_backtrack_point(ctx)
        receiver << visit_entry(ctx.curr_entry, ctx)
      end

      result = jump_to_antecedent(ctx)
      # Emit detection of scan edge if any...
      receiver << result[0] if result.size > 1
      ctx.curr_entry = result.last
    end
  end

  return walker
end