Skip to content
Browse files

+ Uses tuple format for error messages

  • Loading branch information...
1 parent ee4e1c3 commit dc8b4d9288aaf48a18b96651b5878408e277a627 @kschiess committed
View
4 example/ignore.rb
@@ -11,9 +11,9 @@ def to_s_inner(prec)
@parslet.to_s(prec)
end
def try(source, context)
- result = @parslet.try(source, context)
+ result = success, value = @parslet.try(source, context)
- return success(nil) unless result.error?
+ return succ(nil) if success
return result
end
View
8 lib/parslet/atoms/alternative.rb
@@ -32,15 +32,15 @@ def |(parslet) # :nodoc:
def try(source, context) # :nodoc:
errors = alternatives.map { |a|
- value = a.apply(source, context)
- return value unless value.error?
+ success, value = result = a.apply(source, context)
+ return result if success
# Aggregate all errors
- value.message
+ value
}
# If we reach this point, all alternatives have failed.
- error(source, @error_msg, errors)
+ err(source, @error_msg, errors)
end
precedence ALTERNATE
View
60 lib/parslet/atoms/base.rb
@@ -8,20 +8,6 @@ class Parslet::Atoms::Base
include Parslet::Atoms::DSL
include Parslet::Atoms::CanFlatten
- # Internally, all parsing functions return either an instance of Fail
- # or an instance of Success.
- #
- class Fail < Struct.new(:message)
- def error?; true end
- end
-
- # Internally, all parsing functions return either an instance of Fail
- # or an instance of Success.
- #
- class Success < Struct.new(:result)
- def error?; false end
- end
-
# 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.
@@ -34,32 +20,28 @@ def parse(io, prefix_parse=false)
context = Parslet::Atoms::Context.new
result = nil
- value = apply(source, context)
+ success, value = apply(source, context)
# 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.
- if value.error?
- @last_cause = value.message
- @last_cause.raise
+ unless success
+ # Value is a Parslet::Cause, which can be turned into an exception:
+ value.raise
end
- # assert: value is a success answer
+ # 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_parse && !source.eof?
- # Do we know why we stopped matching input? If yes, that's a good
- # error to fail with. Otherwise just report that we cannot consume the
- # input.
old_pos = source.pos
- @last_cause = source.error(
- "Don't know what to do with #{source.read(10).to_s.inspect}", old_pos)
-
- @last_cause.raise(Parslet::UnconsumedInput)
+ source.error(
+ "Don't know what to do with #{source.read(10).to_s.inspect}", old_pos).
+ raise(Parslet::UnconsumedInput)
end
- return flatten(value.result)
+ return flatten(value)
end
#---
@@ -69,19 +51,15 @@ def parse(io, prefix_parse=false)
def apply(source, context) # :nodoc:
old_pos = source.pos
- result = context.cache(self, source) {
+ success, value = result = context.cache(self, source) {
try(source, context)
}
-
- # This has just succeeded, so last_cause must be empty
- unless result.error?
- @last_cause = nil
- return result
- end
+
+ return result if success
# We only reach this point if the parse has failed. Rewind the input.
source.pos = old_pos
- return result # is instance of Fail
+ return result
end
# Override this in your Atoms::Base subclasses to implement parsing
@@ -113,23 +91,23 @@ def inspect # :nodoc:
# Produces an instance of Success and returns it.
#
- def success(result)
- Success.new(result)
+ def succ(result)
+ [true, result]
end
# Produces an instance of Fail and returns it.
#
- def error(source, str, children=nil)
+ def err(source, str, children=nil)
cause = source.error(str)
cause.children = children || []
- Fail.new(cause)
+ [false, cause]
end
# Produces an instance of Fail and returns it.
#
- def error_at(source, str, pos, children=nil)
+ def err_at(source, str, pos, children=nil)
cause = source.error(str, pos)
cause.children = children || []
- Fail.new(cause)
+ [false, cause]
end
end
View
9 lib/parslet/atoms/lookahead.rb
@@ -24,11 +24,12 @@ def initialize(bound_parslet, positive=true) # :nodoc:
def try(source, context) # :nodoc:
pos = source.pos
- value = bound_parslet.apply(source, context)
- return success(nil) if positive ^ value.error?
+ success, value = bound_parslet.apply(source, context)
+ return succ(nil) if positive && success
+ return succ(nil) if !positive && !success
- return error_at(source, @error_msgs[:positive], pos) if positive
- return error_at(source, @error_msgs[:negative], pos)
+ return err_at(source, @error_msgs[:positive], pos) if positive
+ return err_at(source, @error_msgs[:negative], pos)
# This is probably the only parslet that rewinds its input in #try.
# Lookaheads NEVER consume their input, even on success, that's why.
View
8 lib/parslet/atoms/named.rb
@@ -14,12 +14,12 @@ def initialize(parslet, name) # :nodoc:
end
def apply(source, context) # :nodoc:
- value = parslet.apply(source, context)
+ success, value = result = parslet.apply(source, context)
- return value if value.error?
- success(
+ return result unless success
+ succ(
produce_return_value(
- value.result))
+ value))
end
def to_s_inner(prec) # :nodoc:
View
6 lib/parslet/atoms/re.rb
@@ -24,10 +24,10 @@ def try(source, context) # :nodoc:
error_pos = source.pos
s = source.read(1)
- return error_at(source, @error_msgs[:premature], error_pos) unless s
- return error_at(source, @error_msgs[:failed], error_pos) unless s.match(re)
+ return err_at(source, @error_msgs[:premature], error_pos) unless s
+ return err_at(source, @error_msgs[:failed], error_pos) unless s.match(re)
- return success(s)
+ return succ(s)
end
def to_s_inner(prec) # :nodoc:
View
16 lib/parslet/atoms/repetition.rb
@@ -21,34 +21,34 @@ def initialize(parslet, min, max, tag=:repetition)
def try(source, context) # :nodoc:
occ = 0
- result = [@tag] # initialize the result array with the tag (for flattening)
+ accum = [@tag] # initialize the result array with the tag (for flattening)
start_pos = source.pos
break_on = nil
loop do
- value = parslet.apply(source, context)
+ success, value = parslet.apply(source, context)
break_on = value
- break if value.error?
+ break unless success
occ += 1
- result << value.result
+ accum << value
# If we're not greedy (max is defined), check if that has been
# reached.
- return success(result) if max && occ>=max
+ return succ(accum) if max && occ>=max
end
# assert: value.error? is true
# Greedy matcher has produced a failure. Check if occ (which will
# contain the number of sucesses) is in {min, max}.
- return error_at(
+ return err_at(
source,
@error_msgs[:minrep],
start_pos,
- [break_on.message]) if occ < min
+ [break_on]) if occ < min
- return success(result)
+ return succ(accum)
end
precedence REPETITION
View
10 lib/parslet/atoms/sequence.rb
@@ -20,14 +20,14 @@ def >>(parslet) # :nodoc:
end
def try(source, context) # :nodoc:
- success([:sequence]+parslets.map { |p|
- value = p.apply(source, context)
+ succ([:sequence]+parslets.map { |p|
+ success, value = p.apply(source, context)
- if value.error?
- return error(source, @error_msgs[:failed], [value.message])
+ unless success
+ return err(source, @error_msgs[:failed], [value])
end
- value.result
+ value
})
end
View
6 lib/parslet/atoms/str.rb
@@ -23,13 +23,13 @@ def try(source, context) # :nodoc:
error_pos = source.pos
s = source.read(str.bytesize)
- return success(s) if s == str
+ return succ(s) if s == str
# assert: s != str
# Failures:
- return error(source, @error_msgs[:premature]) unless s && s.size==str.size
- return error_at(source, [@error_msgs[:failed], s], error_pos)
+ return err(source, @error_msgs[:premature]) unless s && s.size==str.size
+ return err_at(source, [@error_msgs[:failed], s], error_pos)
end
def to_s_inner(prec) # :nodoc:
View
7 spec/parslet/atoms_spec.rb
@@ -170,7 +170,8 @@ def src(str); Parslet::Source.new str; end
end
context "when fed 'foo'" do
it "should parse" do
- parslet.apply(src('foo'), context).should_not be_error
+ success, _ = parslet.apply(src('foo'), context)
+ success.should == true
end
it "should not change input position" do
source = src('foo')
@@ -185,7 +186,7 @@ def src(str); Parslet::Source.new str; end
end
describe "<- #parse" do
it "should return nil" do
- parslet.apply(src('foo'), context).result.should == nil
+ parslet.apply(src('foo'), context).should == [true, nil]
end
end
end
@@ -200,7 +201,7 @@ def src(str); Parslet::Source.new str; end
end
context "when fed 'bar'" do
it "should parse" do
- parslet.apply(src('bar'), context).should_not be_error
+ parslet.apply(src('bar'), context).should == [true, nil]
end
it "should not change input position" do
source = src('bar')

0 comments on commit dc8b4d9

Please sign in to comment.
Something went wrong with that request. Please try again.