gherkin-ruby 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,359 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.4.7
4
+ # from Racc grammer file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+ require_relative "lexer"
10
+ require_relative "../ast"
11
+
12
+ module Gherkin
13
+ class Parser < Racc::Parser
14
+
15
+ module_eval(<<'...end gherkin.y/module_eval...', 'gherkin.y', 97)
16
+
17
+ def parse(input)
18
+ scan_str(input)
19
+ end
20
+ ...end gherkin.y/module_eval...
21
+ ##### State transition tables begin ###
22
+
23
+ racc_action_table = [
24
+ 14, 3, 14, 15, 14, 26, 14, 11, 13, 3,
25
+ 38, 31, 32, 33, 34, 35, 14, 14, 11, 13,
26
+ 41, 31, 32, 33, 34, 35, 31, 32, 33, 34,
27
+ 35, 31, 32, 33, 34, 35, 31, 32, 33, 34,
28
+ 35, 3, 3, 7, 11, 13, 31, 32, 33, 34,
29
+ 35, 3, 3, 3, 18, 3, 44, 14, 45, 20,
30
+ 21, 48, 3, 14, 3, 14, 27, 3, 14, 14,
31
+ 8, 24 ]
32
+
33
+ racc_action_check = [
34
+ 19, 12, 4, 4, 22, 12, 51, 22, 22, 38,
35
+ 19, 51, 51, 51, 51, 51, 40, 25, 2, 2,
36
+ 25, 40, 40, 40, 40, 40, 47, 47, 47, 47,
37
+ 47, 52, 52, 52, 52, 52, 17, 17, 17, 17,
38
+ 17, 9, 0, 0, 9, 9, 28, 28, 28, 28,
39
+ 28, 6, 24, 18, 5, 29, 30, 36, 37, 7,
40
+ 8, 41, 42, 43, 45, 46, 15, 48, 49, 50,
41
+ 1, 11 ]
42
+
43
+ racc_action_pointer = [
44
+ 40, 70, 13, nil, 0, 50, 49, 47, 60, 39,
45
+ nil, 59, -1, nil, nil, 54, nil, 29, 51, -2,
46
+ nil, nil, 2, nil, 50, 15, nil, nil, 39, 53,
47
+ 44, nil, nil, nil, nil, nil, 55, 46, 7, nil,
48
+ 14, 49, 60, 61, nil, 62, 63, 19, 65, 66,
49
+ 67, 4, 24 ]
50
+
51
+ racc_action_default = [
52
+ -31, -31, -1, -3, -31, -5, -7, -31, -31, -2,
53
+ -24, -31, -31, -29, -4, -31, -6, -31, -31, -8,
54
+ -10, 53, -31, -25, -31, -31, -30, -11, -14, -31,
55
+ -31, -19, -20, -21, -22, -23, -15, -9, -31, -26,
56
+ -31, -31, -31, -16, -18, -31, -12, -27, -31, -17,
57
+ -13, -31, -28 ]
58
+
59
+ racc_goto_table = [
60
+ 4, 10, 28, 42, 6, 16, 19, 5, 23, 22,
61
+ 37, 17, 25, 9, 2, 1, nil, nil, 36, nil,
62
+ nil, 39, 42, nil, 40, 47, nil, 42, nil, 43,
63
+ nil, nil, nil, nil, nil, nil, 52, nil, 46, nil,
64
+ nil, nil, 49, nil, nil, 50, nil, nil, 51 ]
65
+
66
+ racc_goto_check = [
67
+ 4, 13, 10, 11, 7, 6, 4, 5, 13, 4,
68
+ 8, 9, 4, 3, 2, 1, nil, nil, 4, nil,
69
+ nil, 13, 11, nil, 4, 10, nil, 11, nil, 4,
70
+ nil, nil, nil, nil, nil, nil, 10, nil, 4, nil,
71
+ nil, nil, 4, nil, nil, 4, nil, nil, 4 ]
72
+
73
+ racc_goto_pointer = [
74
+ nil, 15, 14, 11, 0, 7, 0, 4, -9, 6,
75
+ -15, -25, nil, -1, nil ]
76
+
77
+ racc_goto_default = [
78
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
79
+ nil, 29, 30, nil, 12 ]
80
+
81
+ racc_reduce_table = [
82
+ 0, 0, :racc_error,
83
+ 1, 14, :_reduce_1,
84
+ 2, 14, :_reduce_2,
85
+ 1, 17, :_reduce_none,
86
+ 2, 17, :_reduce_none,
87
+ 1, 15, :_reduce_5,
88
+ 2, 15, :_reduce_6,
89
+ 1, 18, :_reduce_7,
90
+ 2, 18, :_reduce_8,
91
+ 3, 18, :_reduce_9,
92
+ 2, 20, :_reduce_10,
93
+ 3, 20, :_reduce_11,
94
+ 2, 21, :_reduce_none,
95
+ 3, 21, :_reduce_none,
96
+ 2, 19, :_reduce_14,
97
+ 2, 22, :_reduce_15,
98
+ 2, 23, :_reduce_16,
99
+ 3, 23, :_reduce_17,
100
+ 2, 24, :_reduce_18,
101
+ 1, 25, :_reduce_none,
102
+ 1, 25, :_reduce_none,
103
+ 1, 25, :_reduce_none,
104
+ 1, 25, :_reduce_none,
105
+ 1, 25, :_reduce_none,
106
+ 1, 16, :_reduce_24,
107
+ 2, 16, :_reduce_25,
108
+ 3, 16, :_reduce_26,
109
+ 4, 26, :_reduce_27,
110
+ 6, 26, :_reduce_28,
111
+ 1, 27, :_reduce_29,
112
+ 2, 27, :_reduce_30 ]
113
+
114
+ racc_reduce_n = 31
115
+
116
+ racc_shift_n = 53
117
+
118
+ racc_token_table = {
119
+ false => 0,
120
+ :error => 1,
121
+ :NEWLINE => 2,
122
+ :FEATURE => 3,
123
+ :BACKGROUND => 4,
124
+ :SCENARIO => 5,
125
+ :TAG => 6,
126
+ :GIVEN => 7,
127
+ :WHEN => 8,
128
+ :THEN => 9,
129
+ :AND => 10,
130
+ :BUT => 11,
131
+ :TEXT => 12 }
132
+
133
+ racc_nt_base = 13
134
+
135
+ racc_use_result_var = true
136
+
137
+ Racc_arg = [
138
+ racc_action_table,
139
+ racc_action_check,
140
+ racc_action_default,
141
+ racc_action_pointer,
142
+ racc_goto_table,
143
+ racc_goto_check,
144
+ racc_goto_default,
145
+ racc_goto_pointer,
146
+ racc_nt_base,
147
+ racc_reduce_table,
148
+ racc_token_table,
149
+ racc_shift_n,
150
+ racc_reduce_n,
151
+ racc_use_result_var ]
152
+
153
+ Racc_token_to_s_table = [
154
+ "$end",
155
+ "error",
156
+ "NEWLINE",
157
+ "FEATURE",
158
+ "BACKGROUND",
159
+ "SCENARIO",
160
+ "TAG",
161
+ "GIVEN",
162
+ "WHEN",
163
+ "THEN",
164
+ "AND",
165
+ "BUT",
166
+ "TEXT",
167
+ "$start",
168
+ "Root",
169
+ "Feature",
170
+ "Scenarios",
171
+ "Newline",
172
+ "FeatureHeader",
173
+ "Background",
174
+ "FeatureName",
175
+ "Description",
176
+ "BackgroundHeader",
177
+ "Steps",
178
+ "Step",
179
+ "Keyword",
180
+ "Scenario",
181
+ "Tags" ]
182
+
183
+ Racc_debug_parser = false
184
+
185
+ ##### State transition tables end #####
186
+
187
+ # reduce 0 omitted
188
+
189
+ module_eval(<<'.,.,', 'gherkin.y', 14)
190
+ def _reduce_1(val, _values, result)
191
+ result = val[0];
192
+ result
193
+ end
194
+ .,.,
195
+
196
+ module_eval(<<'.,.,', 'gherkin.y', 17)
197
+ def _reduce_2(val, _values, result)
198
+ result = val[0]; result.scenarios = val[1]
199
+ result
200
+ end
201
+ .,.,
202
+
203
+ # reduce 3 omitted
204
+
205
+ # reduce 4 omitted
206
+
207
+ module_eval(<<'.,.,', 'gherkin.y', 26)
208
+ def _reduce_5(val, _values, result)
209
+ result = val[0]
210
+ result
211
+ end
212
+ .,.,
213
+
214
+ module_eval(<<'.,.,', 'gherkin.y', 28)
215
+ def _reduce_6(val, _values, result)
216
+ result = val[0]; result.background = val[1]
217
+ result
218
+ end
219
+ .,.,
220
+
221
+ module_eval(<<'.,.,', 'gherkin.y', 32)
222
+ def _reduce_7(val, _values, result)
223
+ result = val[0]
224
+ result
225
+ end
226
+ .,.,
227
+
228
+ module_eval(<<'.,.,', 'gherkin.y', 33)
229
+ def _reduce_8(val, _values, result)
230
+ result = val[0]
231
+ result
232
+ end
233
+ .,.,
234
+
235
+ module_eval(<<'.,.,', 'gherkin.y', 35)
236
+ def _reduce_9(val, _values, result)
237
+ result = val[0]
238
+ result
239
+ end
240
+ .,.,
241
+
242
+ module_eval(<<'.,.,', 'gherkin.y', 39)
243
+ def _reduce_10(val, _values, result)
244
+ result = AST::Feature.new(val[1]); result.pos(filename, lineno)
245
+ result
246
+ end
247
+ .,.,
248
+
249
+ module_eval(<<'.,.,', 'gherkin.y', 40)
250
+ def _reduce_11(val, _values, result)
251
+ result = AST::Feature.new(val[2]); result.pos(filename, lineno)
252
+ result
253
+ end
254
+ .,.,
255
+
256
+ # reduce 12 omitted
257
+
258
+ # reduce 13 omitted
259
+
260
+ module_eval(<<'.,.,', 'gherkin.y', 50)
261
+ def _reduce_14(val, _values, result)
262
+ result = val[0]; result.steps = val[1]
263
+ result
264
+ end
265
+ .,.,
266
+
267
+ module_eval(<<'.,.,', 'gherkin.y', 54)
268
+ def _reduce_15(val, _values, result)
269
+ result = AST::Background.new; result.pos(filename, lineno)
270
+ result
271
+ end
272
+ .,.,
273
+
274
+ module_eval(<<'.,.,', 'gherkin.y', 58)
275
+ def _reduce_16(val, _values, result)
276
+ result = [val[0]]
277
+ result
278
+ end
279
+ .,.,
280
+
281
+ module_eval(<<'.,.,', 'gherkin.y', 59)
282
+ def _reduce_17(val, _values, result)
283
+ result = val[0] << val[1]
284
+ result
285
+ end
286
+ .,.,
287
+
288
+ module_eval(<<'.,.,', 'gherkin.y', 63)
289
+ def _reduce_18(val, _values, result)
290
+ result = AST::Step.new(val[1], val[0]); result.pos(filename, lineno)
291
+ result
292
+ end
293
+ .,.,
294
+
295
+ # reduce 19 omitted
296
+
297
+ # reduce 20 omitted
298
+
299
+ # reduce 21 omitted
300
+
301
+ # reduce 22 omitted
302
+
303
+ # reduce 23 omitted
304
+
305
+ module_eval(<<'.,.,', 'gherkin.y', 71)
306
+ def _reduce_24(val, _values, result)
307
+ result = [val[0]]
308
+ result
309
+ end
310
+ .,.,
311
+
312
+ module_eval(<<'.,.,', 'gherkin.y', 72)
313
+ def _reduce_25(val, _values, result)
314
+ result = val[0] << val[1]
315
+ result
316
+ end
317
+ .,.,
318
+
319
+ module_eval(<<'.,.,', 'gherkin.y', 73)
320
+ def _reduce_26(val, _values, result)
321
+ result = val[0] << val[2]
322
+ result
323
+ end
324
+ .,.,
325
+
326
+ module_eval(<<'.,.,', 'gherkin.y', 78)
327
+ def _reduce_27(val, _values, result)
328
+ result = AST::Scenario.new(val[1], val[3]); result.pos(filename, lineno - 1)
329
+ result
330
+ end
331
+ .,.,
332
+
333
+ module_eval(<<'.,.,', 'gherkin.y', 81)
334
+ def _reduce_28(val, _values, result)
335
+ result = AST::Scenario.new(val[3], val[5], val[0]); result.pos(filename, lineno - 2)
336
+ result
337
+ end
338
+ .,.,
339
+
340
+ module_eval(<<'.,.,', 'gherkin.y', 85)
341
+ def _reduce_29(val, _values, result)
342
+ result = [AST::Tag.new(val[0])]
343
+ result
344
+ end
345
+ .,.,
346
+
347
+ module_eval(<<'.,.,', 'gherkin.y', 86)
348
+ def _reduce_30(val, _values, result)
349
+ result = val[0] << AST::Tag.new(val[1])
350
+ result
351
+ end
352
+ .,.,
353
+
354
+ def _reduce_none(val, _values, result)
355
+ val[0]
356
+ end
357
+
358
+ end # class Parser
359
+ end # module Gherkin
@@ -1,43 +1 @@
1
- require 'parslet'
2
-
3
- module Gherkin
4
- class Parser < Parslet::Parser
5
- def indent(num=2)
6
- str(' ' * num)
7
- end
8
-
9
- rule(:space) { match('\s').repeat }
10
- rule(:space?) { space.maybe }
11
- rule(:newline) { match('\n').repeat }
12
- rule(:text) { match('[^\n]').repeat }
13
- rule(:identifier) { match('\w').repeat }
14
-
15
- rule(:feature_line) { str('Feature:') >> space? >> text.as(:name) }
16
- rule(:scenario_line) { indent(2) >> str('Scenario:') >> space? >> text.as(:name) }
17
-
18
- rule(:step_keyword) { str('Given') | str('When') | str('Then') | str('And') | str('But') }
19
-
20
- rule(:comment) { str('#') >> text.as(:comment) }
21
-
22
- rule(:description_text) { (str('Background:') | str('Scenario:') | str('@')).absent? >> text }
23
- rule(:description) { (indent(2) >> description_text >> newline).repeat }
24
-
25
- rule(:background_line) { indent(2) >> str('Background:') }
26
-
27
- rule(:step) { indent(4) >> step_keyword.as(:keyword) >> space? >> text.as(:name) }
28
- rule(:steps) { (step.as(:step) >> newline.maybe).repeat }
29
-
30
- rule(:tags) { indent(2) >> (str('@') >> identifier.as(:tag) >> str(' ').maybe).repeat(1) }
31
-
32
- rule(:scenario) { (tags.as(:tags) >> newline).maybe >> scenario_line >> newline >> steps.as(:steps) }
33
- rule(:scenarios) { (scenario.as(:scenario) >> newline.maybe).repeat }
34
-
35
- rule(:background) { background_line >> newline >> steps.as(:steps) }
36
-
37
- rule(:feature) { feature_line >> newline >> description >> background.as(:background).maybe >> scenarios.as(:scenarios) }
38
-
39
- rule(:main) { feature.as(:feature) }
40
-
41
- root :main
42
- end
43
- end
1
+ require_relative 'parser/parser'
@@ -1,3 +1,3 @@
1
1
  module Gherkin
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/gherkin.rb CHANGED
@@ -1,15 +1,10 @@
1
- require 'parslet'
2
1
  require_relative "gherkin/version"
