Class: Parslet::Atoms::Base
- Inherits:
-
Object
- Object
- Parslet::Atoms::Base
- Includes:
- CanFlatten, DSL, Precedence
- Defined in:
- lib/parslet/atoms/base.rb,
lib/parslet/convenience.rb,
lib/parslet/atoms/visitor.rb
Overview
Base class for all parslets, handles orchestration of calls and implements a lot of the operator and chaining methods.
Also see Parslet::Atoms::DSL chaining parslet atoms together.
Direct Known Subclasses
Alternative, Entity, Lookahead, Named, Re, Repetition, Sequence, Str, Parser
Constant Summary
Constants included from Precedence
Precedence::ALTERNATE, Precedence::BASE, Precedence::LOOKAHEAD, Precedence::OUTER, Precedence::REPETITION, Precedence::SEQUENCE
Class Method Summary collapse
-
.precedence(prec) ⇒ Object
Debug printing - in Treetop syntax.
Instance Method Summary collapse
- #accept(visitor) ⇒ Object
-
#apply(source, context) ⇒ Object
— Calls the #try method of this parslet.
- #inspect ⇒ Object
-
#parse(io, options = {}) ⇒ Hash, ...
Given a string or an IO object, this will attempt a parse of its contents and return a result.
-
#parse_with_debug(str, opts = {}) ⇒ Object
Packages the common idiom begin tree = parser.parse(‘something’) rescue Parslet::ParseFailed => error puts parser.cause.ascii_tree end.
-
#setup_and_apply(source, error_reporter) ⇒ <Boolean, Object>
Creates a context for parsing and applies the current atom to the input.
- #to_s(outer_prec = OUTER) ⇒ Object
-
#try(source, context) ⇒ Object
Override this in your Atoms::Base subclasses to implement parsing behaviour.
Methods included from CanFlatten
#flatten, #flatten_repetition, #flatten_sequence, #foldl, #merge_fold, #warn_about_duplicate_keys
Methods included from DSL
#>>, #absent?, #as, #maybe, #present?, #repeat, #|
Class Method Details
.precedence(prec) ⇒ Object
Debug printing - in Treetop syntax.
102 103 104 |
# File 'lib/parslet/atoms/base.rb', line 102 def self.precedence(prec) define_method(:precedence) { prec } end |
Instance Method Details
#accept(visitor) ⇒ Object
7 8 9 |
# File 'lib/parslet/atoms/visitor.rb', line 7 def accept(visitor) raise NotImplementedError, "No #accept method on #{self.class.name}." end |
#apply(source, context) ⇒ Object
Calls the #try method of this parslet. In case of a parse error, apply leaves the source in the state it was before the attempt. +++
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/parslet/atoms/base.rb', line 79 def apply(source, context) old_pos = source.pos #success, value = result = context.try_with_cache(self, source) success, value = result = try(source, context) return result if success # We only reach this point if the parse has failed. Rewind the input. source.pos = old_pos return result end |
#inspect ⇒ Object
113 114 115 |
# File 'lib/parslet/atoms/base.rb', line 113 def inspect to_s(OUTER) end |
#parse(io, options = {}) ⇒ Hash, ...
Given a string or an IO object, this will attempt a parse of its contents and return a result. If the parse fails, a Parslet::ParseFailed exception will be thrown.
23 24 25 26 27 28 29 30 31 32 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 |
# File 'lib/parslet/atoms/base.rb', line 23 def parse(io, ={}) source = io.respond_to?(:line_and_column) ? io : Parslet::Source.new(io) # Try to cheat. Assuming that we'll be able to parse the input, don't # run error reporting code. success, value = setup_and_apply(source, nil) # If we didn't succeed the parse, raise an exception for the user. # Stack trace will be off, but the error tree should explain the reason # it failed. unless success # Cheating has not paid off. Now pay the cost: Rerun the parse, # gathering error information in the process. reporter = [:reporter] || Parslet::ErrorReporter::Tree.new success, value = setup_and_apply(source, reporter) fail "Assertion failed: success was true when parsing with reporter" \ if success # Value is a Parslet::Cause, which can be turned into an exception: value.raise fail "NEVER REACHED" end # assert: success is true # If we haven't consumed the input, then the pattern doesn't match. Try # to provide a good error message (even asking down below) if ![:prefix] && source.chars_left > 0 old_pos = source.pos Parslet::Cause.format( source, old_pos, "Don't know what to do with #{source.consume(10).to_s.inspect}"). raise(Parslet::UnconsumedInput) end return flatten(value) end |
#parse_with_debug(str, opts = {}) ⇒ Object
Packages the common idiom
begin
tree = parser.parse('something')
rescue Parslet::ParseFailed => error
puts parser.cause.ascii_tree
end
into a convenient method.
Usage:
require 'parslet'
require 'parslet/convenience'
class FooParser < Parslet::Parser
rule(:foo) { str('foo') }
root(:foo)
end
FooParser.new.parse_with_debug('bar')
27 28 29 30 31 32 33 |
# File 'lib/parslet/convenience.rb', line 27 def parse_with_debug str, opts={} parse str, opts rescue Parslet::UnconsumedInput => error puts error rescue Parslet::ParseFailed => error puts error.cause.ascii_tree end |
#setup_and_apply(source, error_reporter) ⇒ <Boolean, Object>
Creates a context for parsing and applies the current atom to the input. Returns the parse result.
70 71 72 73 |
# File 'lib/parslet/atoms/base.rb', line 70 def setup_and_apply(source, error_reporter) context = Parslet::Atoms::Context.new(error_reporter) apply(source, context) end |
#to_s(outer_prec = OUTER) ⇒ Object
106 107 108 109 110 111 112 |
# File 'lib/parslet/atoms/base.rb', line 106 def to_s(outer_prec=OUTER) if outer_prec < precedence "("+to_s_inner(precedence)+")" else to_s_inner(precedence) end end |
#try(source, context) ⇒ Object
Override this in your Atoms::Base subclasses to implement parsing behaviour.
95 96 97 98 |
# File 'lib/parslet/atoms/base.rb', line 95 def try(source, context) raise NotImplementedError, \ "Atoms::Base doesn't have behaviour, please implement #try(source, context)." end |