shallot 0.1 → 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +10 -17
- data/README.rdoc +60 -13
- data/Rakefile +52 -0
- data/lib/shallot.rb +217 -171
- data/shallot.gemspec +58 -0
- data/test/helper.rb +19 -0
- data/test/test_shallot.rb +68 -0
- metadata +20 -15
- data/README.md +0 -79
data/.document
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
CHANGED
@@ -1,20 +1,13 @@
|
|
1
|
-
Copyright
|
1
|
+
Copyright 2011 Noble Samurai
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
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 <
|
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
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
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=
|
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.
|
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: &
|
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: *
|
24
|
+
version_requirements: *70242606199500
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|
27
|
-
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: *
|
35
|
+
version_requirements: *70242606199020
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: jeweler
|
38
|
-
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: *
|
46
|
+
version_requirements: *70242606198540
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rcov
|
49
|
-
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: *
|
58
|
-
description:
|
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
|
-
-
|
69
|
-
- lib/shallot.rb
|
69
|
+
- Gemfile
|
70
70
|
- LICENSE.txt
|
71
71
|
- README.rdoc
|
72
|
-
|
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:
|
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/.
|