Class: Parslet::Atoms::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/parslet/atoms/context.rb

Overview

Helper class that implements a transient cache that maps position and parslet object to results. This is used for memoization in the packrat style.

Also, error reporter is stored here and error reporting happens through this class. This makes the reporting pluggable.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(reporter = Parslet::ErrorReporter::Tree.new) ⇒ Context

Returns a new instance of Context.

Parameters:

  • reporter (#err, #err_at) (defaults to: Parslet::ErrorReporter::Tree.new)

    Error reporter (leave empty for default reporter)



12
13
14
15
16
# File 'lib/parslet/atoms/context.rb', line 12

def initialize(reporter=Parslet::ErrorReporter::Tree.new)
  @cache = Hash.new { |h, k| h[k] = {} }
  @reporter = reporter
  @captures = Parslet::Scope.new
end

Instance Attribute Details

#capturesObject (readonly)

Returns the current captures made on the input (see Parslet::Atoms::Base#capture). Use as follows:

context.captures[:foobar] # => returns capture :foobar


79
80
81
# File 'lib/parslet/atoms/context.rb', line 79

def captures
  @captures
end

Instance Method Details

#err(*args) ⇒ Object

Report an error.

See Also:



61
62
63
64
# File 'lib/parslet/atoms/context.rb', line 61

def err(*args)
  return [false, @reporter.err(*args)] if @reporter
  return [false, nil]
end

#err_at(*args) ⇒ Object

Report an error at a given position.

See Also:



53
54
55
56
# File 'lib/parslet/atoms/context.rb', line 53

def err_at(*args)
  return [false, @reporter.err_at(*args)] if @reporter
  return [false, nil]
end

#scopeObject

Starts a new scope. Use the #scope method of Parslet::Atoms::DSL to call this.



84
85
86
87
88
89
# File 'lib/parslet/atoms/context.rb', line 84

def scope
  captures.push
  yield
ensure
  captures.pop
end

#succ(*args) ⇒ Object

Report a successful parse.



69
70
71
72
# File 'lib/parslet/atoms/context.rb', line 69

def succ(*args)
  return [true, @reporter.succ(*args)] if @reporter
  return [true, nil]
end

#try_with_cache(obj, source, consume_all) ⇒ Object

Caches a parse answer for obj at source.pos. Applying the same parslet at one position of input always yields the same result, unless the input has changed.

We need the entire source here so we can ask for how many characters were consumed by a successful parse. Imitation of such a parse must advance the input pos by the same amount of bytes.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/parslet/atoms/context.rb', line 26

def try_with_cache(obj, source, consume_all)
  beg = source.bytepos
    
  # Not in cache yet? Return early.
  unless entry = lookup(obj, beg)
    result = obj.try(source, self, consume_all)

    if obj.cached?
      set obj, beg, [result, source.bytepos-beg]
    end
    
    return result
  end

  # the condition in unless has returned true, so entry is not nil.
  result, advance = entry

  # The data we're skipping here has been read before. (since it is in 
  # the cache) PLUS the actual contents are not interesting anymore since
  # we know obj matches at beg. So skip reading.
  source.bytepos = beg + advance
  return result
end