3
2
  require_relative 'gherkin/ast'
4
3
  require_relative 'gherkin/parser'
5
- require_relative 'gherkin/transform'
6
4
 
7
5
  module Gherkin
8
6
  def self.parse(input)
9
- parser = Parser.new
10
- transform = Transform.new
11
-
12
- parsed = parser.parse input
13
- transform.apply(parsed)
7
+ parser = Parser.new
8
+ parser.parse(input)
14
9
  end
15
10
  end
@@ -32,51 +32,42 @@ module Gherkin
32
32
  node.ancestors.must_include Node
33
33
  end
34
34
 
35
- it 'has a line and column' do
36
- name = OpenStruct.new(line_and_column: [2, 13])
37
- def name.to_s; 'Name'; end
38
-
39
- instance = node.new(name)
35
+ it 'has a line' do
36
+ instance = node.new("Name")
40
37
  instance.name.must_equal 'Name'
41
- instance.line.must_equal 2
42
- instance.column.must_equal 13
38
+ instance.must_respond_to :line
43
39
  end
44
40
  end
45
41
  end
46
42
 
47
43
  describe Feature do
48
44
  it 'is Enumerable' do
49
- name = OpenStruct.new(line_and_column: [2, 13])
50
- def name.to_s; 'Name'; end
51
-
52
45
  background = ['foo', 'bar']
