[DRE-commits] [ruby-parslet] 01/01: do not ship spec via d/patches

Jonas Genannt genannt at moszumanska.debian.org
Wed Aug 19 13:24:23 UTC 2015


This is an automated email from the git hooks/post-receive script.

genannt pushed a commit to branch master
in repository ruby-parslet.

commit a879e4a5248e33247b2d610bc924ec44136ca4c7
Author: Jonas Genannt <jonas at brachium-system.net>
Date:   Wed Aug 19 15:26:59 2015 +0200

    do not ship spec via d/patches
---
 ...port-rspec-gemspec-from-upstream-Git-repo.patch | 3441 --------------------
 debian/patches/series                              |    1 -
 2 files changed, 3442 deletions(-)

diff --git a/debian/patches/0001-Import-rspec-gemspec-from-upstream-Git-repo.patch b/debian/patches/0001-Import-rspec-gemspec-from-upstream-Git-repo.patch
deleted file mode 100644
index 892e79c..0000000
--- a/debian/patches/0001-Import-rspec-gemspec-from-upstream-Git-repo.patch
+++ /dev/null
@@ -1,3441 +0,0 @@
-From: Youhei SASAKI <uwabami at gfd-dennou.org>
-Date: Tue, 14 Jan 2014 15:39:51 +0900
-Subject: Import rspec, gemspec from upstream Git repo.
-
-Signed-off-by: Youhei SASAKI <uwabami at gfd-dennou.org>
----
- parslet.gemspec                              |  18 ++
- qed/accelerators.md                          | 234 +++++++++++++++
- qed/applique/ae.rb                           |   1 +
- qed/applique/gobbleup.rb                     |  26 ++
- qed/applique/parslet.rb                      |   4 +
- qed/regressions.md                           |  60 ++++
- spec/acceptance/examples_spec.rb             |  37 +++
- spec/acceptance/infix_parser_spec.rb         | 112 +++++++
- spec/acceptance/regression_spec.rb           | 314 ++++++++++++++++++++
- spec/acceptance/repetition_and_maybe_spec.rb |  42 +++
- spec/acceptance/unconsumed_input_spec.rb     |  21 ++
- spec/parslet/atom_results_spec.rb            |  39 +++
- spec/parslet/atoms/alternative_spec.rb       |  26 ++
- spec/parslet/atoms/base_spec.rb              | 124 ++++++++
- spec/parslet/atoms/capture_spec.rb           |  21 ++
- spec/parslet/atoms/combinations_spec.rb      |   5 +
- spec/parslet/atoms/dsl_spec.rb               |  17 ++
- spec/parslet/atoms/entity_spec.rb            |  52 ++++
- spec/parslet/atoms/infix_spec.rb             |   5 +
- spec/parslet/atoms/lookahead_spec.rb         |  22 ++
- spec/parslet/atoms/named_spec.rb             |   4 +
- spec/parslet/atoms/re_spec.rb                |  14 +
- spec/parslet/atoms/repetition_spec.rb        |  24 ++
- spec/parslet/atoms/scope_spec.rb             |  26 ++
- spec/parslet/atoms/sequence_spec.rb          |  28 ++
- spec/parslet/atoms/str_spec.rb               |  15 +
- spec/parslet/atoms/visitor_spec.rb           |  80 +++++
- spec/parslet/atoms_spec.rb                   | 429 +++++++++++++++++++++++++++
- spec/parslet/convenience_spec.rb             |  48 +++
- spec/parslet/error_reporter/deepest_spec.rb  |  73 +++++
- spec/parslet/error_reporter/tree_spec.rb     |   7 +
- spec/parslet/export_spec.rb                  |  67 +++++
- spec/parslet/expression/treetop_spec.rb      |  74 +++++
- spec/parslet/minilisp.citrus                 |  29 ++
- spec/parslet/minilisp.tt                     |  29 ++
- spec/parslet/parser_spec.rb                  |  31 ++
- spec/parslet/parslet_spec.rb                 |  38 +++
- spec/parslet/pattern_spec.rb                 | 268 +++++++++++++++++
- spec/parslet/position_spec.rb                |  10 +
- spec/parslet/rig/rspec_spec.rb               |  54 ++++
- spec/parslet/scope_spec.rb                   |  45 +++
- spec/parslet/slice_spec.rb                   | 140 +++++++++
- spec/parslet/source/line_cache_spec.rb       |  74 +++++
- spec/parslet/source_spec.rb                  | 168 +++++++++++
- spec/parslet/transform/context_spec.rb       |  35 +++
- spec/parslet/transform_spec.rb               | 144 +++++++++
- spec/spec_helper.rb                          |  29 ++
- 47 files changed, 3163 insertions(+)
- create mode 100644 parslet.gemspec
- create mode 100644 qed/accelerators.md
- create mode 100644 qed/applique/ae.rb
- create mode 100644 qed/applique/gobbleup.rb
- create mode 100644 qed/applique/parslet.rb
- create mode 100644 qed/regressions.md
- create mode 100644 spec/acceptance/examples_spec.rb
- create mode 100644 spec/acceptance/infix_parser_spec.rb
- create mode 100644 spec/acceptance/regression_spec.rb
- create mode 100644 spec/acceptance/repetition_and_maybe_spec.rb
- create mode 100644 spec/acceptance/unconsumed_input_spec.rb
- create mode 100644 spec/parslet/atom_results_spec.rb
- create mode 100644 spec/parslet/atoms/alternative_spec.rb
- create mode 100644 spec/parslet/atoms/base_spec.rb
- create mode 100644 spec/parslet/atoms/capture_spec.rb
- create mode 100644 spec/parslet/atoms/combinations_spec.rb
- create mode 100644 spec/parslet/atoms/dsl_spec.rb
- create mode 100644 spec/parslet/atoms/entity_spec.rb
- create mode 100644 spec/parslet/atoms/infix_spec.rb
- create mode 100644 spec/parslet/atoms/lookahead_spec.rb
- create mode 100644 spec/parslet/atoms/named_spec.rb
- create mode 100644 spec/parslet/atoms/re_spec.rb
- create mode 100644 spec/parslet/atoms/repetition_spec.rb
- create mode 100644 spec/parslet/atoms/scope_spec.rb
- create mode 100644 spec/parslet/atoms/sequence_spec.rb
- create mode 100644 spec/parslet/atoms/str_spec.rb
- create mode 100644 spec/parslet/atoms/visitor_spec.rb
- create mode 100644 spec/parslet/atoms_spec.rb
- create mode 100644 spec/parslet/convenience_spec.rb
- create mode 100644 spec/parslet/error_reporter/deepest_spec.rb
- create mode 100644 spec/parslet/error_reporter/tree_spec.rb
- create mode 100644 spec/parslet/export_spec.rb
- create mode 100644 spec/parslet/expression/treetop_spec.rb
- create mode 100644 spec/parslet/minilisp.citrus
- create mode 100644 spec/parslet/minilisp.tt
- create mode 100644 spec/parslet/parser_spec.rb
- create mode 100644 spec/parslet/parslet_spec.rb
- create mode 100644 spec/parslet/pattern_spec.rb
- create mode 100644 spec/parslet/position_spec.rb
- create mode 100644 spec/parslet/rig/rspec_spec.rb
- create mode 100644 spec/parslet/scope_spec.rb
- create mode 100644 spec/parslet/slice_spec.rb
- create mode 100644 spec/parslet/source/line_cache_spec.rb
- create mode 100644 spec/parslet/source_spec.rb
- create mode 100644 spec/parslet/transform/context_spec.rb
- create mode 100644 spec/parslet/transform_spec.rb
- create mode 100644 spec/spec_helper.rb
-
---- /dev/null
-+++ ruby-parslet/parslet.gemspec
-@@ -0,0 +1,18 @@
-+# -*- encoding: utf-8 -*-
-+
-+Gem::Specification.new do |s|
-+  s.name = 'parslet'
-+  s.version = '1.6.1'
-+
-+  s.authors = ['Kaspar Schiess']
-+  s.email = 'kaspar.schiess at absurd.li'
-+  s.extra_rdoc_files = ['README']
-+  s.files = %w(HISTORY.txt LICENSE Rakefile README) + Dir.glob("{lib,example}/**/*")
-+  s.homepage = 'http://kschiess.github.com/parslet'
-+  s.license = 'MIT'
-+  s.rdoc_options = ['--main', 'README']
-+  s.require_paths = ['lib']
-+  s.summary = 'Parser construction library with great error reporting in Ruby.'  
-+  
-+  s.add_dependency 'blankslate', '~> 2.0'
-+end
---- /dev/null
-+++ ruby-parslet/qed/accelerators.md
-@@ -0,0 +1,234 @@
-+# Parslet Accelerator
-+
-+## Synopsis
-+
-+Reading this all the way is worth it. But don't despair; if your attention span is short, read this and zap away! The TLDR:
-+
-+Parslet is slow because of the way it is constructed internally. Optimisation helps, but makes your parser harder to read. Don't go there. Use parser accelerators instead - optimize parts of your parser without changing its definition. This is what it looks like:
-+
-+    slow_parser = something >> slow_part >> other
-+
-+    include Parslet::Accelerator
-+    optimized_parser = apply(
-+      rule( slow_part ) { faster_part })
-+
-+    optimized_parser.parse('"Parsing is now fully optimized! (tm)"')
-+
-+Thus parslet allows you to write cristal clear parsers that are also as fast as you can make them. (But still slower than C!)
-+
-+## Introduction
-+
-+The goals of parslet are simple: make writing PEG parsers a predictable and straightforward endeavour. Some people have since claimed the word 'fun' for writing parsers, a connotation that we don't entirely oppose - otherwise why would we spend our time extending parslet?
-+
-+### Dark Clouds ahead
-+
-+Writing your first thousand line parser that works is easy – IF you use parslet. But very often, the resulting parser is rather slow - having execution times in the second range instead of the subsecond range.
-+
-+You fire up your email client and drop us a mail to the mailing list, asking: "Why is parslet so slow?" You'll receive the following answers:
-+
-+* Parslet is not a parser generator, but a parser engine based on Ruby. As such, it will be slower than parsers written in languages such as C.
-+* Parslet's internal structure is simple and clear. We've invested a lot of effort in making everything it does obvious and extendable. The downside of this somewhat OO-heavy approach is that we've got many objects juggling data and deep callstacks. Read: Bad use of caches and CPU time.
-+* Very few big languages have parsers written in high level languages such as Ruby. For good reasons. Depending on how serious you are about writing a new language (as opposed to fiddling around), you might want to _not start with parslet at all_.
-+
-+It's not like we haven't done anything to fix the above reasons; rather, we're doing everything we can, provided the main goal of *simplicity and understandability* is not in danger! If you look up what has been done over the years you will find a lot of small and large optimisations. But we have always refused to sacrifice simplicity of design to the god of optimisation, especially when it came to making a single parser faster. We want parslet to be fast in general, and frankly, your p [...]
-+
-+But parslet needs to be useful for something. If not, what is the point? We would like to make parslet as useful as possible for smaller languages and for places where execution speed isn't your only concern. A lot of languages have rapidly evolving grammars and are developed by programmers that don't have the time for hand-writing parsers in C.
-+
-+Still, what should you do once you've written your parser and speed becomes the issue? Until now, you had no real options short of rewriting the damn thing in C. That has changed: we've come up with Parslet Accelerator. The Accelerator will allow you to pattern match bits of your _parser_ and replace them with bits that do the same work, but faster. Really just hot spot optimisation, but without sacrificing readability of the original parser grammar.
-+
-+### An Example
-+
-+Let's consider the parser for quoted strings as an example, usually written to look something like this:
-+
-+    quote = str('"')
-+    quote >> (quote.absent? >> any).repeat >> quote
-+
-+If we spell out the work parslet needs to do when matching a 1000 character string using this method, the performance problems will become obvious to you. Parslet will:
-+
-+* Match a quote
-+* In a loop:
-+  * Try to match a quote
-+  * If that fails, continue, otherwise break from the loop
-+  * Gobble up a single char
-+* Match the final quote
-+
-+The inner loop will be executed a 1000 times; that's a 1000 times reading a char, checking to see if it's a quote, then reading it again, etc... As a programmer, this should disturb you deeply. And the fix, pseudo-code wise, should be obvious to you. Let's look at this revised flow:
-+
-+* Match a quote
-+* Gobble up as many chars as possible, until we hit a quote
-+* Match the final quote
-+
-+Ok, we've sort of cheated there in the middle - we've transformed something into a single step that is really still a loop. But as a Ruby programmer, you will not see this as a loop, but rather as a call to a more efficient library like `StringScanner`, which underlies `Parslet::Source`.
-+
-+So we're pretty confident that this new parser will work faster; maybe fast even. Let's assume that we've got a `GobbleUp` atom that gobbles up chars until it hits a stop char. Our faster parser would have to look something like this:
-+
-+    quote = str('"')
-+    quote >> GobbleUp.new('"') >> quote
-+
-+And all is fine, right? We don't think so. You've chosen to use parslet, so you don't want to end up sprinkling your grammar which is as much specification as it is implementation with things like `GobbleUp`. Wouldn't it be nice if you could keep the parser as it is, but somehow replace the pattern of `(quote.absent? >> any).repeat` with `GobbleUp.new('"')` before doing any work with your parser? Well, you can.
-+
-+    quote = str('"')
-+    parser = quote >> (quote.absent? >> any).repeat >> quote
-+
-+    A = Accelerator # for making what follows a bit shorter
-+    optimized_parser = A.apply(parser,
-+      A.rule( (A.str(:x).absent? >> A.any).repeat ) { GobbleUp.new(x) })
-+
-+    optimized_parser.parse('"Parsing is now fully optimized! (tm)"')
-+
-+(If you're interested in a bit of history, the example that triggered the discussion around accelerators is preserved in [optimizer.rb](https://github.com/kschiess/parslet/blob/master/experiments/optimizer.rb). If you look past the hacks and the optimism, you'll recognize some of the things we talk about in this document.)
-+
-+### About this Document
-+
-+Now that the goal is defined, let us expose the details of the system proposed above. We'll start with explaining what these `Accelerator.rule` things are, how they match against your parser and how binding of variables work. (*Parslet Pattern Matching*) Then we'll explain what actions you can take once you've matched part of your parser. (*Binding and Actions*)
-+
-+## Parser Pattern Matching
-+
-+We'll demonstrate how pattern detection is constructed by showing what the smallest parts do first. Let's require needed libraries.
-+
-+    require 'parslet'
-+    require 'parslet/accelerator'
-+
-+    include Parslet
-+
-+The whole optimizer code is inside the `Parslet::Accelerator` module. If you read that, read 'particle accelerator', not 'will make my code fast'. It is very possible to make things worse using `Parslet::Accelerator`.
-+
-+The simplest parser I can think of would be the one matching a simple string.
-+
-+    atom = str('foo')
-+    expression = Accelerator.str(:x)
-+    binding = Accelerator.match(atom, expression)
-+
-+    binding[:x].assert == 'foo'
-+
-+Note that the above was somewhat verbose, with all these variables and all that. We'll write shorter examples from now on.
-+
-+Another simple parser is the one that matches against variants of the `match(...)` atom. Multiple forms of this exist, so we'll go through all of them. First comes a simple character range match.
-+
-+    binding = Accelerator.match(
-+      match['a-z'],
-+      Accelerator.re(:x))
-+
-+    binding[:x].assert == '[a-z]'
-+
-+Note how the internal regular expression value used for the match atom is really bound to :x – we'll keep this as a convention. This also means that some parslet internas are leaked through the Accelerator API here. We consider that a feature, since working with accelerators will bring you into close contact with the atoms internas.
-+
-+Also the Accelerator matcher for `Parslet.match` is called `Accelerator.re` - the reason for this should be obvious from what stands above.
-+
-+Just to make this complete, a special case for the `match(...)` atom is the `any` atom.
-+
-+    binding = Accelerator.match(any, Accelerator.any)
-+    binding.assert != nil
-+
-+## Composite Parsers
-+
-+Let's start assembling these simple parsers into more complex patterns and match those. As our first pattern, we'll consider sequences.
-+
-+    binding = Accelerator.match(
-+      str('a') >> str('b'),
-+      Accelerator.str(:x) >> Accelerator.str(:y))
-+
-+    binding.values_at(:x, :y).assert == %w(a b)
-+
-+Also, alternatives should correctly bind.
-+
-+    binding = Accelerator.match(
-+      str('a') | str('b'),
-+      Accelerator.str(:x) | Accelerator.str(:y))
-+
-+    binding.values_at(:x, :y).assert == %w(a b)
-+
-+Note that this means that we bind to the whole alternative subtree, not either to the left or to the right. We're matching the parslet tree, so the meaning of the alternative is irrelevant.
-+
-+Let's quickly skip through the list of other composite parsers here: First off is repetition.
-+
-+    Accelerator.match(
-+      str('a').repeat(1,2),
-+      A.str('a').repeat(1,2)).assert != nil
-+
-+And then there is positive and negative lookahead.
-+
-+    Accelerator.match(
-+      str('a').present?,
-+      A.str('a').present?).assert != nil
-+
-+    Accelerator.match(
-+      str('a').absent?,
-+      A.str('a').absent?).assert != nil
-+
-+And named values.
-+
-+    Accelerator.match(
-+      str('a').as(:a),
-+      A.str('a').as(:a)).assert != nil
-+
-+Which we also want to be able to bind.
-+
-+    Accelerator.match(
-+      str('a').as(:a),
-+      A.str('a').as(:b)).assert == {:b => :a}
-+
-+## Binding to Values
-+
-+As a side note, our parser should also respect literal value matches in the pattern and only bind to subsequent locations when the values match up.
-+
-+    binding = Accelerator.match(
-+      str('a') >> str('b'),
-+      Accelerator.str(:x) >> Accelerator.str(:x))
-+
-+    binding.assert == nil
-+
-+Another property should be that literal strings passed to the pattern should be matched using ===.
-+
-+    binding = Accelerator.match(
-+      str('abc') >> str('bcd'),
-+      Accelerator.str(/b/) >> Accelerator.str('bcd'))
-+
-+    binding.assert == {}
-+
-+The binding is empty here, since no variables were given. But lets also implement constrained variable bindings, that seems useful. The way this works is that you specify a variable you want to bind to first, and then a list of constraints that are matched by `#===`.
-+
-+    A.match(str('abc'), A.str(:x, /c/))[:x].assert == 'abc'
-+    A.match(str('abc'), A.str(:x, /d/)).assert == nil
-+
-+    A.match(str('abc'), A.str(:x, /a/, /c/))[:x].assert == 'abc'
-+    A.match(str('abc'), A.str(:x, /a/, /d/)).assert == nil
-+
-+Here's a quick demonstration that demonstrates that this feature equally applies to both `Accelerator.re` and `Parslet.match`.
-+
-+    A.match(match['abc'], A.re(:x, /d/)).assert == nil
-+    A.match(match['abc'], A.re(:x, /c/))[:x].assert == '[abc]'
-+
-+## Bindings and Actions
-+
-+Matching parsers is only useful if we can take action and create a new parser that is different in some way. Let's say we have the lofty goal of creating an 'accelerator' that reverses the language understood by a parser. Where the first parser would parse something like:
-+
-+    aaaaabbbb
-+
-+we want the second parser to parse something like:
-+
-+    bbbaaaaa
-+
-+Here's how the first parser would look like:
-+
-+    parser = str('a').repeat(1) >> str('b').repeat(1)
-+
-+And here's how we turn this around to parse the second kind of input.
-+
-+    include Parslet
-+    parser = str('a').repeat(1) >> str('b').repeat(1)
-+    new_parser = A.apply(parser,
-+      A.rule(A.str(:x).repeat(1) >> A.str(:y).repeat(1)) { 
-+        str(y).repeat(1) >> str(x).repeat(1) } )
-+
-+    new_parser.parse('bbbaaaa').assert == 'bbbaaaa'
-+
-+The `Accelerator.apply` method should be called with the following schema: 
-+
-+    Accelerator.apply(PARSER, RULE1, RULE2, ...)
-+
-+This is a more modern syntax than `Parslet::Transform` uses - maybe we'll update that class in a future version.
-+
-+## Closing Note
-+
-+* not a panacea
---- /dev/null
-+++ ruby-parslet/qed/applique/ae.rb
-@@ -0,0 +1 @@
-+require 'ae'
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/qed/applique/gobbleup.rb
-@@ -0,0 +1,26 @@
-+
-+require 'parslet'
-+
-+# This is where the famous GobbleUp atom is defined. This parslet atom consumes
-+# all chars until a given string (absent) is encountered.
-+#
-+class GobbleUp < Parslet::Atoms::Base
-+  def initialize absent, min_chars=0
-+    @absent = absent
-+    @min_chars = min_chars
-+  end
-+
-+  def try(source, context, consume_all)
-+    excluding_length = source.chars_until(@absent)
-+
-+    if excluding_length >= @min_chars
-+      return succ(source.consume(excluding_length))
-+    else
-+      return context.err(self, source, "No such string in input: #{@absent.inspect}.")
-+    end
-+  end
-+
-+  def to_s_inner(prec)
-+    "until('#{@absent}')"
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/qed/applique/parslet.rb
-@@ -0,0 +1,4 @@
-+require 'parslet'
-+require 'parslet/accelerator'
-+
-+include Parslet
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/qed/regressions.md
-@@ -0,0 +1,60 @@
-+
-+# Intro
-+
-+This document collects all sorts of weird bugs that parslet had over the years and asserts that we don't accidentially reintroduce one of these. There's not much to be learnt here but a few war stories to be had. 
-+
-+# Regresssions
-+
-+## Redefinition of Ruby core methods
-+
-+This [bug](https://github.com/kschiess/parslet/issues/101) came up at least twice. When constructing a parser like this
-+
-+    class HashParser < Parslet::Parser
-+      rule(:str_hash) { str('hash') }
-+      rule(:hash) { str_hash }
-+      rule(:expr) { hash }
-+      root(:expr)
-+    end
-+
-+We're essentially redefining the parser object's #hash method here. So the parse might work, but the packrat caching doesn't - because it used to stick parsers into a hash. Now this should be impossible, because we're using the `#object_id` of the parser - a speed gain
-+
-+    HashParser.new.parse('hash') # did raise a TypeError, but doesn't now
-+
-+Looking back, getting this error was not only probable, but inevitable: Everyone constructs parsers for programming languages, and almost all modern programming languages know the hash as a construct. Hope this one stays buried. 
-+
-+## i18n and the Difference between Byte and Character Position
-+
-+This is hard to get right, especially when considering the differences between the 1.8 and 1.9 branches of Ruby. By dropping 1.8 support, we got rid of a special branch of problems, now really the only thing that remains is treating character and byte offsets consistently. Ruby itself doesn't really: 
-+
-+| method                  | seeks by/returns  |
-+-----------------------------------------------
-+| `String#[]`             | character         |
-+| `StringScanner#pos`     | byte              |
-+| `StringScanner#pos=`    | byte              |
-+| `StringScanner#charpos` | character         |
-+
-+In parslet, we adopt the following conventions: 
-+
-+* `Source#bytepos` and `Source#bytepos=` only deal in byte positions. We don't have a choice here, since StringScanner only seeks to byte locations, probably for speed reasons. These methods are used internally for parsing, caching and resetting the parse. 
-+* `Source#pos` returns character positions. This method is used for returning positions associated to slices. 
-+
-+So let's test if we get this right by using input composed of the unicode chars 'öäü', mainly because I can type those easily on this keyboard. 
-+
-+    class I18NParser < Parslet::Parser
-+      rule(:nl) { str("\n") }
-+      rule(:ouml) { str("ö") }
-+      rule(:auml) { str("ä") }
-+      rule(:expr) { ((ouml | auml).repeat(1).as(:line) >> nl).repeat(1) }
-+      root(:expr)
-+    end
-+
-+    result = I18NParser.new.parse("äö\nä\nö\n")
-+
-+    [{ofs: 0, line: 1, col: 1}, 
-+     {ofs: 3, line: 2, col: 1}, 
-+     {ofs: 5, line: 3, col: 1}].zip(result).each do |expect, capture|
-+      capture[:line].offset.assert == expect[:ofs]
-+      capture[:line].line_and_column.assert == expect.values_at(:line, :col)
-+    end 
-+
-+
---- /dev/null
-+++ ruby-parslet/spec/acceptance/examples_spec.rb
-@@ -0,0 +1,37 @@
-+require 'spec_helper'
-+require 'open3'
-+
-+describe "Regression on" do
-+  Dir["example/*.rb"].each do |example|
-+    context example do
-+      # Generates a product path for a given example file. 
-+      def product_path(str, ext)
-+        str.
-+          gsub('.rb', ".#{ext}").
-+          gsub('example/','example/output/')
-+      end
-+      
-+      it "runs successfully" do
-+        stdin, stdout, stderr = Open3.popen3("ruby -Ku #{example}")
-+        
-+        handle_map = {
-+          stdout => :out, 
-+          stderr => :err
-+        }
-+        expectation_found = handle_map.any? do |io, ext|
-+          name = product_path(example, ext)
-+          
-+          if File.exists?(name)
-+            io.read.strip.should == File.read(name).strip
-+            true
-+          end
-+        end
-+        
-+        unless expectation_found
-+          fail "Example doesn't have either an .err or an .out file. "+
-+            "Please create in examples/output!"
-+        end
-+      end
-+    end
-+  end
-+end
---- /dev/null
-+++ ruby-parslet/spec/acceptance/infix_parser_spec.rb
-@@ -0,0 +1,112 @@
-+require 'spec_helper'
-+
-+describe 'Infix expression parsing' do
-+  class InfixExpressionParser < Parslet::Parser
-+    rule(:space) { match['\s'] }
-+
-+    def cts atom
-+      atom >> space.repeat
-+    end
-+    def infix *args
-+      Infix.new(*args)
-+    end
-+
-+    rule(:mul_op) { match['*/'] >> str(' ').maybe }
-+    rule(:add_op) { match['+-'] >> str(' ').maybe }
-+    rule(:digit) { match['0-9'] }
-+    rule(:integer) { cts digit.repeat(1) }
-+
-+    rule(:expression) { infix_expression(integer, 
-+      [mul_op, 2, :left], 
-+      [add_op, 1, :right]) }
-+  end
-+
-+  let(:p) { InfixExpressionParser.new }
-+  describe '#integer' do
-+    let(:i) { p.integer }
-+    it "parses integers" do
-+      i.should parse('1')
-+      i.should parse('123')
-+    end 
-+    it "consumes trailing white space" do
-+      i.should parse('1   ')
-+      i.should parse('134   ')
-+    end 
-+    it "doesn't parse floats" do
-+      i.should_not parse('1.3')
-+    end 
-+  end
-+  describe '#multiplication' do
-+    let(:m) { p.expression }
-+    it "parses simple multiplication" do
-+      m.should parse('1*2').as(l: '1', o: '*', r: '2')
-+    end
-+    it "parses simple multiplication with spaces" do
-+      m.should parse('1 * 2').as(l: '1 ', o: '* ', r: '2')
-+    end
-+    it "parses division" do
-+      m.should parse('1/2')
-+    end 
-+  end
-+  describe '#addition' do
-+    let(:a) { p.expression }
-+    
-+    it "parses simple addition" do
-+      a.should parse('1+2')
-+    end 
-+    it "parses complex addition" do
-+      a.should parse('1+2+3-4')
-+    end
-+    it "parses a single element" do
-+      a.should parse('1')
-+    end
-+  end
-+
-+  describe 'mixed operations' do
-+    let(:mo) { p.expression }
-+
-+    describe 'inspection' do
-+      it 'produces useful expressions' do
-+        p.expression.parslet.inspect.should == 
-+          "infix_expression(INTEGER, [MUL_OP, ADD_OP])"
-+      end
-+    end
-+    describe 'right associativity' do
-+      it 'produces trees that lean right' do
-+        mo.should parse('1+2+3').as(
-+          l: '1', o: '+', r: {l: '2', o: '+', r: '3'})
-+      end      
-+    end
-+    describe 'left associativity' do
-+      it 'produces trees that lean left' do
-+        mo.should parse('1*2*3').as(
-+          l: {l:'1', o:'*', r:'2'}, o:'*', r:'3')
-+      end      
-+    end
-+    describe 'error handling' do
-+      describe 'incomplete expression' do
-+        it 'produces the right error' do
-+          cause = catch_failed_parse {
-+            mo.parse('1+') }
-+
-+          cause.ascii_tree.to_s.should == <<-ERROR
-+INTEGER was expected at line 1 char 3.
-+`- Failed to match sequence (DIGIT{1, } SPACE{0, }) at line 1 char 3.
-+   `- Expected at least 1 of DIGIT at line 1 char 3.
-+      `- Premature end of input at line 1 char 3.
-+          ERROR
-+        end
-+      end
-+      describe 'invalid operator' do
-+        it 'produces the right error' do
-+          cause = catch_failed_parse {
-+            mo.parse('1%') }
-+
-+          cause.ascii_tree.to_s.should == <<-ERROR
-+Don't know what to do with "%" at line 1 char 2.
-+          ERROR
-+        end
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/acceptance/regression_spec.rb
-@@ -0,0 +1,314 @@
-+# Encoding: UTF-8
-+
-+require 'spec_helper'
-+
-+require 'parslet'
-+
-+describe "Regressions from real examples" do
-+  # This parser piece produces on the left a subtree that is keyed (a hash)
-+  # and on the right a subtree that is a repetition of such subtrees. I've
-+  # for now decided that these would merge into the repetition such that the
-+  # return value is an array. This avoids maybe loosing keys/values in a 
-+  # hash merge. 
-+  #
-+  class ArgumentListParser
-+    include Parslet
-+
-+    rule :argument_list do
-+      expression.as(:argument) >> 
-+        (comma >> expression.as(:argument)).repeat
-+    end
-+    rule :expression do
-+      string
-+    end
-+    rule :string do
-+      str('"') >> 
-+      (
-+        str('\\') >> any |
-+        str('"').absent? >> any
-+      ).repeat.as(:string) >>
-+      str('"') >> space?
-+    end
-+    rule :comma do
-+      str(',') >> space?
-+    end
-+    rule :space? do
-+      space.maybe
-+    end
-+    rule :space do
-+      match("[ \t]").repeat(1)
-+    end
-+    
-+    def parse(str)
-+      argument_list.parse(str)
-+    end
-+  end
-+  describe ArgumentListParser do
-+    let(:instance) { ArgumentListParser.new }
-+    it "should have method expression" do
-+      instance.should respond_to(:expression)
-+    end 
-+    it 'should parse "arg1", "arg2"' do
-+      result = ArgumentListParser.new.parse('"arg1", "arg2"')
-+      
-+      result.should have(2).elements
-+      result.each do |r|
-+        r[:argument]
-+      end
-+    end
-+    it 'should parse "arg1", "arg2", "arg3"' do
-+      result = ArgumentListParser.new.parse('"arg1", "arg2", "arg3"')
-+      
-+      result.should have(3).elements
-+      result.each do |r|
-+        r[:argument]
-+      end
-+    end
-+  end
-+
-+  class ParensParser < Parslet::Parser
-+    rule(:balanced) {
-+      str('(').as(:l) >> balanced.maybe.as(:m) >> str(')').as(:r)
-+    }
-+  
-+    root(:balanced)
-+  end
-+  describe ParensParser do
-+    let(:instance) { ParensParser.new }
-+    
-+    context "statefulness: trying several expressions in sequence" do
-+      it "should not be stateful" do
-+        # NOTE: Since you've come here to read this, I'll explain why
-+        # this is broken and not fixed: You're looking at the tuning branch, 
-+        # which rewrites a bunch of stuff - so I have failing tests to 
-+        # remind me of what is left to be done. And to remind you not to 
-+        # trust this code. 
-+        instance.parse('(())')
-+        lambda {
-+          instance.parse('((()))')
-+          instance.parse('(((())))')
-+        }.should_not raise_error
-+      end 
-+    end
-+    context "expression '(())'" do
-+      let(:result) { instance.parse('(())') }
-+
-+      it "should yield a doubly nested hash" do
-+        result.should be_a(Hash)
-+        result.should have_key(:m)
-+        result[:m].should be_a(Hash)   # This was an array earlier
-+      end 
-+      context "inner hash" do
-+        let(:inner) { result[:m] }
-+        
-+        it "should have nil as :m" do
-+          inner[:m].should be_nil
-+        end 
-+      end
-+    end
-+  end
-+
-+  class ALanguage < Parslet::Parser
-+    root(:expressions)
-+
-+    rule(:expressions) { (line >> eol).repeat(1) | line }
-+    rule(:line) { space? >> an_expression.as(:exp).repeat }
-+    rule(:an_expression) { str('a').as(:a) >> space? }
-+
-+    rule(:eol) { space? >> match["\n\r"].repeat(1) >> space? }
-+
-+    rule(:space?) { space.repeat }
-+    rule(:space) { multiline_comment.as(:multi) | line_comment.as(:line) | str(' ') }
-+
-+    rule(:line_comment) { str('//') >> (match["\n\r"].absent? >> any).repeat }
-+    rule(:multiline_comment) { str('/*') >> (str('*/').absent? >> any).repeat >> str('*/') }
-+  end
-+  describe ALanguage do
-+    def remove_indent(s)
-+      s.to_s.lines.map { |l| l.chomp.strip }.join("\n")
-+    end
-+    
-+    it "should count lines correctly" do
-+      cause = catch_failed_parse {
-+        subject.parse('a
-+          a a a 
-+          aaa // ff
-+          /* 
-+          a
-+          */
-+          b
-+        ')
-+      }
-+
-+      remove_indent(cause.ascii_tree).should == remove_indent(%q(
-+      Expected one of [(LINE EOL){1, }, LINE] at line 1 char 1.
-+      |- Extra input after last repetition at line 7 char 11.
-+      |  `- Failed to match sequence (LINE EOL) at line 7 char 11.
-+      |     `- Failed to match sequence (SPACE? [\n\r]{1, } SPACE?) at line 7 char 11.
-+      |        `- Expected at least 1 of [\n\r] at line 7 char 11.
-+      |           `- Failed to match [\n\r] at line 7 char 11.
-+      `- Don't know what to do with "\n         " at line 1 char 2.).strip)
-+    end 
-+  end
-+
-+  class BLanguage < Parslet::Parser
-+    root :expression
-+    rule(:expression) { b.as(:one) >> b.as(:two) }
-+    rule(:b) { str('b') }
-+  end
-+  describe BLanguage do
-+    it "should parse 'bb'" do
-+      subject.should parse('bb').as(:one => 'b', :two => 'b')
-+    end 
-+    it "should transform with binding constraint" do
-+      transform = Parslet::Transform.new do |t|
-+        t.rule(:one => simple(:b), :two => simple(:b)) { :ok }
-+      end
-+      transform.apply(subject.parse('bb')).should == :ok
-+    end 
-+  end
-+
-+  class UnicodeLanguage < Parslet::Parser
-+    root :gobble
-+    rule(:gobble) { any.repeat }
-+  end
-+  describe UnicodeLanguage do
-+    it "should parse UTF-8 strings" do
-+      subject.should parse('éèäöü').as('éèäöü')
-+      subject.should parse('RubyKaigi2009のテーマは、「変わる/変える」です。 前回の').as('RubyKaigi2009のテーマは、「変わる/変える」です。 前回の')
-+    end 
-+  end
-+  
-+  class UnicodeSentenceLanguage < Parslet::Parser
-+    rule(:sentence) { (match('[^。]').repeat(1) >> str("。")).as(:sentence) }
-+    rule(:sentences) { sentence.repeat }
-+    root(:sentences)
-+  end
-+  describe UnicodeSentenceLanguage do
-+    let(:string) {
-+      "RubyKaigi2009のテーマは、「変わる/変える」です。 前回の" +
-+      "RubyKaigi2008のテーマであった「多様性」の言葉の通り、 " +
-+      "2008年はRubyそのものに関しても、またRubyの活躍する舞台に関しても、 " +
-+      "ますます多様化が進みつつあります。RubyKaigi2008は、そのような " +
-+      "Rubyの生態系をあらためて認識する場となりました。 しかし、" +
-+      "こうした多様化が進む中、異なる者同士が単純に距離を 置いたままでは、" +
-+      "その違いを認識したところであまり意味がありません。 異なる実装、" +
-+      "異なる思想、異なる背景といった、様々な多様性を理解しつつ、 " +
-+      "すり合わせるべきものをすり合わせ、変えていくべきところを " +
-+      "変えていくことが、豊かな未来へとつながる道に違いありません。"
-+    }
-+    
-+    it "should parse sentences" do
-+      subject.should parse(string)
-+    end 
-+  end
-+
-+  class TwoCharLanguage < Parslet::Parser
-+    root :twochar
-+    rule(:twochar) { any >> str('2') }
-+  end
-+  describe TwoCharLanguage do
-+    def di(s)
-+      s.strip.to_s.lines.map { |l| l.chomp.strip }.join("\n")
-+    end
-+
-+    it "should raise an error" do
-+      error = catch_failed_parse {
-+        subject.parse('123') }
-+      di(error.ascii_tree).should == di(%q(
-+        Failed to match sequence (. '2') at line 1 char 2.
-+        `- Don't know what to do with "3" at line 1 char 3.
-+      ))
-+    end 
-+  end
-+
-+  # Issue #68: Extra input reporting, written by jmettraux
-+  class RepetitionParser < Parslet::Parser
-+    rule(:nl)      { match('[\s]').repeat(1) }
-+    rule(:nl?)     { nl.maybe }
-+    rule(:sp)      { str(' ').repeat(1) }
-+    rule(:sp?)     { str(' ').repeat(0) }
-+    rule(:line)    { sp >> str('line') }
-+    rule(:body)    { ((line | block) >> nl).repeat(0) }
-+    rule(:block)   { sp? >> str('begin') >> sp >> match('[a-z]') >> nl >>
-+                     body >> sp? >> str('end') }
-+    rule(:blocks)  { nl? >> block >> (nl >> block).repeat(0) >> nl? }
-+
-+    root(:blocks)
-+  end
-+  describe RepetitionParser do
-+    def di(s)
-+      s.strip.to_s.lines.map { |l| l.chomp.strip }.join("\n")
-+    end
-+
-+    it 'parses a block' do
-+      subject.parse(%q{
-+        begin a
-+        end
-+      })
-+    end
-+    it 'parses nested blocks' do
-+      subject.parse(%q{
-+        begin a
-+          begin b
-+          end
-+        end
-+      })
-+    end
-+    it 'parses successive blocks' do
-+      subject.parse(%q{
-+        begin a
-+        end
-+        begin b
-+        end
-+      })
-+    end
-+    it 'fails gracefully on a missing end' do
-+      error = catch_failed_parse {
-+        subject.parse(%q{
-+          begin a
-+            begin b
-+          end
-+        }) }
-+      
-+      di(error.ascii_tree).should == di(%q(
-+        Failed to match sequence (NL? BLOCK (NL BLOCK){0, } NL?) at line 2 char 11.
-+        `- Failed to match sequence (SP? 'begin' SP [a-z] NL BODY SP? 'end') at line 5 char 9.
-+           `- Premature end of input at line 5 char 9.
-+        ))
-+    end
-+    it 'fails gracefully on a missing end (2)' do
-+      error = catch_failed_parse {
-+        subject.parse(%q{
-+          begin a
-+          end
-+          begin b
-+            begin c
-+          end
-+        }) }
-+
-+      di(error.ascii_tree).should == di(%q(
-+        Failed to match sequence (NL? BLOCK (NL BLOCK){0, } NL?) at line 3 char 14.
-+        `- Don't know what to do with "begin b\n  " at line 4 char 11.
-+        ))
-+    end
-+    it 'fails gracefully on a missing end (deepest reporter)' do
-+      error = catch_failed_parse {
-+        subject.parse(%q{
-+            begin a
-+            end
-+            begin b
-+              begin c
-+                li
-+              end
-+            end
-+          },
-+          :reporter => Parslet::ErrorReporter::Deepest.new) }
-+
-+      di(error.ascii_tree).should == di(%q(
-+        Failed to match sequence (NL? BLOCK (NL BLOCK){0, } NL?) at line 3 char 16.
-+        `- Expected "end", but got "li\n" at line 6 char 17.
-+        ))
-+    end
-+  end
-+end
---- /dev/null
-+++ ruby-parslet/spec/acceptance/repetition_and_maybe_spec.rb
-@@ -0,0 +1,42 @@
-+require 'spec_helper'
-+
-+describe "Tree output" do
-+  extend Parslet
-+
-+  def self.hash_examples(h)
-+    h.each do |atom, expected|
-+      it "should convert #{atom} to #{expected.inspect}" do
-+        atom.parse(input).should == expected
-+      end
-+    end
-+  end
-+
-+  context "when parsing the empty string" do
-+    let(:input) { '' }
-+    hash_examples( 
-+      # No naming 
-+      str('a').maybe              => '', 
-+      str('a').repeat             => '',
-+      
-+      # Named contents: maybe yields nil
-+      str('a').maybe.as(:f)       => {:f => nil},
-+      str('a').repeat.as(:f)      => {:f => []}, 
-+      
-+      # Contents that aren't simple strings
-+      (str('a') >> str('b')).maybe.as(:f)     => {:f => nil},
-+      (str('a') >> str('b')).repeat.as(:f)    => {:f => []}, 
-+      
-+      # The other way around: Contents would be tagged, but nil result isn't
-+      (str('a') >> str('b')).as(:f).maybe     => '',
-+      (str('a') >> str('b')).as(:f).repeat    => ''
-+    )
-+  end
-+  
-+  context "when parsing 'aa'" do
-+    let(:input) { 'aa' }
-+    hash_examples(
-+      # since they're not named, repetitions get merged together.
-+      str('a').as(:a).repeat >> str('a').as(:a).repeat => [{:a=>'a'},{:a=>'a'}]
-+    )
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/acceptance/unconsumed_input_spec.rb
-@@ -0,0 +1,21 @@
-+require 'spec_helper'
-+
-+describe "Unconsumed input:" do
-+  class RepeatingBlockParser < Parslet::Parser
-+    root :expressions
-+    rule(:expressions) { expression.repeat }
-+    rule(:expression) { str('(') >> aab >> str(')') }
-+    rule(:aab) { str('a').repeat(1) >> str('b') }
-+  end
-+  describe RepeatingBlockParser do
-+    let(:parser) { described_class.new }
-+    it "throws annotated error" do
-+      error = catch_failed_parse { parser.parse('(aaac)') }
-+    end
-+    it "doesn't error out if prefix is true" do
-+      expect {
-+        parser.parse('(aaac)', :prefix => true)
-+      }.not_to raise_error
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atom_results_spec.rb
-@@ -0,0 +1,39 @@
-+require 'spec_helper'
-+
-+describe 'Result of a Parslet#parse' do
-+  include Parslet; extend Parslet
-+  
-+  describe "regression" do
-+    [
-+      # Behaviour with maybe-nil
-+      [str('foo').maybe >> str('bar'), "bar", "bar"],
-+      [str('bar') >> str('foo').maybe, "bar", 'bar'], 
-+      
-+      # These might be hard to understand; look at the result of 
-+      #   str.maybe >> str
-+      # and 
-+      #   str.maybe >> str first. 
-+      [(str('f').maybe >> str('b')).repeat, "bb", "bb"],
-+      [(str('b') >> str('f').maybe).repeat, "bb", 'bb'], 
-+      
-+      [str('a').as(:a) >> (str('b') >> str('c').as(:a)).repeat, 'abc', 
-+        [{:a=>'a'}, {:a=>'c'}]], 
-+      
-+      [str('a').as(:a).repeat >> str('b').as(:b).repeat, 'ab', [{:a=>'a'}, {:b=>'b'}]], 
-+      
-+      # Repetition behaviour / named vs. unnamed
-+      [str('f').repeat, '', ''], 
-+      [str('f').repeat.as(:f), '', {:f => []}],
-+
-+      # Maybe behaviour / named vs. unnamed
-+      [str('f').maybe, '', ''], 
-+      [str('f').maybe.as(:f), '', {:f => nil}],
-+    ].each do |parslet, input, result|
-+      context "#{parslet.inspect}" do
-+        it "should parse \"#{input}\" into \"#{result}\"" do
-+          parslet.parse(input).should == result
-+        end
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/alternative_spec.rb
-@@ -0,0 +1,26 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Alternative do
-+  include Parslet
-+  
-+  describe '| shortcut' do
-+    let(:alternative) { str('a') | str('b') }
-+    
-+    context "when chained with different atoms" do
-+      before(:each) { 
-+        # Chain something else to the alternative parslet. If it modifies the
-+        # parslet atom in place, we'll notice: 
-+        
-+        alternative | str('d')
-+      }
-+      let!(:chained) { alternative | str('c') }
-+      
-+      
-+      it "is side-effect free" do
-+        chained.should parse('c')
-+        chained.should parse('a')
-+        chained.should_not parse('d')
-+      end 
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/base_spec.rb
-@@ -0,0 +1,124 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Base do
-+  let(:parslet) { Parslet::Atoms::Base.new }
-+  let(:context) { Parslet::Atoms::Context.new }
-+
-+  describe "<- #try(io)" do
-+    it "should raise NotImplementedError" do
-+      lambda {
-+        parslet.try(flexmock(:io), context, false)
-+      }.should raise_error(NotImplementedError)
-+    end 
-+  end
-+  describe "<- #flatten_sequence" do
-+    [
-+      # 9 possibilities for making a word of 2 letters from the alphabeth of
-+      # A(rray), H(ash) and S(tring). Make sure that all results are valid.
-+      #
-+      ['a', 'b'], 'ab',                             # S S
-+      [['a'], ['b']], ['a', 'b'],                   # A A
-+      [{:a=>'a'}, {:b=>'b'}], {:a=>'a',:b=>'b'},    # H H
-+      
-+      [{:a=>'a'}, ['a']], [{:a=>'a'}, 'a'],         # H A
-+      [{:a=>'a'}, 's'],   {:a=>'a'},                # H S
-+
-+      [['a'], {:a=>'a'}], ['a', {:a=>'a'}],         # A H (symmetric to H A)
-+      [['a'], 'b'], ['a'],                          # A S 
-+
-+      ['a', {:b=>'b'}], {:b=>'b'},                  # S H (symmetric to H S)
-+      ['a', ['b']], ['b'],                          # S A (symmetric to A S)
-+      
-+      [nil, ['a']], ['a'],                          # handling of lhs nil
-+      [nil, {:a=>'a'}], {:a=>'a'},
-+      [['a'], nil], ['a'],                          # handling of rhs nil
-+      [{:a=>'a'}, nil], {:a=>'a'}
-+    ].each_slice(2) do |sequence, result|
-+      context "for " + sequence.inspect do
-+        it "should equal #{result.inspect}" do
-+          parslet.flatten_sequence(sequence).should == result
-+        end
-+      end
-+    end
-+  end
-+  describe "<- #flatten_repetition" do
-+    def unnamed(obj)
-+      parslet.flatten_repetition(obj, false)
-+    end
-+    
-+    it "should give subtrees precedence" do
-+      unnamed([[{:a=>"a"}, {:m=>"m"}], {:a=>"a"}]).should == [{:a=>"a"}]
-+    end 
-+  end
-+  describe '#parse(source)' do
-+    context "when given something that looks like a source" do
-+      let(:source) { flexmock("source lookalike", 
-+        :line_and_column => [1,2], 
-+        :bytepos => 1, 
-+        :chars_left => 0) }
-+      
-+      it "should not rewrap in a source" do
-+        flexmock(Parslet::Source).
-+          should_receive(:new => :source_created).never
-+        
-+        begin
-+          parslet.parse(source) 
-+        rescue NotImplementedError
-+        end
-+      end 
-+    end
-+  end
-+  
-+  context "when the parse fails, the exception" do
-+    it "should contain a string" do
-+      begin
-+        Parslet.str('foo').parse('bar')
-+      rescue Parslet::ParseFailed => ex
-+        ex.message.should be_kind_of(String)
-+      end
-+    end 
-+  end
-+  context "when not all input is consumed" do
-+    let(:parslet) { Parslet.str('foo') }
-+    
-+    it "should raise with a proper error message" do
-+      error = catch_failed_parse {
-+        parslet.parse('foobar') }
-+      
-+      error.to_s.should == "Don't know what to do with \"bar\" at line 1 char 4."
-+    end 
-+  end
-+  context "when only parsing string prefix" do
-+    let(:parslet) { Parslet.str('foo') >> Parslet.str('bar') }
-+    
-+    it "returns the first half on a prefix parse" do
-+      parslet.parse('foobarbaz', :prefix => true).should == 'foobar'
-+    end 
-+  end
-+
-+  describe ':reporter option' do
-+    let(:parslet) { Parslet.str('test') >> Parslet.str('ing') }
-+    let(:reporter) { flexmock(:reporter) }
-+    
-+    it "replaces the default reporter" do
-+      cause = flexmock(:cause)
-+      
-+      # Two levels of the parse, calling two different error reporting
-+      # methods.
-+      reporter.
-+        should_receive(:err_at).once
-+      reporter.
-+        should_receive(:err => cause).once
-+      
-+      # The final cause will be sent the #raise method.
-+      cause.
-+        should_receive(:raise).once.and_throw(:raise)
-+      
-+      catch(:raise) {
-+        parslet.parse('testung', :reporter => reporter)
-+        
-+        fail "NEVER REACHED"
-+      }
-+    end 
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/capture_spec.rb
-@@ -0,0 +1,21 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Capture do
-+  include Parslet
-+  
-+  let(:context) { Parslet::Atoms::Context.new(nil) }
-+  
-+  def inject string, parser
-+    source = Parslet::Source.new(string)
-+    parser.apply(source, context, true)
-+  end
-+  
-+  it "should capture simple results" do
-+    inject 'a', str('a').capture(:a)
-+    context.captures[:a].should == 'a'
-+  end 
-+  it "should capture complex results" do
-+    inject 'a', str('a').as(:b).capture(:a)
-+    context.captures[:a].should == {:b => 'a'}
-+  end 
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/combinations_spec.rb
-@@ -0,0 +1,5 @@
-+require 'spec_helper'
-+
-+describe "Parslet combinations" do
-+  include Parslet
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/dsl_spec.rb
-@@ -0,0 +1,17 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::DSL do
-+  describe "deprecated methods" do
-+    let(:parslet) { Parslet.str('foo') }
-+    describe "<- #absnt?" do
-+      subject { parslet.absnt? }
-+      its(:bound_parslet) { should == parslet }
-+      its(:positive) { should == false }
-+    end
-+    describe "<- #prsnt?" do
-+      subject { parslet.prsnt? }
-+      its(:bound_parslet) { should == parslet }
-+      its(:positive) { should == true }
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/entity_spec.rb
-@@ -0,0 +1,52 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Entity do
-+  context "when constructed with str('bar') inside" do
-+    let(:named) { Parslet::Atoms::Entity.new('name', &proc { Parslet.str('bar') }) }
-+
-+    it "should parse 'bar' without raising exceptions" do
-+      named.parse('bar')
-+    end 
-+    it "should raise when applied to 'foo'" do
-+      lambda {
-+        named.parse('foo')
-+      }.should raise_error(Parslet::ParseFailed)
-+    end 
-+
-+    describe "#inspect" do
-+      it "should return the name of the entity" do
-+        named.inspect.should == 'NAME'
-+      end 
-+    end
-+  end
-+  context "when constructed with empty block" do
-+    let(:entity) { Parslet::Atoms::Entity.new('name', &proc { }) }
-+    
-+    it "should raise NotImplementedError" do
-+      lambda {
-+        entity.parse('some_string')
-+      }.should raise_error(NotImplementedError)
-+    end 
-+  end
-+  
-+  context "recursive definition parser" do
-+    class RecDefParser
-+      include Parslet
-+      rule :recdef do
-+        str('(') >> atom >> str(')')
-+      end
-+      rule :atom do
-+        str('a') | str('b') | recdef
-+      end
-+    end
-+    let(:parser) { RecDefParser.new }
-+    
-+    it "should parse balanced parens" do
-+      parser.recdef.parse("(((a)))")
-+    end
-+    it "should not throw 'stack level too deep' when printing errors" do
-+      cause = catch_failed_parse { parser.recdef.parse('(((a))') }
-+      cause.ascii_tree
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/infix_spec.rb
-@@ -0,0 +1,5 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Infix do
-+
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/lookahead_spec.rb
-@@ -0,0 +1,22 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Lookahead do
-+  include Parslet
-+  
-+  describe 'negative lookahead' do
-+    it "influences the error tree" do
-+      parser = str('f').absent? >> str('b')
-+      cause = catch_failed_parse { parser.parse('f') }
-+      
-+      cause.ascii_tree.should == "Failed to match sequence (!'f' 'b') at line 1 char 1.\n`- Input should not start with 'f' at line 1 char 1.\n"
-+    end 
-+  end
-+  describe 'positive lookahead' do
-+    it "influences the error tree" do
-+      parser = str('f').present? >> str('b')
-+      cause = catch_failed_parse { parser.parse('b') }
-+      
-+      cause.ascii_tree.should == "Failed to match sequence (&'f' 'b') at line 1 char 1.\n`- Input should start with 'f' at line 1 char 1.\n"
-+    end 
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/named_spec.rb
-@@ -0,0 +1,4 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Named do
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/re_spec.rb
-@@ -0,0 +1,14 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Re do
-+  describe "construction" do
-+    include Parslet
-+    
-+    it "should allow match(str) form" do
-+      match('[a]').should be_a(Parslet::Atoms::Re)
-+    end 
-+    it "should allow match[str] form" do
-+      match['a'].should be_a(Parslet::Atoms::Re)
-+    end 
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/repetition_spec.rb
-@@ -0,0 +1,24 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Repetition do
-+  include Parslet
-+
-+  describe "repeat" do
-+    let(:parslet) { str('a') }
-+    
-+    describe "(min, max)" do
-+      subject { parslet.repeat(1,2) }
-+      
-+      it { should_not parse("") }
-+      it { should parse("a") }
-+      it { should parse("aa") }
-+    end
-+    describe "0 times" do
-+      it "raises an ArgumentError" do
-+        expect {
-+          parslet.repeat(0,0)
-+        }.to raise_error(ArgumentError)
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/scope_spec.rb
-@@ -0,0 +1,26 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Scope do
-+  include Parslet
-+  include Parslet::Atoms::DSL
-+  
-+  
-+  let(:context) { Parslet::Atoms::Context.new(nil) }
-+  let(:captures) { context.captures }
-+  
-+  def inject string, parser
-+    source = Parslet::Source.new(string)
-+    parser.apply(source, context, true)
-+  end
-+  
-+  let(:aabb) { 
-+    scope {
-+      match['ab'].capture(:f) >> dynamic { |s,c| str(c.captures[:f]) }
-+    }
-+  }
-+  it "keeps values of captures outside" do
-+    captures[:f] = 'old_value'
-+    inject 'aa', aabb
-+    captures[:f].should == 'old_value'
-+  end 
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/sequence_spec.rb
-@@ -0,0 +1,28 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Sequence do
-+  include Parslet
-+  
-+  let(:sequence) { described_class.new }
-+  
-+  describe '>> shortcut' do
-+    let(:sequence) { str('a') >> str('b') }
-+    
-+    context "when chained with different atoms" do
-+      before(:each) { 
-+        # Chain something else to the sequence parslet. If it modifies the
-+        # parslet atom in place, we'll notice: 
-+        
-+        sequence >> str('d')
-+      }
-+      let!(:chained) { sequence >> str('c') }
-+      
-+      
-+      it "is side-effect free" do
-+        chained.should parse('abc')
-+        chained.should_not parse('abdc')
-+      end 
-+    end
-+    
-+  end
-+end
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/str_spec.rb
-@@ -0,0 +1,15 @@
-+# Encoding: UTF-8
-+
-+require 'spec_helper'
-+
-+describe Parslet::Atoms::Str do
-+  def str(s)
-+    described_class.new(s)
-+  end
-+  
-+  describe 'regression #1: multibyte characters' do
-+    it "parses successfully (length check works)" do
-+      str('あああ').should parse('あああ')
-+    end 
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms/visitor_spec.rb
-@@ -0,0 +1,80 @@
-+require 'spec_helper'
-+
-+describe Parslet::Atoms do
-+  include Parslet
-+  let(:visitor) { flexmock(:visitor) }
-+  
-+  describe Parslet::Atoms::Str do
-+    let(:parslet) { str('foo') }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_str).with('foo').once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe Parslet::Atoms::Re do
-+    let(:parslet) { match['abc'] }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_re).with('[abc]').once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe Parslet::Atoms::Sequence do
-+    let(:parslet) { str('a') >> str('b') }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_sequence).with(Array).once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe Parslet::Atoms::Repetition do
-+    let(:parslet) { str('a').repeat(1,2) }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_repetition).with(:repetition, 1, 2, Parslet::Atoms::Base).once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe Parslet::Atoms::Alternative do
-+    let(:parslet) { str('a') | str('b') }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_alternative).with(Array).once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe Parslet::Atoms::Named do
-+    let(:parslet) { str('a').as(:a) }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_named).with(:a, Parslet::Atoms::Base).once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe Parslet::Atoms::Entity do
-+    let(:parslet) { Parslet::Atoms::Entity.new('foo', &lambda {}) }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_entity).with('foo', Proc).once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe Parslet::Atoms::Lookahead do
-+    let(:parslet) { str('a').absent? }
-+    it "should call back visitor" do
-+      visitor.should_receive(:visit_lookahead).with(false, Parslet::Atoms::Base).once
-+      
-+      parslet.accept(visitor)
-+    end 
-+  end
-+  describe "< Parslet::Parser" do
-+    let(:parslet) { Parslet::Parser.new }
-+    it "calls back to visitor" do
-+      visitor.should_receive(:visit_parser).with(:root).once
-+      
-+      flexmock(parslet, :root => :root)
-+      parslet.accept(visitor)
-+    end 
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/atoms_spec.rb
-@@ -0,0 +1,429 @@
-+require 'spec_helper'
-+
-+require 'timeout'
-+require 'parslet'
-+
-+describe Parslet do
-+  def not_parse
-+    raise_error(Parslet::ParseFailed)
-+  end
-+  
-+  include Parslet
-+  extend Parslet
-+
-+  def src(str); Parslet::Source.new str; end
-+  let(:context) { Parslet::Atoms::Context.new }
-+  
-+  describe "match('[abc]')" do
-+    attr_reader :parslet
-+    before(:each) do
-+      @parslet = match('[abc]')
-+    end
-+    
-+    it "should parse {a,b,c}" do
-+      parslet.parse('a')
-+      parslet.parse('b')
-+      parslet.parse('c')
-+    end 
-+    it "should not parse d" do
-+      cause = catch_failed_parse {
-+        parslet.parse('d')
-+      }
-+      cause.to_s.should == "Failed to match [abc] at line 1 char 1."
-+    end 
-+    it "should print as [abc]" do
-+      parslet.inspect.should == "[abc]"
-+    end 
-+  end
-+  describe "match(['[a]').repeat(3)" do
-+    attr_reader :parslet
-+    before(:each) do
-+      @parslet = match('[a]').repeat(3)
-+    end
-+    
-+    context "when failing on input 'aa'" do
-+      let!(:cause) {
-+        catch_failed_parse { parslet.parse('aa') }
-+      }
-+      it "should have a relevant cause" do
-+        cause.to_s.should == "Expected at least 3 of [a] at line 1 char 1."
-+      end 
-+      it "should have a tree with 2 nodes" do
-+        cause.children.should have(1).elements
-+      end 
-+    end
-+    it "should succeed on 'aaa'" do
-+      parslet.parse('aaa')
-+    end 
-+    it "should succeed on many 'a'" do
-+      parslet.parse('a'*100)
-+    end 
-+    it "should inspect as [a]{3, }" do
-+      parslet.inspect.should == "[a]{3, }"
-+    end
-+  end
-+  describe "str('foo')" do
-+    attr_reader :parslet
-+    before(:each) do
-+      @parslet = str('foo')
-+    end
-+    
-+    it "should parse 'foo'" do
-+      parslet.parse('foo')
-+    end
-+    it "should not parse 'bar'"  do
-+      cause = catch_failed_parse { parslet.parse('bar') }
-+      cause.to_s.should == 
-+        "Expected \"foo\", but got \"bar\" at line 1 char 1."
-+    end
-+    it "should inspect as 'foo'" do
-+      parslet.inspect.should == "'foo'"
-+    end 
-+  end
-+  describe "str('foo').maybe" do
-+    let(:parslet) { str('foo').maybe }
-+
-+    it "should parse a foo" do
-+      parslet.parse('foo')
-+    end
-+    it "should leave pos untouched if there is no foo" do
-+      source = src('bar')
-+      parslet.apply(source, context)
-+      source.pos.charpos.should == 0
-+    end
-+    it "should inspect as 'foo'?" do
-+      parslet.inspect.should == "'foo'?"
-+    end 
-+    context "when parsing 'foo'" do
-+      subject { parslet.parse('foo') }
-+      
-+      it { should == 'foo' }
-+    end
-+    context "when parsing ''" do
-+      subject { parslet.parse('') } 
-+      
-+      it { should == '' } 
-+    end
-+  end
-+  describe "str('foo') >> str('bar')" do
-+    let(:parslet) { str('foo') >> str('bar') }
-+    
-+    context "when it fails on input 'foobaz'" do
-+      let!(:cause) {
-+        catch_failed_parse { parslet.parse('foobaz') }
-+      }
-+
-+      it "should not parse 'foobaz'" do
-+        cause.to_s.should == "Failed to match sequence ('foo' 'bar') at line 1 char 4."
-+      end
-+      it "should have 2 nodes in error tree" do
-+        cause.should have(1).children
-+      end 
-+    end
-+    it "should parse 'foobar'" do
-+      parslet.parse('foobar')
-+    end
-+    it "should inspect as ('foo' 'bar')" do
-+      parslet.inspect.should == "'foo' 'bar'"
-+    end 
-+  end
-+  describe "str('foo') | str('bar')" do
-+    attr_reader :parslet
-+    before(:each) do
-+      @parslet = str('foo') | str('bar')
-+    end
-+    
-+    context "when failing on input 'baz'" do
-+      let!(:cause) {
-+        catch_failed_parse { parslet.parse('baz') }
-+      }
-+
-+      it "should have a sensible cause" do
-+        cause.to_s.should == "Expected one of ['foo', 'bar'] at line 1 char 1."
-+      end   
-+      it "should have an error tree with 3 nodes" do
-+        cause.should have(2).children
-+      end 
-+    end
-+    
-+    it "should accept 'foo'" do
-+      parslet.parse('foo')
-+    end
-+    it "should accept 'bar'" do
-+      parslet.parse('bar')
-+    end
-+    it "should inspect as ('foo' / 'bar')" do
-+      parslet.inspect.should == "'foo' / 'bar'"
-+    end 
-+  end
-+  describe "str('foo').present? (positive lookahead)" do
-+    attr_reader :parslet
-+    before(:each) do
-+      @parslet = str('foo').present?
-+    end
-+    
-+    it "should inspect as &'foo'" do
-+      parslet.inspect.should == "&'foo'"
-+    end 
-+    context "when fed 'foo'" do
-+      it "should parse" do
-+        success, _ = parslet.apply(src('foo'), context)
-+        success.should == true
-+      end
-+      it "should not change input position" do
-+        source = src('foo')
-+        parslet.apply(source, context)
-+        source.pos.charpos.should == 0
-+      end
-+    end
-+    context "when fed 'bar'" do
-+      it "should not parse" do
-+        lambda { parslet.parse('bar') }.should not_parse
-+      end
-+    end
-+    describe "<- #parse" do
-+      it "should return nil" do
-+        parslet.apply(src('foo'), context).should == [true, nil]
-+      end 
-+    end
-+  end
-+  describe "str('foo').absent? (negative lookahead)" do
-+    attr_reader :parslet
-+    before(:each) do
-+      @parslet = str('foo').absent?
-+    end
-+    
-+    it "should inspect as !'foo'" do
-+      parslet.inspect.should == "!'foo'"
-+    end 
-+    context "when fed 'bar'" do
-+      it "should parse" do
-+        parslet.apply(src('bar'), context).should == [true, nil]
-+      end
-+      it "should not change input position" do
-+        source = src('bar')
-+        parslet.apply(source, context)
-+        source.pos.charpos.should == 0
-+      end
-+    end
-+    context "when fed 'foo'" do
-+      it "should not parse" do
-+        lambda { parslet.parse('foo') }.should not_parse
-+      end
-+    end
-+  end
-+  describe "non greedy matcher combined with greedy matcher (possible loop)" do
-+    attr_reader :parslet
-+    before(:each) do
-+      # repeat will always succeed, since it has a minimum of 0. It will not
-+      # modify input position in that case. absent? will, depending on
-+      # implementation, match as much as possible and call its inner element
-+      # again. This leads to an infinite loop. This example tests for the 
-+      # absence of that loop. 
-+      @parslet = str('foo').repeat.maybe
-+    end
-+    
-+    it "should not loop infinitely" do
-+      lambda {
-+        timeout(1) { parslet.parse('bar') }
-+      }.should raise_error(Parslet::ParseFailed)
-+    end 
-+  end
-+  describe "any" do
-+    attr_reader :parslet
-+    before(:each) do
-+      @parslet = any
-+    end
-+    
-+    it "should match" do
-+      parslet.parse('.')
-+    end 
-+    it "should consume one char" do
-+      source = src('foo')
-+      parslet.apply(source, context)
-+      source.pos.charpos.should == 1
-+    end 
-+  end
-+  describe "eof behaviour" do
-+    context "when the pattern just doesn't consume the input" do
-+      let (:parslet) { any }
-+
-+      it "should fail the parse" do
-+        cause = catch_failed_parse { parslet.parse('..') }
-+        cause.to_s.should == "Don't know what to do with \".\" at line 1 char 2."
-+      end 
-+    end
-+    context "when the pattern doesn't match the input" do
-+      let (:parslet) { (str('a')).repeat(1) }
-+      attr_reader :exception
-+      before(:each) do
-+        begin 
-+          parslet.parse('a.')
-+        rescue => @exception
-+        end
-+      end
-+
-+      it "raises Parslet::ParseFailed" do
-+        # ParseFailed here, because the input doesn't match the parser grammar. 
-+        exception.should be_kind_of(Parslet::ParseFailed)
-+      end 
-+      it "has the correct error message" do
-+        exception.message.should == \
-+          "Extra input after last repetition at line 1 char 2."
-+      end 
-+    end
-+  end
-+  
-+  describe "<- #as(name)" do
-+    context "str('foo').as(:bar)" do
-+      it "should return :bar => 'foo'" do
-+        str('foo').as(:bar).parse('foo').should == { :bar => 'foo' }
-+      end 
-+    end
-+    context "match('[abc]').as(:name)" do
-+      it "should return :name => 'b'" do
-+        match('[abc]').as(:name).parse('b').should == { :name => 'b' }
-+      end 
-+    end
-+    context "match('[abc]').repeat.as(:name)" do
-+      it "should return collated result ('abc')" do
-+        match('[abc]').repeat.as(:name).
-+          parse('abc').should == { :name => 'abc' }
-+      end
-+    end
-+    context "(str('a').as(:a) >> str('b').as(:b)).as(:c)" do
-+      it "should return a hash of hashes" do
-+        (str('a').as(:a) >> str('b').as(:b)).as(:c).
-+          parse('ab').should == {
-+            :c => {
-+              :a => 'a', 
-+              :b => 'b'
-+            }
-+          }
-+      end 
-+    end
-+    context "(str('a').as(:a) >> str('ignore') >> str('b').as(:b))" do
-+      it "should correctly flatten (leaving out 'ignore')" do
-+        (str('a').as(:a) >> str('ignore') >> str('b').as(:b)).
-+          parse('aignoreb').should == 
-+          {
-+            :a => 'a', 
-+            :b => 'b'
-+          }
-+      end
-+    end
-+    
-+    context "(str('a') >> str('ignore') >> str('b')) (no .as(...))" do
-+      it "should return simply the original string" do
-+        (str('a') >> str('ignore') >> str('b')).
-+          parse('aignoreb').should == 'aignoreb'
-+      end 
-+    end
-+    context "str('a').as(:a) >> str('b').as(:a)" do
-+      attr_reader :parslet
-+      before(:each) do
-+        @parslet = str('a').as(:a) >> str('b').as(:a)
-+      end
-+      
-+      it "should issue a warning that a key is being overwritten in merge" do
-+        flexmock(parslet).
-+          should_receive(:warn).once
-+        parslet.parse('ab').should == { :a => 'b' }
-+      end
-+      it "should return :a => 'b'" do
-+        flexmock(parslet).
-+          should_receive(:warn)
-+          
-+        parslet.parse('ab').should == { :a => 'b' }
-+      end  
-+    end
-+    context "str('a').absent?" do
-+      it "should return something in merge, even though it is nil" do
-+        (str('a').absent? >> str('b').as(:b)).
-+          parse('b').should == {:b => 'b'}
-+      end
-+    end
-+    context "str('a').as(:a).repeat" do
-+      it "should return an array of subtrees" do
-+        str('a').as(:a).repeat.
-+          parse('aa').should == [{:a=>'a'}, {:a=>'a'}]
-+      end 
-+    end
-+  end
-+  describe "<- #flatten(val)" do
-+    def call(val)
-+      dummy = str('a')
-+      flexmock(dummy, :warn => nil)
-+      dummy.flatten(val)
-+    end
-+    
-+    [
-+      # In absence of named subtrees: ----------------------------------------
-+      # Sequence or Repetition
-+      [ [:sequence, 'a', 'b'], 'ab' ], 
-+      [ [:repetition, 'a', 'a'], 'aa' ],
-+            
-+      # Nested inside another node
-+      [ [:sequence, [:sequence, 'a', 'b']], 'ab' ],
-+      # Combined with lookahead (nil)
-+      [ [:sequence, nil, 'a'], 'a' ],
-+                  
-+      # Including named subtrees ---------------------------------------------
-+      # Atom: A named subtree
-+      [ {:a=>'a'}, {:a=>'a'} ],
-+      # Composition of subtrees
-+      [ [:sequence, {:a=>'a'},{:b=>'b'}], {:a=>'a',:b=>'b'} ],
-+      # Mixed subtrees :sequence of :repetition yields []
-+      [ [:sequence, [:repetition, {:a => 'a'}], {:a => 'a'} ], [{:a=>'a'}, {:a=>'a'}]],
-+      [ [:sequence, {:a => 'a'},[:repetition, {:a => 'a'}] ], [{:a=>'a'}, {:a=>'a'}]],
-+      [ [:sequence, [:repetition, {:a => 'a'}],[:repetition, {:a => 'a'}] ], [{:a=>'a'}, {:a=>'a'}]],
-+      # Repetition
-+      [ [:repetition, [:repetition, {:a=>'a'}], [:repetition, {:a=>'a'}]], 
-+        [{:a => 'a'}, {:a => 'a'}]],
-+      [ [:repetition, {:a=>'a'}, 'a', {:a=>'a'}], [{:a=>'a'}, {:a=>'a'}]],
-+      [ [:repetition, {:a=>'a'}, [:repetition, {:b=>'b'}]], [{:a=>'a'}] ],
-+      
-+      # Some random samples --------------------------------------------------
-+      [ [:sequence, {:a => :b, :b => :c}], {:a=>:b, :b=>:c} ], 
-+      [ [:sequence, {:a => :b}, 'a', {:c=>:d}], {:a => :b, :c=>:d} ], 
-+      [ [:repetition, {:a => :b}, 'a', {:c=>:d}], [{:a => :b}, {:c=>:d}] ], 
-+      [ [:sequence, {:a => :b}, {:a=>:d}], {:a => :d} ], 
-+      [ [:sequence, {:a=>:b}, [:sequence, [:sequence, "\n", nil]]], {:a=>:b} ], 
-+      [ [:sequence, nil, " "], ' ' ], 
-+    ].each do |input, output|
-+      it "should transform #{input.inspect} to #{output.inspect}" do
-+        call(input).should == output
-+      end
-+    end
-+  end
-+
-+  describe "combinations thereof (regression)" do
-+    success=[
-+      [(str('a').repeat >> str('b').repeat), 'aaabbb'] 
-+    ].each do |(parslet, input)|
-+      describe "#{parslet.inspect} applied to #{input.inspect}" do
-+        it "should parse successfully" do
-+          parslet.parse(input)
-+        end
-+      end 
-+    end
-+
-+    inspection=[
-+      [str('a'),                              "'a'"                 ], 
-+      [(str('a') | str('b')).maybe,           "('a' / 'b')?"        ], 
-+      [(str('a') >> str('b')).maybe,          "('a' 'b')?"          ], 
-+      [str('a').maybe.maybe,                  "'a'??"               ], 
-+      [(str('a')>>str('b')).maybe.maybe,      "('a' 'b')??"         ], 
-+      [(str('a') >> (str('b') | str('c'))),   "'a' ('b' / 'c')"], 
-+      
-+      [str('a') >> str('b').repeat,           "'a' 'b'{0, }"        ], 
-+      [(str('a')>>str('b')).repeat,           "('a' 'b'){0, }"      ]  
-+    ].each do |(parslet, inspect_output)|
-+      context "regression for #{parslet.inspect}" do
-+        it "should inspect correctly as #{inspect_output}" do
-+          parslet.inspect.should == inspect_output
-+        end 
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/convenience_spec.rb
-@@ -0,0 +1,48 @@
-+require 'spec_helper'
-+
-+describe 'parslet/convenience' do
-+  require 'parslet/convenience'
-+  include Parslet
-+  
-+  class FooParser < Parslet::Parser
-+    rule(:foo) { str('foo') }
-+    root(:foo)
-+  end
-+  
-+  describe 'parse_with_debug' do
-+    let(:parser) { flexmock FooParser.new }
-+    context 'internal' do
-+      before(:each) do
-+        # Suppress output.
-+        #
-+        parser.should_receive(:puts)
-+      end
-+      it 'should exist' do
-+        lambda { parser.parse_with_debug('anything') }.should_not raise_error
-+      end
-+      it 'should catch ParseFailed exceptions' do
-+        lambda { parser.parse_with_debug('bar') }.should_not raise_error
-+      end
-+      it 'should parse correct input like #parse' do
-+        lambda { parser.parse_with_debug('foo') }.should_not raise_error
-+      end
-+    end
-+    context 'output' do
-+      it 'should puts once for tree output' do
-+        parser.should_receive(:puts).once
-+        
-+        parser.parse_with_debug('incorrect')
-+      end
-+      it "should puts once for the error on unconsumed input" do
-+        parser.should_receive(:puts).once
-+
-+        parser.parse_with_debug('foobar')
-+      end 
-+    end
-+    
-+    it "should work for all parslets" do
-+      str('foo').parse_with_debug('foo')
-+      match['bar'].parse_with_debug('a')
-+    end 
-+  end
-+end
---- /dev/null
-+++ ruby-parslet/spec/parslet/error_reporter/deepest_spec.rb
-@@ -0,0 +1,73 @@
-+require 'spec_helper'
-+
-+describe Parslet::ErrorReporter::Deepest do
-+  let(:reporter) { described_class.new }
-+  let(:fake_source) { flexmock('source') }
-+  
-+  describe '#err' do
-+    before(:each) { fake_source.should_receive(
-+      :pos => 13, 
-+      :line_and_column => [1,1]) }
-+    
-+    it "returns the deepest cause" do
-+      flexmock(reporter).
-+        should_receive(:deepest).and_return(:deepest)
-+      reporter.err('parslet', fake_source, 'message').
-+        should == :deepest
-+    end 
-+  end
-+  describe '#err_at' do
-+    before(:each) { fake_source.should_receive(
-+      :pos => 13, 
-+      :line_and_column => [1,1]) }
-+
-+    it "returns the deepest cause" do
-+      flexmock(reporter).
-+        should_receive(:deepest).and_return(:deepest)
-+      reporter.err('parslet', fake_source, 'message', 13).
-+        should == :deepest
-+    end
-+  end
-+  describe '#deepest(cause)' do
-+    def fake_cause(pos=13, children=nil)
-+      flexmock('cause' + pos.to_s, :pos => pos, :children => children)
-+    end
-+    
-+    context "when there is no deepest cause yet" do
-+      let(:cause) { fake_cause }
-+      it "returns the given cause" do
-+        reporter.deepest(cause).should == cause
-+      end
-+    end
-+    context "when the previous cause is deeper (no relationship)" do
-+      let(:previous) { fake_cause }
-+      before(:each) { 
-+        reporter.deepest(previous) }
-+      
-+      it "returns the previous cause" do
-+        reporter.deepest(fake_cause(12)).
-+          should == previous
-+      end 
-+    end
-+    context "when the previous cause is deeper (child)" do
-+      let(:previous) { fake_cause }
-+      before(:each) { 
-+        reporter.deepest(previous) }
-+        
-+      it "returns the given cause" do
-+        given = fake_cause(12, [previous])
-+        reporter.deepest(given).should == given
-+      end 
-+    end
-+    context "when the previous cause is shallower" do
-+      before(:each) { 
-+        reporter.deepest(fake_cause) }
-+      
-+      it "stores the cause as deepest" do
-+        deeper = fake_cause(14)
-+        reporter.deepest(deeper)
-+        reporter.deepest_cause.should == deeper
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/error_reporter/tree_spec.rb
-@@ -0,0 +1,7 @@
-+require 'spec_helper'
-+
-+require 'parslet/error_reporter'
-+
-+describe Parslet::ErrorReporter::Tree do
-+  
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/export_spec.rb
-@@ -0,0 +1,67 @@
-+require 'spec_helper'
-+
-+describe Parslet::Parser, "exporting to other lingos" do
-+  class MiniLisp < Parslet::Parser
-+    root :expression
-+    rule(:expression) {
-+      space? >> str('(') >> space? >> body >> str(')')
-+    }
-+    
-+    rule(:body) {
-+      (expression | identifier | float | integer | string).repeat.as(:exp)
-+    }
-+    
-+    rule(:space) {
-+      match('\s').repeat(1)
-+    }
-+    rule(:space?) {
-+      space.maybe
-+    }
-+    
-+    rule(:identifier) { 
-+      (match('[a-zA-Z=*]') >> match('[a-zA-Z=*_]').repeat).as(:identifier) >> space?
-+    }
-+    
-+    rule(:float) { 
-+      (
-+        integer >> (
-+          str('.') >> match('[0-9]').repeat(1) |
-+          str('e') >> match('[0-9]').repeat(1)
-+        ).as(:e)
-+      ).as(:float) >> space?
-+    }
-+    
-+    rule(:integer) {
-+      ((str('+') | str('-')).maybe >> match("[0-9]").repeat(1)).as(:integer) >> space?
-+    }
-+    
-+    rule(:string) {
-+      str('"') >> (
-+        str('\\') >> any |
-+        str('"').absent? >> any 
-+      ).repeat.as(:string) >> str('"') >> space?
-+    }
-+  end
-+
-+  # I only update the files once I've verified the new syntax to work with 
-+  # the respective tools. This is more an acceptance test than a real spec. 
-+
-+  describe "<- #to_citrus" do
-+    let(:citrus) { File.read(
-+      File.join(File.dirname(__FILE__), 'minilisp.citrus'))
-+    }
-+    it "should be valid citrus syntax" do
-+      # puts MiniLisp.new.to_citrus
-+      MiniLisp.new.to_citrus.should == citrus 
-+    end 
-+  end
-+  describe "<- #to_treetop" do
-+    let(:treetop) { File.read(
-+      File.join(File.dirname(__FILE__), 'minilisp.tt'))
-+    }
-+    it "should be valid treetop syntax" do
-+      # puts MiniLisp.new.to_treetop
-+      MiniLisp.new.to_treetop.should == treetop
-+    end 
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/expression/treetop_spec.rb
-@@ -0,0 +1,74 @@
-+require 'spec_helper'
-+
-+require 'parslet'
-+
-+describe Parslet::Expression::Treetop do
-+  include Parslet
-+
-+  describe "positive samples" do
-+    [ # pattern             # input
-+      "'abc'",              'abc', 
-+      "...",                'abc', 
-+      "[1-4]",              '3',
-+      
-+      "'abc'?",             'abc', 
-+      "'abc'?",             '', 
-+      
-+      "('abc')",            'abc', 
-+      
-+      "'a' 'b'",            'ab', 
-+      "'a' ('b')",          'ab', 
-+      
-+      "'a' / 'b'",          'a', 
-+      "'a' / 'b'",          'b', 
-+      
-+      "'a'*",               'aaa', 
-+      "'a'*",               '', 
-+
-+      "'a'+",               'aa', 
-+      "'a'+",               'a', 
-+      
-+      "'a'{1,2}",           'a',
-+      "'a'{1,2}",           'aa',
-+
-+      "'a'{1,}",            'a',
-+      "'a'{1,}",            'aa',
-+
-+      "'a'{,2}",            '',
-+      "'a'{,2}",            'a',
-+      "'a'{,2}",            'aa',
-+    ].each_slice(2) do |pattern, input|
-+      context "exp(#{pattern.inspect})" do
-+        let(:parslet) { exp(pattern) }
-+        subject { parslet }
-+        it { should parse(input) }
-+        context "string representation" do
-+          subject { exp(parslet.to_s) }
-+          it { should parse(input, :trace => true) }
-+        end
-+      end
-+    end
-+  end
-+  describe "negative samples" do
-+    [ # pattern             # input
-+      "'abc'",              'cba', 
-+      "[1-4]",              '5',
-+      
-+      "'a' / 'b'",          'c', 
-+      
-+      "'a'+",               '',
-+      
-+      "'a'{1,2}",           '',
-+      "'a'{1,2}",           'aaa',
-+      
-+      "'a'{1,}",            '',
-+
-+      "'a'{,2}",            'aaa',
-+    ].each_slice(2) do |pattern, input|
-+      context "exp(#{pattern.inspect})" do
-+        subject { exp(pattern) }
-+        it { should_not parse(input) }
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/minilisp.citrus
-@@ -0,0 +1,29 @@
-+grammar MiniLisp
-+  rule root
-+    (expression)
-+  end
-+  rule expression
-+    ((space_p) "(" (space_p) (body) ")")
-+  end
-+  rule space_p
-+    (space)0*1
-+  end
-+  rule body
-+    ((expression) | (identifier) | (float) | (integer) | (string))0*
-+  end
-+  rule space
-+    \s1*
-+  end
-+  rule identifier
-+    (([a-zA-Z=*] [a-zA-Z=*_]0*) (space_p))
-+  end
-+  rule float
-+    (((integer) (("." [0-9]1*) | ("e" [0-9]1*))) (space_p))
-+  end
-+  rule integer
-+    ((("+" | "-")0*1 [0-9]1*) (space_p))
-+  end
-+  rule string
-+    ("\"" (("\\" .) | (!"\"" .))0* "\"" (space_p))
-+  end
-+end
---- /dev/null
-+++ ruby-parslet/spec/parslet/minilisp.tt
-@@ -0,0 +1,29 @@
-+grammar MiniLisp
-+  rule root
-+    (expression)
-+  end
-+  rule expression
-+    ((space_p) "(" (space_p) (body) ")")
-+  end
-+  rule space_p
-+    (space)0..1
-+  end
-+  rule body
-+    ((expression) / (identifier) / (float) / (integer) / (string))0..
-+  end
-+  rule space
-+    \s1..
-+  end
-+  rule identifier
-+    (([a-zA-Z=*] [a-zA-Z=*_]0..) (space_p))
-+  end
-+  rule float
-+    (((integer) (("." [0-9]1..) / ("e" [0-9]1..))) (space_p))
-+  end
-+  rule integer
-+    ((("+" / "-")0..1 [0-9]1..) (space_p))
-+  end
-+  rule string
-+    ("\"" (("\\" .) / (!"\"" .))0.. "\"" (space_p))
-+  end
-+end
---- /dev/null
-+++ ruby-parslet/spec/parslet/parser_spec.rb
-@@ -0,0 +1,31 @@
-+require 'spec_helper'
-+
-+describe Parslet::Parser do
-+  include Parslet
-+  class FooParser < Parslet::Parser
-+    rule(:foo) { str('foo') }
-+    root(:foo)
-+  end
-+  
-+  describe "<- .root" do
-+    parser = Class.new(Parslet::Parser)
-+    parser.root :root_parslet
-+    
-+    it "should have defined a 'root' method, returning the root" do
-+      parser_instance = parser.new
-+      flexmock(parser_instance).should_receive(:root_parslet => :answer)
-+      
-+      parser_instance.root.should == :answer
-+    end 
-+  end
-+  it "should parse 'foo'" do
-+    FooParser.new.parse('foo').should == 'foo'
-+  end 
-+  context "composition" do
-+    let(:parser) { FooParser.new }
-+    it "should allow concatenation" do
-+      composite = parser >> str('bar')
-+      composite.should parse('foobar')
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/parslet_spec.rb
-@@ -0,0 +1,38 @@
-+require 'spec_helper'
-+
-+describe Parslet do
-+  include Parslet
-+  
-+  describe Parslet::ParseFailed do
-+    it "should be caught by an empty rescue" do
-+      begin
-+        raise Parslet::ParseFailed
-+      rescue
-+        # Success! Ignore this.
-+      end
-+    end 
-+  end
-+  describe "<- .rule" do
-+    # Rules define methods. This can be easily tested by defining them right 
-+    # here. 
-+    context "empty rule" do
-+      rule(:empty) { }
-+      
-+      it "should raise a NotImplementedError" do
-+        lambda {
-+          empty.parslet
-+        }.should raise_error(NotImplementedError)
-+      end 
-+    end
-+    
-+    context "containing 'any'" do
-+      rule(:any_rule) { any }
-+      subject { any_rule }
-+      
-+      it { should be_a Parslet::Atoms::Entity }
-+      it "should memoize the returned instance" do
-+        any_rule.object_id.should == any_rule.object_id
-+      end 
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/pattern_spec.rb
-@@ -0,0 +1,268 @@
-+require 'spec_helper'
-+
-+require 'parslet'
-+
-+describe Parslet::Pattern do
-+  include Parslet
-+  
-+  # These two factory methods help make the specs more robust to interface
-+  # changes. They also help to label trees (t) and patterns (p).
-+  def p(pattern)
-+    Parslet::Pattern.new(pattern)
-+  end
-+  def t(obj)
-+    obj
-+  end
-+  
-+  # Tries to match pattern to the tree, and verifies the bindings hash. Don't
-+  # use this for new examples.
-+  #
-+  RSpec::Matchers.define :match_with_bind do |pattern, exp_bindings|
-+    failure_message_for_should do |tree|
-+      "expected #{pattern.inspect} to match #{tree.inspect}, but didn't. (block wasn't called or not correctly)"
-+    end
-+    match do |tree|
-+      bindings = Parslet::Pattern.new(pattern).match(tree)
-+      bindings && bindings == exp_bindings
-+    end
-+  end
-+
-+  # This is the more modern version of verifying a match: (uses 'exp'
-+  # implicitly). Checks for a match of pattern in +exp+ and yields the
-+  # matched variables.
-+  #
-+  def with_match_locals(pattern, &block) 
-+    bindings = p(pattern).match(exp)
-+    bindings.should_not be_nil
-+    
-+    block.call(bindings) if block
-+  end
-+  
-+  # Can't use #match here, so I went to the Thesaurus.
-+  #
-+  RSpec::Matchers.define :detect do |pattern|
-+    match do |tree|
-+      bindings = Parslet::Pattern.new(pattern).match(tree)
-+
-+      bindings ? true : false
-+    end
-+  end
-+  
-+  describe "<- #match" do
-+    context "injecting bindings" do
-+      let(:pattern) { p(simple(:x)) }
-+      
-+      it "should not modify the original bindings hash" do
-+        h = {}
-+        b=pattern.match('a', h)
-+        h.size.should == 0
-+        b.size.should == 1
-+      end
-+      it "should return nil when no match succeeds" do
-+        pattern.match([], :foo => :bar).should be_nil
-+      end
-+      context "when matching simple(:x) against 'a'" do
-+        let(:bindings) { pattern.match(t('a'), :foo => :bar) }
-+        
-+        before(:each) { bindings.should_not be_nil }
-+        it "should return the injected bindings" do
-+          bindings[:foo].should == :bar
-+        end
-+        it "should return the new bindings" do  
-+          bindings[:x].should == 'a'
-+        end
-+      end
-+    end
-+    context "simple strings" do
-+      let(:exp) { 'aaaa' }
-+
-+      it "should match simple strings" do
-+        exp.should match_with_bind(simple(:x), :x => 'aaaa')
-+      end 
-+    end
-+    context "simple hash {:a => 'b'}" do
-+      attr_reader :exp
-+      before(:each) do
-+        @exp = t(:a => 'b')
-+      end
-+
-+      it "should not match {:a => simple(:x), :b => simple(:y)}" do
-+        exp.should_not detect(:a => simple(:x), :b => simple(:y))
-+      end
-+      it "should match {:a => simple(:x)}, binding 'x' to the first argument" do
-+        exp.should match_with_bind({:a => simple(:x)}, :x => 'b')
-+      end 
-+      it "should match {:a => 'b'} with no binds" do
-+        exp.should match_with_bind({:a => 'b'}, {})
-+      end 
-+    end
-+    context "a more complex hash {:a => {:b => 'c'}}" do
-+      attr_reader :exp
-+      before(:each) do
-+        @exp = t(:a => {:b => 'c'})
-+      end
-+      
-+      it "should match wholly with {:a => {:b => simple(:x)}}" do
-+        exp.should match_with_bind({:a => {:b => simple(:x)}}, :x => 'c')
-+      end
-+      it "should match wholly with {:a => subtree(:t)}" do
-+        with_match_locals(:a => subtree(:t)) do |dict|
-+          dict[:t].should == {:b => 'c'}
-+        end
-+      end
-+      it "should not bind subtrees to variables in {:a => simple(:x)}" do
-+        p(:a => simple(:x)).should_not detect(exp)
-+      end
-+    end
-+    context "a more complex hash {:a => 'a', :b => 'b'}" do
-+      attr_reader :exp
-+      before(:each) do
-+        @exp = t({:a => 'a', :b => 'b'})
-+      end
-+
-+      it "should not match partially" do
-+        Parslet::Pattern.new(:a => simple(:x)).match(exp).should be_nil
-+      end 
-+      it "should match completely" do
-+        exp.should match_with_bind({:a => simple(:x), :b => simple(:y)}, 
-+          :x => 'a', 
-+          :y => 'b')
-+      end 
-+    end
-+    context "an array of 'a', 'b', 'c'" do
-+      let(:exp) { ['a', 'b', 'c'] }
-+
-+      it "should match all elements at once" do
-+        exp.should match_with_bind(
-+          [simple(:x), simple(:y), simple(:z)], 
-+          :x => 'a', :y => 'b', :z => 'c')
-+      end 
-+    end
-+    context "{:a => 'a', :b => 'b'}" do
-+      attr_reader :exp
-+      before(:each) do
-+        @exp = t(:a => 'a', :b => 'b')
-+      end
-+
-+      it "should match both elements simple(:x), simple(:y)" do
-+        exp.should match_with_bind(
-+          {:a => simple(:x), :b => simple(:y)}, 
-+          :x => 'a', :y => 'b')
-+      end
-+      it "should not match a constrained match (simple(:x) != simple(:y))"  do
-+        exp.should_not detect({:a => simple(:x), :b => simple(:x)})
-+      end
-+    end
-+    context "{:a => 'a', :b => 'a'}" do
-+      attr_reader :exp
-+      before(:each) do
-+        @exp = t(:a => 'a', :b => 'a')
-+      end
-+
-+      it "should match constrained pattern" do
-+        exp.should match_with_bind(
-+          {:a => simple(:x), :b => simple(:x)}, 
-+          :x => 'a')
-+      end
-+    end
-+    context "{:sub1 => {:a => 'a'}, :sub2 => {:a => 'a'}}" do
-+      attr_reader :exp
-+      before(:each) do
-+        @exp = t({
-+          :sub1 => {:a => 'a'}, 
-+          :sub2 => {:a => 'a'} 
-+        })
-+      end
-+
-+      it "should verify constraints over several subtrees" do
-+        exp.should match_with_bind({
-+          :sub1 => {:a => simple(:x)}, 
-+          :sub2 => {:a => simple(:x)} 
-+        }, :x => 'a')
-+      end
-+      it "should return both bind variables simple(:x), simple(:y)" do
-+        exp.should match_with_bind({
-+          :sub1 => {:a => simple(:x)}, 
-+          :sub2 => {:a => simple(:y)} 
-+        }, :x => 'a', :y => 'a')
-+      end  
-+    end
-+    context "{:sub1 => {:a => 'a'}, :sub2 => {:a => 'b'}}" do
-+      attr_reader :exp
-+      before(:each) do
-+        @exp = t({
-+          :sub1 => {:a => 'a'}, 
-+          :sub2 => {:a => 'b'} 
-+        })
-+      end
-+
-+      it "should verify constraints over several subtrees" do
-+        exp.should_not match_with_bind({
-+          :sub1 => {:a => simple(:x)}, 
-+          :sub2 => {:a => simple(:x)} 
-+        }, :x => 'a')
-+      end
-+      it "should return both bind variables simple(:x), simple(:y)" do
-+        exp.should match_with_bind({
-+          :sub1 => {:a => simple(:x)}, 
-+          :sub2 => {:a => simple(:y)} 
-+        }, :x => 'a', :y => 'b')
-+      end  
-+    end
-+    context "[{:a => 'x'}, {:a => 'y'}]" do
-+      attr_reader :exp  
-+      before(:each) do
-+        @exp = t([{:a => 'x'}, {:a => 'y'}])
-+      end
-+      
-+      it "should not match sequence(:x) (as a whole)" do
-+        exp.should_not detect(sequence(:x))
-+      end
-+    end
-+    context "['x', 'y', 'z']" do
-+      attr_reader :exp  
-+      before(:each) do
-+        @exp = t(['x', 'y', 'z'])
-+      end
-+
-+      it "should match [simple(:x), simple(:y), simple(:z)]" do
-+        with_match_locals([simple(:x), simple(:y), simple(:z)]) do |dict|
-+          dict[:x].should == 'x'
-+          dict[:y].should == 'y'
-+          dict[:z].should == 'z'
-+        end
-+      end
-+      it "should match %w(x y z)" do
-+        exp.should match_with_bind(%w(x y z), { })
-+      end 
-+      it "should not match [simple(:x), simple(:y), simple(:x)]" do
-+        exp.should_not detect([simple(:x), simple(:y), simple(:x)])
-+      end
-+      it "should not match [simple(:x), simple(:y)]" do
-+        exp.should_not detect([simple(:x), simple(:y), simple(:x)])
-+      end
-+      it "should match sequence(:x) (as array)" do
-+        exp.should match_with_bind(sequence(:x), :x => ['x', 'y', 'z'])
-+      end
-+    end
-+    context "{:a => [1,2,3]}" do
-+      attr_reader :exp  
-+      before(:each) do
-+        @exp = t(:a => [1,2,3])
-+      end
-+
-+      it "should match :a => sequence(:x) (binding x to the whole array)" do
-+        exp.should match_with_bind({:a => sequence(:x)}, {:x => [1,2,3]})
-+      end
-+    end
-+    context "with differently ordered hashes" do
-+      it "should still match" do
-+        t(:a => 'a', :b => 'b').should detect(:a => 'a', :b => 'b')
-+        t(:a => 'a', :b => 'b').should detect(:b => 'b', :a => 'a')
-+
-+        t(:b => 'b', :a => 'a').should detect(:b => 'b', :a => 'a')
-+        t(:b => 'b', :a => 'a').should detect(:a => 'a', :b => 'b')
-+      end 
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/position_spec.rb
-@@ -0,0 +1,10 @@
-+# Encoding: UTF-8
-+
-+require 'spec_helper'
-+
-+describe Parslet::Position do
-+  slet(:position) { described_class.new('öäüö', 4) }
-+
-+  its(:charpos) { should == 2 }
-+  its(:bytepos) { should == 4 } 
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/rig/rspec_spec.rb
-@@ -0,0 +1,54 @@
-+require 'spec_helper'
-+require 'parslet/rig/rspec'
-+
-+describe 'rspec integration' do
-+  include Parslet
-+  subject { str('example') }
-+
-+  it { should parse('example') }
-+  it { should_not parse('foo') }
-+  it { should parse('example').as('example') }
-+  it { should_not parse('foo').as('example') }
-+  it { should_not parse('example').as('foo') }
-+
-+  it { str('foo').as(:bar).should parse('foo').as({:bar => 'foo'}) }
-+  it { str('foo').as(:bar).should_not parse('foo').as({:b => 'f'}) }
-+
-+  it 'accepts a block to assert more specific details about the parsing output' do
-+    str('foo').as(:bar).should(parse('foo').as { |output|
-+      output.should have_key(:bar)
-+      output.values.first.should == 'foo'
-+    })
-+  end
-+
-+  # Uncomment to test error messages manually: 
-+  # it { str('foo').should parse('foo', :trace => true).as('bar') }
-+  # it { str('foo').should parse('food', :trace => true) }
-+  # it { str('foo').should_not parse('foo', :trace => true).as('foo') }
-+  # it { str('foo').should_not parse('foo', :trace => true) }
-+  # it 'accepts a block to assert more specific details about the parsing output' do
-+  #   str('foo').as(:bar).should(parse('foo', :trace => true).as { |output|
-+  #     output.should_not have_key(:bar)
-+  #   })
-+  # end
-+  
-+end
-+
-+describe 'rspec3 syntax' do
-+  include Parslet
-+
-+  let(:s) { str('example') }
-+
-+  it { expect(s).to parse('example') }
-+  it { expect(s).not_to parse('foo') }
-+  it { expect(s).to parse('example').as('example') }
-+  it { expect(s).not_to parse('foo').as('example') }
-+
-+  it { expect(s).not_to parse('example').as('foo') }
-+
-+  # Uncomment to test error messages manually: 
-+  # it { expect(str('foo')).to parse('foo', :trace => true).as('bar') }
-+  # it { expect(str('foo')).to parse('food', :trace => true) }
-+  # it { expect(str('foo')).not_to parse('foo', :trace => true).as('foo') }
-+  # it { expect(str('foo')).not_to parse('foo', :trace => true) }
-+end
---- /dev/null
-+++ ruby-parslet/spec/parslet/scope_spec.rb
-@@ -0,0 +1,45 @@
-+require 'spec_helper'
-+
-+describe Parslet::Scope do
-+  let(:scope) { described_class.new }
-+  
-+  describe 'simple store/retrieve' do
-+    before(:each) { scope[:foo] = :bar }
-+    it "allows storing objects" do
-+      scope[:obj] = 42
-+    end 
-+    it "raises on access of empty slots" do
-+      expect {
-+        scope[:empty]
-+      }.to raise_error(Parslet::Scope::NotFound)
-+    end 
-+    it "allows retrieval of stored values" do
-+      scope[:foo].should == :bar
-+    end 
-+  end
-+  
-+  describe 'scoping' do
-+    before(:each) { scope[:depth] = 1 }
-+    before(:each) { scope.push }
-+    
-+    let(:depth) { scope[:depth] }
-+    subject { depth }
-+    
-+    it { should == 1 }
-+    describe 'after a push' do
-+      before(:each) { scope.push }
-+      it { should == 1 }
-+      
-+      describe 'and reassign' do
-+        before(:each) { scope[:depth] = 2 }
-+        
-+        it { should == 2 }
-+
-+        describe 'and a pop' do
-+          before(:each) { scope.pop }
-+          it { should == 1 }
-+        end
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/slice_spec.rb
-@@ -0,0 +1,140 @@
-+require 'spec_helper'
-+
-+describe Parslet::Slice do
-+  def cslice string, offset, cache=nil
-+    described_class.new(
-+      Parslet::Position.new(string, offset), 
-+      string, cache)
-+  end
-+
-+  describe "construction" do
-+    it "should construct from an offset and a string" do
-+      cslice('foobar', 40)
-+    end
-+  end
-+  context "('foobar', 40, 'foobar')" do
-+    let(:slice) { cslice('foobar', 40) }
-+    describe "comparison" do
-+      it "should be equal to other slices with the same attributes" do
-+        other = cslice('foobar', 40)
-+        slice.should == other
-+        other.should == slice
-+      end 
-+      it "should be equal to other slices (offset is irrelevant for comparison)" do
-+        other = cslice('foobar', 41)
-+        slice.should == other
-+        other.should == slice
-+      end 
-+      it "should be equal to a string with the same content" do
-+        slice.should == 'foobar'
-+      end
-+      it "should be equal to a string (inversed operands)" do
-+        'foobar'.should == slice
-+      end 
-+      it "should not be equal to a string" do
-+        slice.should_not equal('foobar')
-+      end 
-+      it "should not be eql to a string" do
-+        slice.should_not eql('foobar')
-+      end 
-+      it "should not hash to the same number" do
-+        slice.hash.should_not == 'foobar'.hash
-+      end 
-+    end
-+    describe "offset" do
-+      it "should return the associated offset" do
-+        slice.offset.should == 6
-+      end
-+      it "should fail to return a line and column" do
-+        lambda {
-+          slice.line_and_column
-+        }.should raise_error(ArgumentError)
-+      end 
-+      
-+      context "when constructed with a source" do
-+        let(:slice) { cslice(
-+          'foobar', 40,  
-+          flexmock(:cache, :line_and_column => [13, 14])) }
-+        it "should return proper line and column" do
-+          slice.line_and_column.should == [13, 14]
-+        end
-+      end
-+    end
-+    describe "string methods" do
-+      describe "matching" do
-+        it "should match as a string would" do
-+          slice.should match(/bar/)
-+          slice.should match(/foo/)
-+
-+          md = slice.match(/f(o)o/)
-+          md.captures.first.should == 'o'
-+        end
-+      end
-+      describe "<- #size" do
-+        subject { slice.size }
-+        it { should == 6 } 
-+      end
-+      describe "<- #+" do
-+        let(:other) { cslice('baz', 10) }
-+        subject { slice + other }
-+        
-+        it "should concat like string does" do
-+          subject.size.should == 9
-+          subject.should == 'foobarbaz'
-+          subject.offset.should == 6
-+        end 
-+      end
-+    end
-+    describe "conversion" do
-+      describe "<- #to_slice" do
-+        it "should return self" do
-+          slice.to_slice.should eq(slice)
-+        end 
-+      end
-+      describe "<- #to_sym" do
-+        it "should return :foobar" do
-+          slice.to_sym.should == :foobar
-+        end 
-+      end
-+      describe "cast to Float" do
-+        it "should return a float" do
-+          Float(cslice('1.345', 11)).should == 1.345
-+        end 
-+      end
-+      describe "cast to Integer" do
-+        it "should cast to integer as a string would" do
-+          s = cslice('1234', 40)
-+          Integer(s).should == 1234
-+          s.to_i.should == 1234
-+        end 
-+        it "should fail when Integer would fail on a string" do
-+          lambda { Integer(slice) }.should raise_error
-+        end 
-+        it "should turn into zero when a string would" do
-+          slice.to_i.should == 0
-+        end 
-+      end
-+    end
-+    describe "inspection and string conversion" do
-+      describe "#inspect" do
-+        subject { slice.inspect }
-+        it { should == '"foobar"@6' }
-+      end
-+      describe "#to_s" do
-+        subject { slice.to_s }
-+        it { should == 'foobar' }
-+      end
-+    end
-+    describe "serializability" do
-+      it "should serialize" do
-+        Marshal.dump(slice)
-+      end
-+      context "when storing a line cache" do
-+        let(:slice) { cslice('foobar', 40, Parslet::Source::LineCache.new()) }
-+        it "should serialize" do
-+          Marshal.dump(slice)
-+        end
-+      end
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/source/line_cache_spec.rb
-@@ -0,0 +1,74 @@
-+require 'spec_helper'
-+
-+describe Parslet::Source::RangeSearch do
-+  describe "<- #lbound" do
-+    context "for a simple array" do
-+      let(:ary) { [10, 20, 30, 40, 50] }
-+      before(:each) { ary.extend Parslet::Source::RangeSearch }
-+
-+      it "should return correct answers for numbers not in the array" do
-+        ary.lbound(5).should == 0
-+        ary.lbound(15).should == 1
-+        ary.lbound(25).should == 2
-+        ary.lbound(35).should == 3
-+        ary.lbound(45).should == 4
-+      end
-+      it "should return correct answers for numbers in the array" do
-+        ary.lbound(10).should == 1
-+        ary.lbound(20).should == 2
-+        ary.lbound(30).should == 3
-+        ary.lbound(40).should == 4
-+      end
-+      it "should cover right edge case" do
-+        ary.lbound(50).should be_nil
-+        ary.lbound(51).should be_nil
-+      end 
-+      it "should cover left edge case" do
-+        ary.lbound(0).should == 0
-+      end
-+    end
-+    context "for an empty array" do
-+      let(:ary) { [] }
-+      before(:each) { ary.extend Parslet::Source::RangeSearch }
-+
-+      it "should return nil" do
-+        ary.lbound(1).should be_nil
-+      end 
-+    end
-+  end
-+end
-+
-+describe Parslet::Source::LineCache do
-+  describe "<- scan_for_line_endings" do
-+    context "calculating the line_and_columns" do
-+      let(:str) { "foo\nbar\nbazd" }
-+
-+      it "should return the first line if we have no line ends" do
-+        subject.scan_for_line_endings(0, nil)
-+        subject.line_and_column(3).should == [1, 4]
-+
-+        subject.scan_for_line_endings(0, "")
-+        subject.line_and_column(5).should == [1, 6]
-+      end
-+
-+      it "should find the right line starting from pos 0" do
-+        subject.scan_for_line_endings(0, str)
-+        subject.line_and_column(5).should == [2, 2]
-+        subject.line_and_column(9).should == [3, 2]
-+      end
-+
-+      it "should find the right line starting from pos 5" do
-+        subject.scan_for_line_endings(5, str)
-+        subject.line_and_column(11).should == [2, 3]
-+      end
-+
-+      it "should find the right line if scannning the string multiple times" do
-+        subject.scan_for_line_endings(0, str)
-+        subject.scan_for_line_endings(0, "#{str}\nthe quick\nbrown fox")
-+        subject.line_and_column(10).should == [3,3]
-+        subject.line_and_column(24).should == [5,2]
-+      end
-+    end
-+  end
-+end
-+
---- /dev/null
-+++ ruby-parslet/spec/parslet/source_spec.rb
-@@ -0,0 +1,168 @@
-+# Encoding: UTF-8
-+
-+require 'spec_helper'
-+
-+describe Parslet::Source do
-+  describe "using simple input" do
-+    let(:str)     { "a"*100 + "\n" + "a"*100 + "\n" }
-+    let(:source)  { described_class.new(str) }
-+  
-+    describe "<- #read(n)" do
-+      it "should not raise error when the return value is nil" do
-+        described_class.new('').consume(1)
-+      end 
-+      it "should return 100 'a's when reading 100 chars" do
-+        source.consume(100).should == 'a'*100
-+      end
-+    end
-+    describe "<- #chars_left" do
-+      subject { source.chars_left }
-+  
-+      it { should == 202 }
-+      context "after depleting the source" do
-+        before(:each) { source.consume(10000) }
-+  
-+        it { should == 0 }
-+      end
-+    end
-+    describe "<- #pos" do
-+      subject { source.pos.charpos }
-+  
-+      it { should == 0 }
-+      context "after reading a few bytes" do
-+        it "should still be correct" do
-+          pos = 0
-+          10.times do
-+            pos += (n = rand(10)+1)
-+            source.consume(n)
-+  
-+            source.pos.charpos.should == pos
-+          end
-+        end 
-+      end
-+    end
-+    describe "<- #pos=(n)" do
-+      subject { source.pos.charpos }
-+      10.times do
-+        pos = rand(200)
-+        context "setting position #{pos}" do
-+          before(:each) { source.bytepos = pos }
-+  
-+          it { should == pos }
-+        end
-+      end
-+    end
-+    describe '#chars_until' do
-+      it 'should return 100 chars before line end' do
-+        source.chars_until("\n").should == 100
-+      end
-+    end
-+    describe "<- #column & #line" do
-+      subject { source.line_and_column }
-+  
-+      it { should == [1,1] }
-+  
-+      context "on the first line" do
-+        it "should increase column with every read" do
-+          10.times do |i|
-+            source.line_and_column.last.should == 1+i
-+            source.consume(1)
-+          end
-+        end 
-+      end
-+      context "on the second line" do
-+        before(:each) { source.consume(101) }
-+        it { should == [2, 1]}
-+      end
-+      context "after reading everything" do
-+        before(:each) { source.consume(10000) }
-+  
-+        context "when seeking to 9" do
-+          before(:each) { source.bytepos = 9 }
-+          it { should == [1, 10] }
-+        end
-+        context "when seeking to 100" do
-+          before(:each) { source.bytepos = 100 }
-+          it { should == [1, 101] }
-+        end
-+        context "when seeking to 101" do
-+          before(:each) { source.bytepos = 101 }
-+          it { should == [2, 1] }
-+        end
-+        context "when seeking to 102" do
-+          before(:each) { source.bytepos = 102 }
-+          it { should == [2, 2] }
-+        end
-+        context "when seeking beyond eof" do
-+          it "should not throw an error" do
-+            source.bytepos = 1000
-+          end 
-+        end
-+      end
-+      context "reading char by char, storing the results" do
-+        attr_reader :results
-+        before(:each) { 
-+          @results = {}
-+          while source.chars_left>0
-+            pos = source.pos.charpos
-+            @results[pos] = source.line_and_column
-+            source.consume(1)
-+          end
-+  
-+          @results.should have(202).entries
-+          @results
-+        }
-+  
-+        context "when using pos argument" do
-+          it "should return the same results" do
-+            results.each do |pos, result|
-+              source.line_and_column(pos).should == result
-+            end
-+          end 
-+        end
-+        it "should give the same results when seeking" do
-+          results.each do |pos, result|
-+            source.bytepos = pos
-+            source.line_and_column.should == result
-+          end
-+        end
-+        it "should give the same results when reading" do
-+          cur = source.bytepos = 0
-+          while source.chars_left>0
-+            source.line_and_column.should == results[cur]
-+            cur += 1
-+            source.consume(1)
-+          end
-+        end 
-+      end
-+    end
-+    
-+  end
-+  
-+  describe "reading encoded input" do
-+    let(:source) { described_class.new("éö変わる") }
-+
-+    def r str
-+      Regexp.new(Regexp.escape(str))
-+    end
-+  
-+    it "should read characters, not bytes" do
-+      source.should match(r("é"))
-+      source.consume(1)
-+      source.pos.charpos.should == 1
-+      source.bytepos.should == 2
-+      
-+      source.should match(r("ö"))
-+      source.consume(1)
-+      source.pos.charpos.should == 2
-+      source.bytepos.should == 4
-+      
-+      source.should match(r("変"))
-+      source.consume(1)
-+      
-+      source.consume(2)
-+      source.chars_left.should == 0
-+      source.chars_left.should == 0
-+    end 
-+  end
-+end
---- /dev/null
-+++ ruby-parslet/spec/parslet/transform/context_spec.rb
-@@ -0,0 +1,35 @@
-+require 'spec_helper'
-+
-+describe Parslet::Context do
-+  def context(*args)
-+    described_class.new(*args)
-+  end
-+  
-+  it "binds hash keys as variable like things" do
-+    context(:a => 'value').instance_eval { a }.
-+      should == 'value'
-+  end
-+  describe 'when a method in BlankSlate is inherited from the environment somehow' do
-+    before(:each) { BlankSlate.send(:define_method, :a) { 'c' } }
-+    after(:each) { BlankSlate.send(:undef_method, :a) }
-+    
-+    it "masks what is already on blank slate" do
-+      context(:a => 'b').instance_eval { a }.
-+        should == 'b'
-+    end  
-+  end
-+  it "should not reveal define_singleton_method for all users of blankslate, just for us" do
-+    expect {
-+      BlankSlate.new.instance_eval {
-+        define_singleton_method(:foo) { 'foo' }
-+      }
-+    }.to raise_error(NoMethodError)
-+  end 
-+  it "one contexts variables aren't the next ones" do
-+    ca = context(:a => 'b')
-+    cb = context(:b => 'c')
-+
-+    ca.methods.should_not include(:b)
-+    cb.methods.should_not include(:a)
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/parslet/transform_spec.rb
-@@ -0,0 +1,144 @@
-+require 'spec_helper'
-+
-+require 'parslet'
-+
-+describe Parslet::Transform do
-+  include Parslet
-+  
-+  let(:transform) { Parslet::Transform.new }
-+  attr_reader :transform
-+  before(:each) do
-+    @transform = Parslet::Transform.new
-+  end
-+  
-+  class A < Struct.new(:elt); end
-+  class B < Struct.new(:elt); end
-+  class C < Struct.new(:elt); end
-+  class Bi < Struct.new(:a, :b); end
-+
-+  describe "delayed construction" do
-+    context "given simple(:x) => A.new(x)" do
-+      before(:each) do
-+        transform.rule(simple(:x)) { |d| A.new(d[:x]) }
-+      end
-+
-+      it "should transform 'a' into A.new('a')" do
-+        transform.apply('a').should == A.new('a')
-+      end 
-+      it "should transform ['a', 'b'] into [A.new('a'), A.new('b')]" do
-+        transform.apply(['a', 'b']).should == 
-+          [A.new('a'), A.new('b')]
-+      end
-+    end
-+    context "given rules on {:a => simple(:x)} and {:b => :_x}" do
-+      before(:each) do
-+        transform.rule(:a => simple(:x)) { |d| A.new(d[:x]) }
-+        transform.rule(:b => simple(:x)) { |d| B.new(d[:x]) }
-+      end
-+
-+      it "should transform {:d=>{:b=>'c'}} into d => B('c')" do
-+        transform.apply({:d=>{:b=>'c'}}).should == {:d => B.new('c')}
-+      end
-+      it "should transform {:a=>{:b=>'c'}} into A(B('c'))" do
-+        transform.apply({:a=>{:b=>'c'}}).should == A.new(B.new('c'))
-+      end
-+    end
-+    describe "pulling out subbranches" do
-+      before(:each) do
-+        transform.rule(:a => {:b => simple(:x)}, :d => {:e => simple(:y)}) { |d|
-+          Bi.new(*d.values_at(:x, :y))
-+        }
-+      end
-+
-+      it "should yield Bi.new('c', 'f')" do
-+        transform.apply(:a => {:b => 'c'}, :d => {:e => 'f'}).should ==
-+          Bi.new('c', 'f')
-+      end 
-+    end
-+  end
-+  describe "dsl construction" do
-+    let(:transform) { Parslet::Transform.new do
-+        rule(simple(:x)) { A.new(x) }
-+      end 
-+    }
-+    
-+    it "should still evaluate rules correctly" do
-+      transform.apply('a').should == A.new('a')
-+    end 
-+  end
-+  describe "class construction" do
-+    class OptimusPrime < Parslet::Transform 
-+      rule(simple(:x)) { A.new(x) }
-+    end
-+    let(:transform) { OptimusPrime.new }
-+    
-+    it "should evaluate rules" do
-+      transform.apply('a').should == A.new('a')
-+    end 
-+  end
-+  describe "<- #call_on_match" do
-+    let(:bindings) { { :foo => 'test' } }
-+    context "when given a block of arity 1" do
-+      it "should call the block" do
-+        called = false
-+        transform.call_on_match(bindings, lambda do |dict|
-+          called = true
-+        end)
-+        
-+        called.should == true
-+      end 
-+      it "should yield the bindings" do
-+        transform.call_on_match(bindings, lambda do |dict|
-+          dict.should == bindings
-+        end)
-+      end
-+      it "should execute in the current context"  do
-+        foo = 'test'
-+        transform.call_on_match(bindings, lambda do |dict|
-+          foo.should == 'test'
-+        end)
-+      end
-+    end
-+    context "when given a block of arity 0" do
-+      it "should call the block" do
-+        called = false
-+        transform.call_on_match(bindings, proc do 
-+          called = true
-+        end)
-+        
-+        called.should == true
-+      end 
-+      it "should have bindings as local variables" do
-+        transform.call_on_match(bindings, proc do
-+          foo.should == 'test'
-+        end)
-+      end
-+      it "should execute in its own context" do
-+        @bar = 'test'
-+        transform.call_on_match(bindings, proc do
-+          @bar.should_not == 'test'
-+        end)
-+      end
-+    end
-+  end
-+  
-+  context "various transformations (regression)" do
-+    context "hashes" do
-+      it "are matched completely" do
-+        transform.rule(:a => simple(:x)) { fail }
-+        transform.apply(:a => 'a', :b => 'b')
-+      end 
-+    end
-+  end
-+  
-+  context "when not using the bindings as hash, but as local variables" do
-+    it "should access the variables" do
-+      transform.rule(simple(:x)) { A.new(x) }
-+      transform.apply('a').should == A.new('a')
-+    end
-+    it "should allow context as local variable" do
-+      transform.rule(simple(:x)) { foo }
-+      transform.apply('a', :foo => 'bar').should == 'bar'
-+    end
-+  end
-+end
-\ No newline at end of file
---- /dev/null
-+++ ruby-parslet/spec/spec_helper.rb
-@@ -0,0 +1,29 @@
-+
-+require 'parslet'
-+
-+require 'parslet/rig/rspec'
-+require 'parslet/atoms/visitor'
-+require 'parslet/export'
-+
-+RSpec.configure do |config|
-+  config.mock_with :flexmock
-+  
-+  # Exclude other ruby versions by giving :ruby => 1.8 or :ruby => 1.9
-+  #
-+  config.filter_run_excluding :ruby => lambda { |version|
-+    RUBY_VERSION.to_s !~ /^#{Regexp.escape(version.to_s)}/
-+  }
-+end
-+
-+def catch_failed_parse
-+  begin
-+    yield
-+  rescue Parslet::ParseFailed => exception
-+  end
-+  exception.cause
-+end
-+
-+def slet name, &block
-+  let(name, &block)
-+  subject(&block)
-+end
-\ No newline at end of file
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index b4fa6cb..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-0001-Import-rspec-gemspec-from-upstream-Git-repo.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-parslet.git



More information about the Pkg-ruby-extras-commits mailing list