shallot 0.1 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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/.
|