53
46
  elements = ['+foo', '+bar']
54
47
 
55
- instance = Feature.new(name, elements, background )
48
+ instance = Feature.new("My feature", elements, background )
56
49
  instance.background.each.to_a.must_equal ['foo', 'bar']
57
50
  instance.each.to_a.must_equal ['+foo', '+bar']
58
51
  end
59
52
  end
60
53
 
61
54
  describe Scenario do
62
- it 'is Enumerable' do
63
- name = OpenStruct.new(line_and_column: [2, 13])
64
- def name.to_s; 'Name'; end
65
-
66
- elements = ['foo', 'bar']
55
+ let(:steps) do
56
+ steps = [
57
+ OpenStruct.new(line: 4),
58
+ OpenStruct.new(line: 5),
59
+ ]
60
+ end
67
61
 
68
- instance = Scenario.new(name, elements)
69
- instance.each.to_a.must_equal ['foo', 'bar']
62
+ it 'is Enumerable' do
63
+ instance = Scenario.new("Name", steps)
64
+ instance.each.to_a.must_equal steps
70
65
  end
71
66
 
72
67
  it 'has tags' do
73
- name = OpenStruct.new(line_and_column: [2, 13])
74
- def name.to_s; 'Name'; end
75
-
76
- steps = ['foo', 'bar']
77
68
  tags = ['javascript', 'wip']
