shallot 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "shoulda", ">= 0"
5
+ gem "bundler", "~> 1.0.0"
6
+ gem "jeweler", "~> 1.6.4"
7
+ gem "rcov", ">= 0"
8
+ end
data/LICENSE.txt CHANGED
@@ -1,20 +1,13 @@
1
- Copyright (c) 2011 Anneli Cuss
1
+ Copyright 2011 Noble Samurai
2
2
 
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
3
+ shallot is free software: you can redistribute it and/or modify it under the
4
+ terms of the GNU General Public License as published by the Free Software
5
+ Foundation, either version 3 of the License, or (at your option) any later
6
+ version.
10
7
 
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
8
+ shallot is distributed in the hope that it will be useful, but WITHOUT ANY
9
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
10
+ PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
11
 
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12
+ You should have received a copy of the GNU General Public License along with
13
+ shallot. If not, see http://www.gnu.org/licenses/.
data/README.rdoc CHANGED
@@ -1,19 +1,66 @@
1
1
  = shallot
2
2
 
3
- Description goes here.
4
-
5
- == Contributing to shallot
6
-
7
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
- * Fork the project
10
- * Start a feature/bugfix branch
11
- * Commit and push until you are happy with your contribution
12
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
3
+ shallot can lex and parse just enough Gherkin to give you:
4
+
5
+ {:feature=>"The name of the feature",
6
+ :background=>
7
+ [" Each step in the background",
8
+ " But without any additional parsing",
9
+ " Or validation"],
10
+ :scenarios=>
11
+ [{:name=>"And each scenario",
12
+ :outline=>false,
13
+ :tags=>["shallot", "regression", "bug"],
14
+ :contents=>
15
+ [" With tags, including those inherited",
16
+ " From the feature level tags"]},
17
+ {:name=>"As well as scenario outlines",
18
+ :outline=>true,
19
+ :tags=>["shallot", "feature"],
20
+ :contents=>
21
+ [" With support for the following",
22
+ " \"\"\"",
23
+ " long-quoted",
24
+ " sections",
25
+ " \"\"\"",
26
+ " While no extra <kind> for examples",
27
+ " Examples:",
28
+ " | kind |",
29
+ " | parsing |",
30
+ " | lexing |"]}]}
31
+
32
+ The above results from calling Shallot.parse(f), where f is an open File
33
+ handle on the following feature file:
34
+
35
+ @shallot
36
+ Feature: The name of the feature
37
+ This gets completely ignored.
38
+
39
+ Background:
40
+ Each step in the background
41
+ But without any additional parsing
42
+ Or validation
43
+
44
+ @regression @bug
45
+ Scenario: And each scenario
46
+ With tags, including those inherited
47
+ From the feature level tags
48
+
49
+ @feature
50
+ Scenario Outline: As well as scenario outlines
51
+ With support for the following
52
+ """
53
+ long-quoted
54
+ sections
55
+ """
56
+ While no extra <kind> for examples
57
+
58
+ Examples:
59
+ | kind |
60
+ | parsing |
61
+ | lexing |
14
62
 
15
63
  == Copyright
16
64
 
17
- Copyright (c) 2011 Anneli Cuss. See LICENSE.txt for
65
+ Copyright (c) 2011 Noble Samurai. See LICENSE.txt for
18
66
  further details.
19
-
data/Rakefile ADDED
@@ -0,0 +1,52 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ gem.name = "shallot"
17
+ gem.version = "0.2"
18
+ gem.homepage = "http://github.com/noblesamurai/shallot"
19
+ gem.license = "GPL-3"
20
+ gem.summary = %Q{a lexer/parser for Gherkin}
21
+ gem.description = %Q{shallot is a lexer/parser for Gherkin, the syntax used by Cucumber. It takes a .feature file and gives you something easy to work with.}
22
+ gem.email = "opensource@noblesamurai.com"
23
+ gem.authors = ["Anneli Cuss"]
24
+ end
25
+ Jeweler::RubygemsDotOrgTasks.new
26
+
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/test_*.rb'
31
+ test.verbose = true
32
+ end
33
+
34
+ require 'rcov/rcovtask'
35
+ Rcov::RcovTask.new do |test|
36
+ test.libs << 'test'
37
+ test.pattern = 'test/**/test_*.rb'
38
+ test.verbose = true
39
+ test.rcov_opts << '--exclude "gems/*"'
40
+ end
41
+
42
+ task :default => :test
43
+
44
+ require 'rdoc/task'
45
+ Rake::RDocTask.new do |rdoc|
46
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
47
+
48
+ rdoc.rdoc_dir = 'rdoc'
49
+ rdoc.title = "shallot #{version}"
50
+ rdoc.rdoc_files.include('README*')
51
+ rdoc.rdoc_files.include('lib/**/*.rb')
52
+ end
data/lib/shallot.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # shallot: a lexer/parser for Gherkin.
2
- # Copyright 2011 Noble Samurai.
3
- # Bugs to Anneli Cuss <celtic@sairyx.org>.
2
+ # Copyright 2011 Noble Samurai
3
+ # Bugs to Anneli Cuss <a@unnali.com>.
4
4
  #