78
69
 
79
- instance = Scenario.new(name, steps, tags)
70
+ instance = Scenario.new("Name", steps, tags)
80
71
  instance.tags.must_equal tags
81
72
  end
82
73
  end
@@ -99,10 +90,10 @@ module Gherkin
99
90
  end
100
91
 
101
92
  describe 'when there are background steps' do
102
- it 'records line and column' do
93
+ it 'records line' do
103
94
  instance = Background.new(steps)
95
+ instance.pos("file", 3)
104
96
  instance.line.must_equal 3
105
- instance.column.must_equal 3
106
97
  end
107
98
  end
108
99
 
@@ -110,7 +101,6 @@ module Gherkin
110
101
  it 'does not' do
111
102
  instance = Background.new([])
112
103
  instance.line.must_equal nil
113
- instance.column.must_equal nil
114
104
  end
115
105
  end
116
106
  end
@@ -120,15 +110,12 @@ module Gherkin
120
110
  Step.ancestors.must_include Node
121
111
  end
122
112
 
123
- it 'has a line and column' do
124
- name = OpenStruct.new(line_and_column: [2, 13])
125
- def name.to_s; 'Name'; end
126
-
127
- instance = Step.new(name, 'Given')
113
+ it 'has a line' do
114
+ instance = Step.new("Name", 'Given')
115
+ instance.pos("file", 2)
128
116
  instance.name.must_equal 'Name'
129
117
  instance.keyword.must_equal 'Given'
130
118
  instance.line.must_equal 2
131
- instance.column.must_equal 13
132
119
  end
133
120
  end
134
121
  end
@@ -0,0 +1,43 @@
1
+ require 'test_helper'
2
+
3
+ module Gherkin
4
+ describe Parser do
5
+ let(:lexer) { Parser.new }
6
+
7
+ it 'ignores commments' do
8
+ lexer.tokenize("# this is a comment").must_equal []
9
+ end
10
+
11
+ it 'parses newlines' do
12
+ lexer.tokenize("\n\n").must_equal [[:NEWLINE, "\n"], [:NEWLINE, "\n"]]
13
+ end
14
+
15
+ it 'parses text and strips it' do
16
+ lexer.tokenize(" Arbitrary text ").must_equal [[:TEXT, "Arbitrary text"]]
17
+ end
18
+
19
+ it 'parses tags' do
20
+ lexer.tokenize("@javascript @wip").must_equal [
21
+ [:TAG, "javascript"],
22
+ [:TAG, "wip"],
23
+ ]
24
+ end
25
+
26
+ describe 'Keywords' do
27
+ %w(Feature: Background: Scenario:).each do |keyword|
28
+ it "parses #{keyword}:" do
29
+ name = keyword[0..-2]
30
+ lexer.tokenize(keyword).must_equal [[name.upcase.to_sym, name]]
31
+ end
32
+ end
33
+ end
34
+
35
+ describe 'Step keywords' do
36
+ %w(Given When Then And But).each do |keyword|
37
+ it "parses #{keyword}" do
38
+ lexer.tokenize(keyword).must_equal [[keyword.upcase.to_sym, keyword]]
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,96 @@
1
+ require 'test_helper'
2
+
3
+ module Gherkin
4
+ describe Parser do
5
+ def parse(input)
6
+ parser = Parser.new
7
+ parser.parse(input)
8
+ end
9
+
10
+ describe 'Feature name and description' do
11
+ it 'parses feature header without description' do
12
+ feature = parse(
13
+ "Feature: my feature"
14
+ )
15
+ feature.must_be_kind_of AST::Feature
16
+ feature.name.must_equal "my feature"
17
+ end
18
+
19
+ it 'parses feature header with description' do
20
+ feature = parse(
21
+ "Feature: my feature\n In order to do something\n As a user\n"
22
+ )
23
+ feature.must_be_kind_of AST::Feature
24
+ feature.name.must_equal "my feature"
25
+ end
26
+
27
+ it 'parses feature with background' do
28
+ feature = parse("""
29
+ Feature: Do something
30
+
31
+ Background:
32
+ Given blah foo bar
33
+ Then something else
34
+ """)
35
+ feature.name.must_equal "Do something"
36
+ feature.background.must_be_kind_of AST::Background
37
+ steps = feature.background.steps
38
+
39
+ given_step = steps.first
40
+ then_step = steps.last
41
+
42
+ given_step.keyword.must_equal "Given"
43
+ given_step.name.must_equal "blah foo bar"
44
+ then_step.keyword.must_equal "Then"
45
+ then_step.name.must_equal "something else"
46
+ end
47
+
48
+ it 'parses feature with scenarios' do
49
+ feature = parse("""
50
+ Feature: Do something
51
+
52
+ Scenario: Foo bar baz
53
+ Given blah foo bar
54
+ Then something else
55
+
56
+ Scenario: Foo bar baz blah
57
+ Given blah foo bar
58
+ Then something else
59
+ """)
60
+ scenarios = feature.scenarios
61
+
62
+ first_scenario = scenarios.first
63
+ last_scenario = scenarios.last
64
+
65
+ first_scenario.name.must_equal "Foo bar baz"
66
+ first_scenario.steps.first.name.must_equal "blah foo bar"
67
+ first_scenario.steps.last.name.must_equal "something else"
68
+
69
+ last_scenario.name.must_equal "Foo bar baz blah"
70
+ last_scenario.steps.first.name.must_equal "blah foo bar"
71
+ last_scenario.steps.last.name.must_equal "something else"
72
+ end
73
+
74
+ it 'parses feature with scenarios with tags' do
75
+ feature = parse("""
76
+ Feature: Do something
77
+
78
+ Scenario: Foo bar baz
79
+ Given blah foo bar
80
+ Then something else
81
+
82
+ @javascript @wip
83
+ Scenario: Foo bar baz blah
84
+ Given blah foo bar
85
+ Then something else
86
+ """)
87
+ scenarios = feature.scenarios
88
+
89
+ last_scenario = scenarios.last
90
+
91
+ last_scenario.tags.first.name.must_equal "javascript"
92
+ last_scenario.tags.last.name.must_equal "wip"
93
+ end
94
+ end
95
+ end
96
+ end