5
5
  # shallot is free software: you can redistribute it and/or modify it under the
6
6
  # terms of the GNU General Public License as published by the Free Software
@@ -14,175 +14,221 @@
14
14
  # You should have received a copy of the GNU General Public License along with
15
15
  # shallot. If not, see http://www.gnu.org/licenses/.
16
16
 
17
+ # shallot exposes only one class; Shallot. A Shallot instance encompasses the
18
+ # state of the parsing operation, which can be advanced by feeding it lines of
19
+ # gherkin. That sounded weird. The Shallot class also exposes methods to wrap
20
+ # the instance, allowing you to quickly serve parsed feature files.
17
21
  class Shallot
18
- class Error < ::StandardError; end
19
-
20
- def self.parse f
21
- parser = new
22
- f.each_line {|l| parser.parse l}
23
- parser.eof
24
-
25
- {
26
- feature: parser.feature,
27
- background: parser.background,
28
- scenarios: parser.scenarios,
29
- }
30
- end
31
-
32
- def initialize
33
- @state = :opening
34
- @file_tags = []
35
- @scenario_tags = []
36
- @qqq = nil
37
- @scenario = nil
38
- @line = 0
39
-
40
- @background = []
41
- @scenarios = []
42
- @feature = nil
43
- end
44
-
45
- attr_reader :background, :scenarios, :feature
46
-
47
- def parse l
48
- # Check some conditions that should be (more or less) invariant across
49
- # a feature file.
50
- @line += 1
51
-
52
- if @qqq.nil? and %w{''' """}.include? l.strip
53
- # Start triple-quote.
54
- @qqq = l.strip
55
-
56
- elsif @qqq == l.strip
57
- # End triple-quote.
58
- @qqq = nil
59
-
60
- elsif @qqq.nil? and [nil, ?#].include? l.strip[0]
61
- # Blank or comment; outside triple-quote.
62
- return
63
- end
64
-
65
- # Use state.
66
-
67
- method = :"parse_#@state"
68
- raise Error, "no parser for #@state" unless respond_to? method
69
- send method, l
70
- end
71
-
72
- def eof
73
- method = :"eof_#@state"
74
- raise Error, "no eof handler for #@state" unless respond_to? method
75
- send method
76
- end
77
-
78
- protected
79
-
80
- def parse_opening l
81
- if tags = parse_tag_line(l)
82
- # Tags on beginning of file.
83
- @file_tags.concat tags
84
-
85
- elsif feature = parse_feature_start(l)
86
- # Start feature.
87
- @state = :feature
88
- @feature = feature
89
-
90
- else
91
- # There shouldn't be anything else in here.
92
- raise Error, "unexpected line before feature start"
93
- end
94
- end
95
-
96
- def parse_feature l
97
- if is_background_start? l
98
- # Start background.
99
- @state = :background
100
-
101
- raise Error, "tags before background" if @scenario_tags.length > 0
102
-
103
- elsif scenario = parse_scenario_start(l)
104
- # Start scenario (outline).
105
- start_scenario scenario
106
-
107
- elsif tags = parse_tag_line(l)
108
- # Tags; presumably before a scenario.
109
- @scenario_tags.concat tags
110
-
111
- else
112
- # Most likely part of the "As a .." prelude. Ignore.
113
- end
114
- end
115
-
116
- def parse_background l
117
- if @qqq.nil? and tags = parse_tag_line(l)
118
- # Tags; presumably before a scenario.
119
- @scenario_tags.concat tags
120
-
121
- elsif @qqq.nil? and scenario = parse_scenario_start(l)
122
- # Start scenario (outline).
123
- start_scenario scenario
124
-
125
- else
126
- # Any other step; part of the background.
127
- @background << l.gsub(/\n$/, "")
128
- end
129
- end
130
-
131
- def parse_scenario l
132
- if @qqq.nil? and tags = parse_tag_line(l)
133
- # Tags; presumably before a scenario.
134
- @scenario_tags.concat tags
135
-
136
- elsif @qqq.nil? and scenario = parse_scenario_start(l)
137
- # Start scenario (outline).
138
- start_scenario scenario
139
-
140
- else
141
- # Any other step; part of the scenario (outline).
142
- @scenario[:contents] << l.gsub(/\n$/, "")
143
- end
144
- end
145
-
146
- def eof_scenario
147
- @scenarios << @scenario
148
- end
149
-
150
- def start_scenario scenario
151
- @state = :scenario
152
- @scenarios << @scenario if @scenario
153
-
154
- @scenario = {
155
- name: scenario[:name],
156
- outline: scenario[:outline],
157
- tags: (@file_tags + @scenario_tags).uniq,
158
- contents: [],
159
- line: @line,
160
- }
161
-
162
- @scenario_tags = []
163
- end
164
-
165
- private
166
-
167
- def parse_tag_line l
168
- if (tags = l.strip.split).all? {|w| w[0] == ?@}
169
- tags.map {|t| t[1..-1].downcase}
170
- end
171
- end
172
-
173
- def parse_feature_start l
174
- $1.strip if l.strip =~ /^feature:(.*)$/i
175
- end
176
-
177
- def is_background_start? l
178
- l.strip.downcase == "background:"
179
- end
180
-
181
- def parse_scenario_start l
182
- if l.strip =~ /^scenario( outline)?:(.*)$/i
183
- {name: $2.strip, outline: !!$1}
184
- end
185
- end
22
+
23
+ # All errors from shallot are raised as a Shallot::Error. Details are in the
24
+ # message.
25
+ class Error < ::StandardError; end
26
+
27
+ # Parses +file+ in its entirety (by creating a new Shallot instance), and
28
+ # returns a hash with +:feature+, +:background+ and +:scenarios+ keys as for
29
+ # the Shallot instance object. +file+ only needs to implement +each_line+.
30
+ # If an error occurs, Shallot::Error will be thrown.
31
+ def self.parse file
32
+ parser = new
33
+ file.each_line {|line| parser.parse line}
34
+ parser.eof!
35
+
36
+ {
37
+ feature: parser.feature,
38
+ background: parser.background,
39
+ scenarios: parser.scenarios,
40
+ }
41
+ end
42
+
43
+ # Creates a fresh Shallot instance.
44
+ def initialize
45
+ @state = :opening
46
+ @file_tags = []
47
+ @scenario_tags = []
48
+ @qqq = nil
49
+ @scenario = nil
50
+ @line = 0
51
+
52
+ @background = []
53
+ @scenarios = []
54
+ @feature = nil
55
+ end
56
+
57
+ # The name of the feature, as specified on the "Feature:" line.
58
+ attr_reader :feature
59
+
60
+ # A list of strings; the lines comprising the Background steps.
61
+ attr_reader :background
62
+
63
+ # A list of hashes for each Scenario or Scenario Outline; the hash contains:
64
+ # * +:name+: the name as given on the "Scenario:" or "Scenario Outline:" line
65
+ # * +:outline+: +true+ if this is a Scenario Outline, +false+ if Scenario
66
+ # * +:tags+: the list of tags for this scenario (sans "@"), including
67
+ # feature-wide tags
68
+ # * +:contents+: the list of steps (one string per line), including all
69
+ # whitespace, tables, etc.
70
+ attr_reader :scenarios
71
+
72
+ # Parses the next line, +line+. Parse or internal errors may cause
73
+ # Shallot::Error to be thrown.
74
+ def parse line
75
+ # Check some conditions that should be (more or less) invariant across
76
+ # a feature file.
77
+ @line += 1
78
+
79
+ if @qqq.nil? and %w{''' """}.include? line.strip
80
+ # Start triple-quote.
81
+ @qqq = line.strip
82
+
83
+ elsif @qqq == line.strip
84
+ # End triple-quote.
85
+ @qqq = nil
86
+
87
+ elsif @qqq.nil? and [nil, ?#].include? line.strip[0]
88
+ # Blank or comment; outside triple-quote.
89
+ return
90
+ end
91
+
92
+ # Use state.
93
+
94
+ method = :"parse_#@state"
95
+ raise Error, "no parser for #@state" unless respond_to? method
96
+ send method, line
97
+ end
98
+
99
+ # Signals to the parser that the end of the file has been reached. This may
100
+ # throw Shallot::Error if EOF wasn't expected in its current state.
101
+ def eof!
102
+ method = :"eof_#@state"
103
+ raise Error, "no eof handler for #@state" unless respond_to? method
104
+ send method
105
+ end
106
+
107
+ protected
108
+
109
+ # Parses +line+ before we've seen the opening "Feature:" line.
110
+ def parse_opening line
111
+ if tags = parse_tag_line(line)
112
+ # Tags on beginning of file.
113
+ @file_tags.concat tags
114
+
115
+ elsif feature = parse_feature_start(line)
116
+ # Start feature.
117
+ @state = :feature
118
+ @feature = feature
119
+
120
+ else
121
+ # There shouldn't be anything else in here.
122
+ raise Error, "unexpected line before feature start"
123
+ end
124
+ end
125
+
126
+ # Parses +line+ after we've seen "Feature:", but before the Background or any
127
+ # scenario (outline).
128
+ def parse_feature line
129
+ if is_background_start? line
130
+ # Start background.
131
+ @state = :background
132
+
133
+ raise Error, "tags before background" if @scenario_tags.length > 0
134
+
135
+ elsif scenario = parse_scenario_start(line)
136
+ # Start scenario (outline).
137
+ start_scenario scenario
138
+
139
+ elsif tags = parse_tag_line(line)
140
+ # Tags; presumably before a scenario.
141
+ @scenario_tags.concat tags
142
+
143
+ else
144
+ # Most likely part of the "As a .." prelude. Ignore.
145
+ end
146
+ end
147
+
148
+ # Parses +line+ after we've seen "Background:", but before any scenario.
149
+ def parse_background line
150
+ if @qqq.nil? and tags = parse_tag_line(line)
151
+ # Tags; presumably before a scenario.
152
+ @scenario_tags.concat tags
153
+
154
+ elsif @qqq.nil? and scenario = parse_scenario_start(line)
155
+ # Start scenario (outline).
156
+ start_scenario scenario
157
+
158
+ else
159
+ # Any other step; part of the background.
160
+ @background << line.gsub(/\n$/, "")
161
+ end
162
+ end
163
+
164
+ # Parses +line+ after we've seen "Scenario:" or "Scenario Outline:".
165
+ def parse_scenario line
166
+ if @qqq.nil? and tags = parse_tag_line(line)
167
+ # Tags; presumably before a scenario.
168
+ @scenario_tags.concat tags
169
+
170
+ elsif @qqq.nil? and scenario = parse_scenario_start(line)
171
+ # Start scenario (outline).
172
+ start_scenario scenario
173
+
174
+ else
175
+ # Any other step; part of the scenario (outline).
176
+ @scenario[:contents] << line.gsub(/\n$/, "")
177
+ end
178
+ end
179
+
180
+ # Handles EOF after having seen "Scenario:" or "Scenario Outline:".
181
+ def eof_scenario
182
+ @scenarios << @scenario
183
+ end
184
+
185
+ # Moves to the scenario parsing state with the ad-hoc information in
186
+ # +scenario+ from +parse_scenario_start+.
187
+ def start_scenario scenario
188
+ @state = :scenario
189
+ @scenarios << @scenario if @scenario
190
+
191
+ @scenario = {
192
+ name: scenario[:name],
193
+ outline: scenario[:outline],
194
+ tags: (@file_tags + @scenario_tags).uniq,
195
+ contents: [],
196
+ line: @line,
197
+ }
198
+
199
+ @scenario_tags = []
200
+ end
201
+
202
+ private
203
+
204
+ # Parses a line of tags, +line+, returning a list of downcased tags sans "@".
205
+ # Returns +nil+ if the line didn't contain only tags (and at least one).
206
+ def parse_tag_line line
207
+ if (tags = line.strip.split).all? {|w| w[0] == ?@}
208
+ tags.map {|t| t[1..-1].downcase}
209
+ end
210
+ end
211
+
212
+ # Parses a "Feature:" line, +line+, returning the title on the line, or +nil+
213
+ # if it wasn't a feature line at all.
214
+ def parse_feature_start line
215
+ $1.strip if line.strip =~ /^feature:(.*)$/i
216
+ end
217
+
218
+ # Returns +true+ if +line+ is a "Background:" line.
219
+ def is_background_start? line
220
+ line.strip.downcase == "background:"
221
+ end
222
+
223
+ # Parses a scenario (outline) starting line, +line+, returning a hash with
224
+ # +:name+ containing the title given on the line, and +:outline+ with +true+
225
+ # if it was "Scenario Outline:", and +false+ if "Scenario:". If it wasn't a
226
+ # scenario starting line, returns +nil+.
227
+ def parse_scenario_start line
228
+ if line.strip =~ /^scenario( outline)?:(.*)$/i
229
+ {name: $2.strip, outline: !!$1}
230
+ end
231
+ end
186
232
  end
187
233
 
188
- # vim: set sw=4 ts=4 noet cc=80:
234
+ # vim: set sw=2 ts=2 et cc=80:
data/shallot.gemspec ADDED
@@ -0,0 +1,58 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "shallot"
8
+ s.version = "0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Anneli Cuss"]
12
+ s.date = "2011-12-21"
13
+ s.description = "shallot is a lexer/parser for Gherkin, the syntax used by Cucumber. It takes a .feature file and gives you something easy to work with."
14
+ s.email = "opensource@noblesamurai.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "COPYING",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "lib/shallot.rb",
27
+ "shallot.gemspec",
28
+ "test/helper.rb",
29
+ "test/test_shallot.rb"
30
+ ]
31
+ s.homepage = "http://github.com/noblesamurai/shallot"
32
+ s.licenses = ["GPL-3"]
33
+ s.require_paths = ["lib"]
34
+ s.rubygems_version = "1.8.10"
35
+ s.summary = "a lexer/parser for Gherkin"
36
+
37
+ if s.respond_to? :specification_version then
38
+ s.specification_version = 3
39
+
40
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
41
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
42
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
43
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
44
+ s.add_development_dependency(%q<rcov>, [">= 0"])
45
+ else
46
+ s.add_dependency(%q<shoulda>, [">= 0"])
47
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
48
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
49
+ s.add_dependency(%q<rcov>, [">= 0"])
50
+ end
51
+ else
52
+ s.add_dependency(%q<shoulda>, [">= 0"])
53
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
54
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
55
+ s.add_dependency(%q<rcov>, [">= 0"])
56
+ end
57
+ end
58
+
data/test/helper.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'shallot'
16
+
17
+ class Test::Unit::TestCase
18
+ end
19
+
@@ -0,0 +1,68 @@
1
+ require 'helper'
2
+
3
+ class TestShallot < Test::Unit::TestCase
4
+ should "parse a feature with all the trimmings correctly" do
5
+ assert_equal Shallot.parse($feature), $parsed
6
+ end
7
+ end
8
+
9
+ $feature = <<FEATURE
10
+ @shallot
11
+ Feature: The name of the feature
12
+ This gets completely ignored.
13
+
14
+ Background:
15
+ Each step in the background
16
+ But without any additional parsing
17
+ Or validation
18
+
19
+ @regression @bug
20
+ Scenario: And each scenario
21
+ With tags, including those inherited
22
+ From the feature level tags
23
+
24
+ @feature
25
+ Scenario Outline: As well as scenario outlines
26
+ With support for the following
27
+ """
28
+ long-quoted
29
+ sections
30
+ """
31
+ While no extra <kind> for examples
32
+
33
+ Examples:
34
+ | kind |
35
+ | parsing |
36
+ | lexing |
37
+ FEATURE
38
+
39
+ $parsed =
40
+ {:feature=>"The name of the feature",
41
+ :background=>
42
+ [" Each step in the background",
43
+ " But without any additional parsing",
44
+ " Or validation"],
45
+ :scenarios=>
46
+ [{:name=>"And each scenario",
47
+ :outline=>false,
48
+ :tags=>["shallot", "regression", "bug"],
49
+ :contents=>
50
+ [" With tags, including those inherited",
51
+ " From the feature level tags"],
52
+ :line=>11},
53
+ {:name=>"As well as scenario outlines",
54
+ :outline=>true,
55
+ :tags=>["shallot", "feature"],
56
+ :contents=>
57
+ [" With support for the following",
58
+ " \"\"\"",
59
+ " long-quoted",
60
+ " sections",
61
+ " \"\"\"",
62
+ " While no extra <kind> for examples",
63
+ " Examples:",
64
+ " | kind |",
65
+ " | parsing |",
66
+ " | lexing |"],
67
+ :line=>16}]}
68
+ # vim: set sw=2 ts=8 et cc=80:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shallot
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-12-21 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: shoulda
16
- requirement: &70169654535800 !ruby/object:Gem::Requirement
16
+ requirement: &70242606199500 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70169654535800
24
+ version_requirements: *70242606199500
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70169654535200 !ruby/object:Gem::Requirement
27
+ requirement: &70242606199020 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70169654535200
35
+ version_requirements: *70242606199020
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &70169654534480 !ruby/object:Gem::Requirement
38
+ requirement: &70242606198540 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.6.4
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70169654534480
46
+ version_requirements: *70242606198540
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rcov
49
- requirement: &70169654533960 !ruby/object:Gem::Requirement
49
+ requirement: &70242606198060 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,22 +54,27 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70169654533960
58
- description: Takes a .feature file, gives you something easy to work with.
57
+ version_requirements: *70242606198060
58
+ description: shallot is a lexer/parser for Gherkin, the syntax used by Cucumber. It
59
+ takes a .feature file and gives you something easy to work with.
59
60
  email: opensource@noblesamurai.com
60
61
  executables: []
61
62
  extensions: []
62
63
  extra_rdoc_files:
63
64
  - LICENSE.txt
64
- - README.md
65
65
  - README.rdoc
66
66
  files:
67
+ - .document
67
68
  - COPYING
68
- - README.md
69
- - lib/shallot.rb
69
+ - Gemfile
70
70
  - LICENSE.txt
71
71
  - README.rdoc
72
- homepage: http://github.com/anneli/shallot
72
+ - Rakefile
73
+ - lib/shallot.rb
74
+ - shallot.gemspec
75
+ - test/helper.rb
76
+ - test/test_shallot.rb
77
+ homepage: http://github.com/noblesamurai/shallot
73
78
  licenses:
74
79
  - GPL-3
75
80
  post_install_message:
@@ -84,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
84
89
  version: '0'
85
90
  segments:
86
91
  - 0
87
- hash: 2371435404367762663
92
+ hash: 2093830947511408019
88
93
  required_rubygems_version: !ruby/object:Gem::Requirement
89
94
  none: false
90
95
  requirements:
data/README.md DELETED
@@ -1,79 +0,0 @@
1
- # shallot
2
- #### <span style="color: #333">a lexer/parser for Gherkin</span>
3
-
4
- ## introduction
5
-
6
- shallot can lex and parse just enough Gherkin to give you:
7
-
8
- {:feature=>"The name of the feature",
9
- :background=>
10
- ["\t\tEach step in the background",
11
- "\t\tBut without any additional parsing",
12
- "\t\tOr validation"],
13
- :scenarios=>
14
- [{:name=>"And each scenario",
15
- :outline=>false,
16
- :tags=>["shallot", "regression", "bug"],
17
- :contents=>
18
- ["\t\tWith tags, including those inherited",
19
- "\t\tFrom the feature level tags"]},
20
- {:name=>"As well as scenario outlines",
21
- :outline=>true,
22
- :tags=>["shallot", "feature"],
23
- :contents=>
24
- ["\t\tWith support for the following",
25
- "\t\t\t\"\"\"",
26
- "\t\t\tlong-quoted",
27
- "\t\t\tsections",
28
- "\t\t\t\"\"\"",
29
- "\t\tWhile no extra <kind> for examples",
30
- "\t\tExamples:",
31
- "\t\t\t| kind |",
32
- "\t\t\t| parsing |",
33
- "\t\t\t| lexing |"]}]}
34
-
35
- The above results from calling Shallot.parse(f), where f is an open File
36
- handle on the following feature file:
37
-
38
- @shallot
39
- Feature: The name of the feature
40
- This gets completely ignored.
41
-
42
- Background:
43
- Each step in the background
44
- But without any additional parsing
45
- Or validation
46
-
47
- @regression @bug
48
- Scenario: And each scenario
49
- With tags, including those inherited
50
- From the feature level tags
51
-
52
- @feature
53
- Scenario Outline: As well as scenario outlines
54
- With support for the following
55
- """
56
- long-quoted
57
- sections
58
- """
59
- While no extra <kind> for examples
60
-
61
- Examples:
62
- | kind |
63
- | parsing |
64
- | lexing |
65
-
66
- ## contributors
67
-
68
- - [Anneli Cuss](http://github.com/celtic) with [Noble Samurai](http://github.com/noblesamurai)
69
- - You?
70
-
71
- ## license
72
-
73
- Copyright 2011 Noble Samurai
74
-
75
- shallot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
76
-
77
- shallot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
78
-
79
- You should have received a copy of the GNU General Public License along with shallot. If not, see http://www.gnu.org/licenses/.