cucumber 0.1.7 → 0.1.8

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.
Files changed (80) hide show
  1. data/History.txt +81 -0
  2. data/Manifest.txt +30 -9
  3. data/README.txt +1 -2
  4. data/bin/cucumber +1 -1
  5. data/examples/calculator/README.txt +5 -0
  6. data/examples/calculator/Rakefile +1 -2
  7. data/examples/calculator/features/addition.feature +1 -0
  8. data/examples/chinese_simplified_calculator/Rakefile +6 -0
  9. data/examples/chinese_simplified_calculator/features/addition.feature +17 -0
  10. data/examples/chinese_simplified_calculator/features/steps/calculator_steps.rb +24 -0
  11. data/examples/chinese_simplified_calculator/lib/calculator.rb +10 -0
  12. data/examples/java/features/steps/hello_steps.rb +1 -1
  13. data/examples/swedish_calculator/Rakefile +5 -0
  14. data/examples/swedish_calculator/features/steps/kalkulator_steps.rb +22 -0
  15. data/examples/swedish_calculator/features/summering.feature +17 -0
  16. data/examples/swedish_calculator/lib/kalkulator.rb +11 -0
  17. data/examples/tickets/Rakefile +8 -1
  18. data/examples/tickets/cucumber.yml +2 -0
  19. data/examples/tickets/features/steps/tickets_steps.rb +15 -0
  20. data/examples/tickets/features/tickets.feature +12 -1
  21. data/gem_tasks/treetop.rake +35 -23
  22. data/lib/cucumber.rb +1 -0
  23. data/lib/cucumber/cli.rb +19 -5
  24. data/lib/cucumber/core_ext/proc.rb +8 -5
  25. data/lib/cucumber/executor.rb +7 -1
  26. data/lib/cucumber/formatters.rb +1 -1
  27. data/lib/cucumber/formatters/html_formatter.rb +6 -3
  28. data/lib/cucumber/formatters/pretty_formatter.rb +29 -7
  29. data/lib/cucumber/formatters/profile_formatter.rb +92 -0
  30. data/lib/cucumber/languages.yml +39 -12
  31. data/lib/cucumber/model.rb +1 -0
  32. data/lib/cucumber/model/table.rb +28 -0
  33. data/lib/cucumber/rails/world.rb +1 -3
  34. data/lib/cucumber/rake/task.rb +1 -1
  35. data/lib/cucumber/tree/feature.rb +8 -2
  36. data/lib/cucumber/tree/scenario.rb +23 -6
  37. data/lib/cucumber/tree/step.rb +5 -4
  38. data/lib/cucumber/treetop_parser/feature.treetop.erb +54 -12
  39. data/lib/cucumber/treetop_parser/feature_da.rb +415 -74
  40. data/lib/cucumber/treetop_parser/feature_de.rb +415 -74
  41. data/lib/cucumber/treetop_parser/feature_en.rb +415 -74
  42. data/lib/cucumber/treetop_parser/feature_es.rb +415 -74
  43. data/lib/cucumber/treetop_parser/feature_et.rb +415 -74
  44. data/lib/cucumber/treetop_parser/feature_fr.rb +415 -74
  45. data/lib/cucumber/treetop_parser/feature_nl.rb +1593 -0
  46. data/lib/cucumber/treetop_parser/feature_no.rb +415 -74
  47. data/lib/cucumber/treetop_parser/feature_pt.rb +415 -74
  48. data/lib/cucumber/treetop_parser/feature_ru.rb +415 -74
  49. data/lib/cucumber/treetop_parser/feature_se.rb +419 -78
  50. data/lib/cucumber/treetop_parser/feature_zh-CN.rb +1593 -0
  51. data/lib/cucumber/version.rb +1 -1
  52. data/{generators → rails_generators}/cucumber/cucumber_generator.rb +0 -0
  53. data/{generators → rails_generators}/cucumber/templates/common_webrat.rb +1 -10
  54. data/{generators → rails_generators}/cucumber/templates/cucumber +0 -0
  55. data/{generators → rails_generators}/cucumber/templates/cucumber.rake +0 -0
  56. data/{generators → rails_generators}/cucumber/templates/env.rb +0 -0
  57. data/{generators → rails_generators}/feature/feature_generator.rb +0 -0
  58. data/{generators → rails_generators}/feature/templates/feature.erb +1 -0
  59. data/{generators → rails_generators}/feature/templates/steps.erb +0 -0
  60. data/spec/cucumber/cli_spec.rb +11 -3
  61. data/spec/cucumber/core_ext/proc_spec.rb +6 -0
  62. data/spec/cucumber/formatters/html_formatter_spec.rb +16 -1
  63. data/spec/cucumber/formatters/pretty_formatter_spec.rb +54 -25
  64. data/spec/cucumber/formatters/profile_formatter_spec.rb +193 -0
  65. data/spec/cucumber/model/table_spec.rb +20 -0
  66. data/spec/cucumber/rails/stubs/mini_rails.rb +17 -0
  67. data/spec/cucumber/rails/stubs/test_help.rb +1 -0
  68. data/spec/cucumber/rails/world_spec.rb +11 -0
  69. data/spec/cucumber/tree/feature_spec.rb +12 -0
  70. data/spec/cucumber/tree/scenario_spec.rb +22 -0
  71. data/spec/cucumber/tree/step_spec.rb +12 -2
  72. data/spec/cucumber/treetop_parser/empty_scenario.feature +1 -1
  73. data/spec/cucumber/treetop_parser/feature_parser_spec.rb +18 -0
  74. data/spec/cucumber/treetop_parser/fit_scenario.feature +1 -0
  75. data/spec/cucumber/treetop_parser/multiline_steps.feature +13 -0
  76. data/spec/cucumber/treetop_parser/multiple_tables.feature +2 -0
  77. data/spec/cucumber/treetop_parser/test_dos.feature +1 -0
  78. data/spec/cucumber/treetop_parser/with_comments.feature +6 -2
  79. metadata +34 -12
  80. data/examples/calculator/cucumber.yml +0 -1
@@ -15,7 +15,7 @@ module Cucumber
15
15
  attr_accessor :rcov_opts
16
16
 
17
17
  # Define a task
18
- def initialize(task_name = "features", desc = "Run Features")
18
+ def initialize(task_name = "features", desc = "Run Features with Cucumber")
19
19
  @task_name, @desc = task_name, desc
20
20
  @libs = []
21
21
  @rcov_opts = %w{--rails --exclude osx\/objc,gems\/}
@@ -1,6 +1,8 @@
1
1
  module Cucumber
2
2
  module Tree
3
3
  class Feature
4
+ MIN_PADDING = 2
5
+
4
6
  attr_accessor :file
5
7
 
6
8
  def initialize(header, &proc)
@@ -9,8 +11,8 @@ module Cucumber
9
11
  instance_eval(&proc) if block_given?
10
12
  end
11
13
 
12
- def add_scenario(name, &proc)
13
- scenario = Scenario.new(self, name, &proc)
14
+ def add_scenario(name, line, &proc)
15
+ scenario = Scenario.new(self, name, line, &proc)
14
16
  @scenarios << scenario
15
17
  scenario
16
18
  end
@@ -25,6 +27,10 @@ module Cucumber
25
27
  @scenarios.find {|s| s.name == name}
26
28
  end
27
29
 
30
+ def padding_length
31
+ MIN_PADDING
32
+ end
33
+
28
34
  def Scenario(name, &proc)
29
35
  add_scenario(name, &proc)
30
36
  end
@@ -28,13 +28,14 @@ module Cucumber
28
28
 
29
29
  class Scenario < BaseScenario
30
30
  MIN_PADDING = 2
31
+ INDENT = 2
31
32
 
32
33
  # If a table follows, the header will be stored here. Weird, but convenient.
33
34
  attr_accessor :table_header
34
35
  attr_reader :name, :line
35
36
 
36
- def initialize(feature, name, &proc)
37
- @feature, @name = feature, name
37
+ def initialize(feature, name, line, &proc)
38
+ @feature, @name, @line = feature, name, line
38
39
  @steps_and_given_scenarios = []
39
40
  instance_eval(&proc) if block_given?
40
41
  end
@@ -51,12 +52,28 @@ module Cucumber
51
52
  @feature.scenario_named(name)
52
53
  end
53
54
 
54
- def padding_length(step)
55
- (max_step_length - step.length) + MIN_PADDING
55
+ def length
56
+ @length ||= Cucumber.language['scenario'].length + 2 + (@name.nil? ? 0 : @name.length)
56
57
  end
57
-
58
+
59
+ def max_line_length
60
+ [length, max_step_length].max
61
+ end
62
+
63
+ def padding_length
64
+ padding = (max_line_length - length) + MIN_PADDING
65
+ padding += INDENT if length != max_line_length
66
+ padding
67
+ end
68
+
69
+ def step_padding_length(step)
70
+ padding = (max_line_length - step.length) + MIN_PADDING
71
+ padding -= INDENT if length == max_line_length
72
+ padding
73
+ end
74
+
58
75
  def max_step_length
59
- steps.map{|step| step.length}.max
76
+ @max_step_length ||= (steps.map{|step| step.length}.max || 0)
60
77
  end
61
78
 
62
79
  def row?
@@ -45,7 +45,7 @@ module Cucumber
45
45
  strip_pos = method_line_pos - (Pending === e ? PENDING_ADJUSTMENT : REGULAR_ADJUSTMENT)
46
46
  else
47
47
  # This happens with rails, because they screw up the backtrace
48
- # before we get here (injecting erb stactrace and such)
48
+ # before we get here (injecting erb stacktrace and such)
49
49
  end
50
50
  format_error(strip_pos, proc, e)
51
51
  end
@@ -79,13 +79,13 @@ module Cucumber
79
79
  end
80
80
 
81
81
  def padding_length
82
- @scenario.padding_length(self)
82
+ @scenario.step_padding_length(self)
83
83
  end
84
84
  end
85
85
 
86
86
  class Step < BaseStep
87
87
  attr_reader :keyword, :name, :line
88
- attr_accessor :arity
88
+ attr_accessor :arity, :extra_args
89
89
 
90
90
  def row?
91
91
  false
@@ -93,12 +93,13 @@ module Cucumber
93
93
 
94
94
  def initialize(scenario, keyword, name, line)
95
95
  @scenario, @keyword, @name, @line = scenario, keyword, name, line
96
+ @extra_args = []
96
97
  end
97
98
 
98
99
  def regexp_args_proc(step_mother)
99
100
  regexp, args, proc = step_mother.regexp_args_proc(name)
100
101
  @arity = args.length
101
- [regexp, args, proc]
102
+ [regexp, (args + extra_args), proc]
102
103
  end
103
104
 
104
105
  def format(regexp, format=nil, &proc)
@@ -3,7 +3,7 @@ module TreetopParser
3
3
 
4
4
  grammar Feature
5
5
  rule root
6
- header scenario_sequence space? {
6
+ space? header scenario_sequence space? {
7
7
  def compile
8
8
  feature = Tree::Feature.new(header.text_value.strip)
9
9
  scenario_sequence.compile(feature)
@@ -13,7 +13,7 @@ grammar Feature
13
13
  end
14
14
 
15
15
  rule header
16
- (!scenario_keyword .)+
16
+ (!(scenario_keyword / comment_to_eol) .)+
17
17
  end
18
18
 
19
19
  rule scenario_sequence
@@ -31,9 +31,10 @@ grammar Feature
31
31
  end
32
32
 
33
33
  rule scenario
34
- scenario_keyword space name:line_to_eol steps:(space step_sequence)? {
34
+ scenario_keyword space? name:line_to_eol steps:(space step_sequence)? {
35
35
  def compile(feature)
36
- scenario = feature.add_scenario(name.text_value.strip)
36
+ line = input.line_of(interval.first)
37
+ scenario = feature.add_scenario(name.text_value.strip, line)
37
38
  steps.step_sequence.compile(scenario) if steps.respond_to?(:step_sequence)
38
39
  # TODO - GET RID OF THIS last_scenario NASTINESS
39
40
  # Use a better datastructure, like a linked list...
@@ -43,7 +44,15 @@ grammar Feature
43
44
  end
44
45
 
45
46
  rule scenario_or_table
46
- scenario / table
47
+ scenario / more_examples
48
+ end
49
+
50
+ rule more_examples
51
+ more_examples_keyword space table {
52
+ def compile(f)
53
+ table.compile(f)
54
+ end
55
+ }
47
56
  end
48
57
 
49
58
  rule table
@@ -54,7 +63,17 @@ grammar Feature
54
63
  feature.add_row_scenario(Feature.last_scenario, table_line.cell_values, table_line.line)
55
64
  end
56
65
  end
57
-
66
+
67
+ def matrix
68
+ ([head] + body).map do |table_line|
69
+ table_line.cell_values # We're losing the line - we'll get it back when we make our own class
70
+ end
71
+ end
72
+
73
+ def to_arg
74
+ Model::Table.new(matrix)
75
+ end
76
+
58
77
  def body
59
78
  super.elements.map { |elt| elt.table_line }
60
79
  end
@@ -96,7 +115,7 @@ grammar Feature
96
115
  end
97
116
 
98
117
  rule given_scenario
99
- given_scenario_keyword space name:line_to_eol {
118
+ given_scenario_keyword space? name:line_to_eol {
100
119
  def compile(scenario)
101
120
  line = input.line_of(interval.first)
102
121
  scenario.create_given_scenario(name.text_value.strip, line)
@@ -105,13 +124,32 @@ grammar Feature
105
124
  end
106
125
 
107
126
  rule plain_step
108
- step_keyword space name:line_to_eol {
127
+ step_keyword space? name:line_to_eol multi:(space multiline_arg)? {
109
128
  def compile(scenario)
110
129
  line = input.line_of(interval.first)
111
- scenario.create_step(step_keyword.text_value, name.text_value.strip, line)
130
+ step = scenario.create_step(step_keyword.text_value, name.text_value.strip, line)
131
+ if multi.respond_to?(:multiline_arg)
132
+ step.extra_args << multi.multiline_arg.to_arg
133
+ end
112
134
  end
113
135
  }
114
136
  end
137
+
138
+ rule multiline_arg
139
+ table / multiline_string
140
+ end
141
+
142
+ rule multiline_string
143
+ quote string:(!quote .)* quote {
144
+ def to_arg
145
+ string.text_value.split("\n").map{|l| l.strip}.join("\n")
146
+ end
147
+ }
148
+ end
149
+
150
+ rule quote
151
+ '"'
152
+ end
115
153
 
116
154
  rule separator
117
155
  '|'
@@ -142,15 +180,19 @@ grammar Feature
142
180
  end
143
181
 
144
182
  rule step_keyword
145
- '<%= words['given'] %>' / '<%= words['when'] %>' / '<%= words['then'] %>' / '<%= words['and'] %>' / '<%= words['but'] %>'
183
+ "<%= words['given'] %>" / "<%= words['when'] %>" / "<%= words['then'] %>" / "<%= words['and'] %>" / "<%= words['but'] %>"
146
184
  end
147
185
 
148
186
  rule scenario_keyword
149
- '<%= words['scenario'] %>:'
187
+ "<%= words['scenario'] %>" ":"?
188
+ end
189
+
190
+ rule more_examples_keyword
191
+ "<%= words['more_examples'] %>" ":"?
150
192
  end
151
193
 
152
194
  rule given_scenario_keyword
153
- '<%= words['given_scenario'] %>' ':'?
195
+ "<%= words['given_scenario'] %>" ":"?
154
196
  end
155
197
 
156
198
  end
@@ -10,11 +10,11 @@ module Feature #:nodoc:
10
10
 
11
11
  module Root0 #:nodoc:
12
12
  def header #:nodoc:
13
- elements[0]
13
+ elements[1]
14
14
  end
15
15
 
16
16
  def scenario_sequence #:nodoc:
17
- elements[1]
17
+ elements[2]
18
18
  end
19
19
 
20
20
  end
@@ -36,19 +36,28 @@ module Feature #:nodoc:
36
36
  end
37
37
 
38
38
  i0, s0 = index, []
39
- r1 = _nt_header
39
+ r2 = _nt_space
40
+ if r2
41
+ r1 = r2
42
+ else
43
+ r1 = SyntaxNode.new(input, index...index)
44
+ end
40
45
  s0 << r1
41
46
  if r1
42
- r2 = _nt_scenario_sequence
43
- s0 << r2
44
- if r2
45
- r4 = _nt_space
47
+ r3 = _nt_header
48
+ s0 << r3
49
+ if r3
50
+ r4 = _nt_scenario_sequence
51
+ s0 << r4
46
52
  if r4
47
- r3 = r4
48
- else
49
- r3 = SyntaxNode.new(input, index...index)
53
+ r6 = _nt_space
54
+ if r6
55
+ r5 = r6
56
+ else
57
+ r5 = SyntaxNode.new(input, index...index)
58
+ end
59
+ s0 << r5
50
60
  end
51
- s0 << r3
52
61
  end
53
62
  end
54
63
  if s0.last
@@ -80,7 +89,19 @@ module Feature #:nodoc:
80
89
  loop do
81
90
  i1, s1 = index, []
82
91
  i2 = index
83
- r3 = _nt_scenario_keyword
92
+ i3 = index
93
+ r4 = _nt_scenario_keyword
94
+ if r4
95
+ r3 = r4
96
+ else
97
+ r5 = _nt_comment_to_eol
98
+ if r5
99
+ r3 = r5
100
+ else
101
+ self.index = i3
102
+ r3 = nil
103
+ end
104
+ end
84
105
  if r3
85
106
  r2 = nil
86
107
  else
@@ -90,13 +111,13 @@ module Feature #:nodoc:
90
111
  s1 << r2
91
112
  if r2
92
113
  if index < input_length
93
- r4 = (SyntaxNode).new(input, index...(index + 1))
114
+ r6 = (SyntaxNode).new(input, index...(index + 1))
94
115
  @index += 1
95
116
  else
96
117
  terminal_parse_failure("any character")
97
- r4 = nil
118
+ r6 = nil
98
119
  end
99
- s1 << r4
120
+ s1 << r6
100
121
  end
101
122
  if s1.last
102
123
  r1 = (SyntaxNode).new(input, i1...index, s1)
@@ -226,10 +247,6 @@ module Feature #:nodoc:
226
247
  elements[0]
227
248
  end
228
249
 
229
- def space #:nodoc:
230
- elements[1]
231
- end
232
-
233
250
  def name #:nodoc:
234
251
  elements[2]
235
252
  end
@@ -241,7 +258,8 @@ module Feature #:nodoc:
241
258
 
242
259
  module Scenario2 #:nodoc:
243
260
  def compile(feature) #:nodoc:
244
- scenario = feature.add_scenario(name.text_value.strip)
261
+ line = input.line_of(interval.first)
262
+ scenario = feature.add_scenario(name.text_value.strip, line)
245
263
  steps.step_sequence.compile(scenario) if steps.respond_to?(:step_sequence)
246
264
  # TODO - GET RID OF THIS last_scenario NASTINESS
247
265
  # Use a better datastructure, like a linked list...
@@ -261,32 +279,37 @@ module Feature #:nodoc:
261
279
  r1 = _nt_scenario_keyword
262
280
  s0 << r1
263
281
  if r1
264
- r2 = _nt_space
282
+ r3 = _nt_space
283
+ if r3
284
+ r2 = r3
285
+ else
286
+ r2 = SyntaxNode.new(input, index...index)
287
+ end
265
288
  s0 << r2
266
289
  if r2
267
- r3 = _nt_line_to_eol
268
- s0 << r3
269
- if r3
270
- i5, s5 = index, []
271
- r6 = _nt_space
272
- s5 << r6
273
- if r6
274
- r7 = _nt_step_sequence
275
- s5 << r7
290
+ r4 = _nt_line_to_eol
291
+ s0 << r4
292
+ if r4
293
+ i6, s6 = index, []
294
+ r7 = _nt_space
295
+ s6 << r7
296
+ if r7
297
+ r8 = _nt_step_sequence
298
+ s6 << r8
276
299
  end
277
- if s5.last
278
- r5 = (SyntaxNode).new(input, i5...index, s5)
279
- r5.extend(Scenario0)
300
+ if s6.last
301
+ r6 = (SyntaxNode).new(input, i6...index, s6)
302
+ r6.extend(Scenario0)
280
303
  else
281
- self.index = i5
282
- r5 = nil
304
+ self.index = i6
305
+ r6 = nil
283
306
  end
284
- if r5
285
- r4 = r5
307
+ if r6
308
+ r5 = r6
286
309
  else
287
- r4 = SyntaxNode.new(input, index...index)
310
+ r5 = SyntaxNode.new(input, index...index)
288
311
  end
289
- s0 << r4
312
+ s0 << r5
290
313
  end
291
314
  end
292
315
  end
@@ -317,7 +340,7 @@ module Feature #:nodoc:
317
340
  if r1
318
341
  r0 = r1
319
342
  else
320
- r2 = _nt_table
343
+ r2 = _nt_more_examples
321
344
  if r2
322
345
  r0 = r2
323
346
  else
@@ -331,6 +354,59 @@ module Feature #:nodoc:
331
354
  return r0
332
355
  end
333
356
 
357
+ module MoreExamples0 #:nodoc:
358
+ def more_examples_keyword #:nodoc:
359
+ elements[0]
360
+ end
361
+
362
+ def space #:nodoc:
363
+ elements[1]
364
+ end
365
+
366
+ def table #:nodoc:
367
+ elements[2]
368
+ end
369
+ end
370
+
371
+ module MoreExamples1 #:nodoc:
372
+ def compile(f) #:nodoc:
373
+ table.compile(f)
374
+ end
375
+ end
376
+
377
+ def _nt_more_examples #:nodoc:
378
+ start_index = index
379
+ if node_cache[:more_examples].has_key?(index)
380
+ cached = node_cache[:more_examples][index]
381
+ @index = cached.interval.end if cached
382
+ return cached
383
+ end
384
+
385
+ i0, s0 = index, []
386
+ r1 = _nt_more_examples_keyword
387
+ s0 << r1
388
+ if r1
389
+ r2 = _nt_space
390
+ s0 << r2
391
+ if r2
392
+ r3 = _nt_table
393
+ s0 << r3
394
+ end
395
+ end
396
+ if s0.last
397
+ r0 = (SyntaxNode).new(input, i0...index, s0)
398
+ r0.extend(MoreExamples0)
399
+ r0.extend(MoreExamples1)
400
+ else
401
+ self.index = i0
402
+ r0 = nil
403
+ end
404
+
405
+ node_cache[:more_examples][start_index] = r0
406
+
407
+ return r0
408
+ end
409
+
334
410
  module Table0 #:nodoc:
335
411
  def eol #:nodoc:
336
412
  elements[1]
@@ -358,7 +434,17 @@ module Feature #:nodoc:
358
434
  feature.add_row_scenario(Feature.last_scenario, table_line.cell_values, table_line.line)
359
435
  end
360
436
  end
361
-
437
+
438
+ def matrix #:nodoc:
439
+ ([head] + body).map do |table_line|
440
+ table_line.cell_values # We're losing the line - we'll get it back when we make our own class #:nodoc:
441
+ end
442
+ end
443
+
444
+ def to_arg #:nodoc:
445
+ Model::Table.new(matrix)
446
+ end
447
+
362
448
  def body #:nodoc:
363
449
  super.elements.map { |elt| elt.table_line }
364
450
  end
@@ -729,10 +815,6 @@ module Feature #:nodoc:
729
815
  elements[0]
730
816
  end
731
817
 
732
- def space #:nodoc:
733
- elements[1]
734
- end
735
-
736
818
  def name #:nodoc:
737
819
  elements[2]
738
820
  end
@@ -757,11 +839,16 @@ module Feature #:nodoc:
757
839
  r1 = _nt_given_scenario_keyword
758
840
  s0 << r1
759
841
  if r1
760
- r2 = _nt_space
842
+ r3 = _nt_space
843
+ if r3
844
+ r2 = r3
845
+ else
846
+ r2 = SyntaxNode.new(input, index...index)
847
+ end
761
848
  s0 << r2
762
849
  if r2
763
- r3 = _nt_line_to_eol
764
- s0 << r3
850
+ r4 = _nt_line_to_eol
851
+ s0 << r4
765
852
  end
766
853
  end
767
854
  if s0.last
@@ -779,23 +866,36 @@ module Feature #:nodoc:
779
866
  end
780
867
 
781
868
  module PlainStep0 #:nodoc:
782
- def step_keyword #:nodoc:
869
+ def space #:nodoc:
783
870
  elements[0]
784
871
  end
785
872
 
786
- def space #:nodoc:
873
+ def multiline_arg #:nodoc:
787
874
  elements[1]
788
875
  end
876
+ end
877
+
878
+ module PlainStep1 #:nodoc:
879
+ def step_keyword #:nodoc:
880
+ elements[0]
881
+ end
789
882
 
790
883
  def name #:nodoc:
791
884
  elements[2]
792
885
  end
886
+
887
+ def multi #:nodoc:
888
+ elements[3]
889
+ end
793
890
  end
794
891
 
795
- module PlainStep1 #:nodoc:
892
+ module PlainStep2 #:nodoc:
796
893
  def compile(scenario) #:nodoc:
797
894
  line = input.line_of(interval.first)
798
- scenario.create_step(step_keyword.text_value, name.text_value.strip, line)
895
+ step = scenario.create_step(step_keyword.text_value, name.text_value.strip, line)
896
+ if multi.respond_to?(:multiline_arg)
897
+ step.extra_args << multi.multiline_arg.to_arg
898
+ end
799
899
  end
800
900
  end
801
901
 
@@ -811,17 +911,44 @@ module Feature #:nodoc:
811
911
  r1 = _nt_step_keyword
812
912
  s0 << r1
813
913
  if r1
814
- r2 = _nt_space
914
+ r3 = _nt_space
915
+ if r3
916
+ r2 = r3
917
+ else
918
+ r2 = SyntaxNode.new(input, index...index)
919
+ end
815
920
  s0 << r2
816
921
  if r2
817
- r3 = _nt_line_to_eol
818
- s0 << r3
922
+ r4 = _nt_line_to_eol
923
+ s0 << r4
924
+ if r4
925
+ i6, s6 = index, []
926
+ r7 = _nt_space
927
+ s6 << r7
928
+ if r7
929
+ r8 = _nt_multiline_arg
930
+ s6 << r8
931
+ end
932
+ if s6.last
933
+ r6 = (SyntaxNode).new(input, i6...index, s6)
934
+ r6.extend(PlainStep0)
935
+ else
936
+ self.index = i6
937
+ r6 = nil
938
+ end
939
+ if r6
940
+ r5 = r6
941
+ else
942
+ r5 = SyntaxNode.new(input, index...index)
943
+ end
944
+ s0 << r5
945
+ end
819
946
  end
820
947
  end
821
948
  if s0.last
822
949
  r0 = (SyntaxNode).new(input, i0...index, s0)
823
- r0.extend(PlainStep0)
824
950
  r0.extend(PlainStep1)
951
+ r0.extend(PlainStep2)
825
952
  else
826
953
  self.index = i0
827
954
  r0 = nil
@@ -832,6 +959,145 @@ module Feature #:nodoc:
832
959
  return r0
833
960
  end
834
961
 
962
+ def _nt_multiline_arg #:nodoc:
963
+ start_index = index
964
+ if node_cache[:multiline_arg].has_key?(index)
965
+ cached = node_cache[:multiline_arg][index]
966
+ @index = cached.interval.end if cached
967
+ return cached
968
+ end
969
+
970
+ i0 = index
971
+ r1 = _nt_table
972
+ if r1
973
+ r0 = r1
974
+ else
975
+ r2 = _nt_multiline_string
976
+ if r2
977
+ r0 = r2
978
+ else
979
+ self.index = i0
980
+ r0 = nil
981
+ end
982
+ end
983
+
984
+ node_cache[:multiline_arg][start_index] = r0
985
+
986
+ return r0
987
+ end
988
+
989
+ module MultilineString0 #:nodoc:
990
+ end
991
+
992
+ module MultilineString1 #:nodoc:
993
+ def quote #:nodoc:
994
+ elements[0]
995
+ end
996
+
997
+ def string #:nodoc:
998
+ elements[1]
999
+ end
1000
+
1001
+ def quote #:nodoc:
1002
+ elements[2]
1003
+ end
1004
+ end
1005
+
1006
+ module MultilineString2 #:nodoc:
1007
+ def to_arg #:nodoc:
1008
+ string.text_value.split("\n").map{|l| l.strip}.join("\n")
1009
+ end
1010
+ end
1011
+
1012
+ def _nt_multiline_string #:nodoc:
1013
+ start_index = index
1014
+ if node_cache[:multiline_string].has_key?(index)
1015
+ cached = node_cache[:multiline_string][index]
1016
+ @index = cached.interval.end if cached
1017
+ return cached
1018
+ end
1019
+
1020
+ i0, s0 = index, []
1021
+ r1 = _nt_quote
1022
+ s0 << r1
1023
+ if r1
1024
+ s2, i2 = [], index
1025
+ loop do
1026
+ i3, s3 = index, []
1027
+ i4 = index
1028
+ r5 = _nt_quote
1029
+ if r5
1030
+ r4 = nil
1031
+ else
1032
+ self.index = i4
1033
+ r4 = SyntaxNode.new(input, index...index)
1034
+ end
1035
+ s3 << r4
1036
+ if r4
1037
+ if index < input_length
1038
+ r6 = (SyntaxNode).new(input, index...(index + 1))
1039
+ @index += 1
1040
+ else
1041
+ terminal_parse_failure("any character")
1042
+ r6 = nil
1043
+ end
1044
+ s3 << r6
1045
+ end
1046
+ if s3.last
1047
+ r3 = (SyntaxNode).new(input, i3...index, s3)
1048
+ r3.extend(MultilineString0)
1049
+ else
1050
+ self.index = i3
1051
+ r3 = nil
1052
+ end
1053
+ if r3
1054
+ s2 << r3
1055
+ else
1056
+ break
1057
+ end
1058
+ end
1059
+ r2 = SyntaxNode.new(input, i2...index, s2)
1060
+ s0 << r2
1061
+ if r2
1062
+ r7 = _nt_quote
1063
+ s0 << r7
1064
+ end
1065
+ end
1066
+ if s0.last
1067
+ r0 = (SyntaxNode).new(input, i0...index, s0)
1068
+ r0.extend(MultilineString1)
1069
+ r0.extend(MultilineString2)
1070
+ else
1071
+ self.index = i0
1072
+ r0 = nil
1073
+ end
1074
+
1075
+ node_cache[:multiline_string][start_index] = r0
1076
+
1077
+ return r0
1078
+ end
1079
+
1080
+ def _nt_quote #:nodoc:
1081
+ start_index = index
1082
+ if node_cache[:quote].has_key?(index)
1083
+ cached = node_cache[:quote][index]
1084
+ @index = cached.interval.end if cached
1085
+ return cached
1086
+ end
1087
+
1088
+ if input.index('"', index) == index
1089
+ r0 = (SyntaxNode).new(input, index...(index + 1))
1090
+ @index += 1
1091
+ else
1092
+ terminal_parse_failure('"')
1093
+ r0 = nil
1094
+ end
1095
+
1096
+ node_cache[:quote][start_index] = r0
1097
+
1098
+ return r0
1099
+ end
1100
+
835
1101
  def _nt_separator #:nodoc:
836
1102
  start_index = index
837
1103
  if node_cache[:separator].has_key?(index)
@@ -1109,51 +1375,51 @@ module Feature #:nodoc:
1109
1375
  end
1110
1376
 
1111
1377
  i0 = index
1112
- if input.index('Givet', index) == index
1378
+ if input.index("Givet", index) == index
1113
1379
  r1 = (SyntaxNode).new(input, index...(index + 5))
1114
1380
  @index += 5
1115
1381
  else
1116
- terminal_parse_failure('Givet')
1382
+ terminal_parse_failure("Givet")
1117
1383
  r1 = nil
1118
1384
  end
1119
1385
  if r1
1120
1386
  r0 = r1
1121
1387
  else
1122
- if input.index('Når', index) == index
1388
+ if input.index("Når", index) == index
1123
1389
  r2 = (SyntaxNode).new(input, index...(index + 4))
1124
1390
  @index += 4
1125
1391
  else
1126
- terminal_parse_failure('Når')
1392
+ terminal_parse_failure("Når")
1127
1393
  r2 = nil
1128
1394
  end
1129
1395
  if r2
1130
1396
  r0 = r2
1131
1397
  else
1132
- if input.index('', index) == index
1398
+ if input.index("", index) == index
1133
1399
  r3 = (SyntaxNode).new(input, index...(index + 3))
1134
1400
  @index += 3
1135
1401
  else
1136
- terminal_parse_failure('')
1402
+ terminal_parse_failure("")
1137
1403
  r3 = nil
1138
1404
  end
1139
1405
  if r3
1140
1406
  r0 = r3
1141
1407
  else
1142
- if input.index('Og', index) == index
1408
+ if input.index("Og", index) == index
1143
1409
  r4 = (SyntaxNode).new(input, index...(index + 2))
1144
1410
  @index += 2
1145
1411
  else
1146
- terminal_parse_failure('Og')
1412
+ terminal_parse_failure("Og")
1147
1413
  r4 = nil
1148
1414
  end
1149
1415
  if r4
1150
1416
  r0 = r4
1151
1417
  else
1152
- if input.index('Men', index) == index
1418
+ if input.index("Men", index) == index
1153
1419
  r5 = (SyntaxNode).new(input, index...(index + 3))
1154
1420
  @index += 3
1155
1421
  else
1156
- terminal_parse_failure('Men')
1422
+ terminal_parse_failure("Men")
1157
1423
  r5 = nil
1158
1424
  end
1159
1425
  if r5
@@ -1172,6 +1438,9 @@ module Feature #:nodoc:
1172
1438
  return r0
1173
1439
  end
1174
1440
 
1441
+ module ScenarioKeyword0 #:nodoc:
1442
+ end
1443
+
1175
1444
  def _nt_scenario_keyword #:nodoc:
1176
1445
  start_index = index
1177
1446
  if node_cache[:scenario_keyword].has_key?(index)
@@ -1180,11 +1449,35 @@ module Feature #:nodoc:
1180
1449
  return cached
1181
1450
  end
1182
1451
 
1183
- if input.index('Scenarie:', index) == index
1184
- r0 = (SyntaxNode).new(input, index...(index + 9))
1185
- @index += 9
1452
+ i0, s0 = index, []
1453
+ if input.index("Scenarie", index) == index
1454
+ r1 = (SyntaxNode).new(input, index...(index + 8))
1455
+ @index += 8
1456
+ else
1457
+ terminal_parse_failure("Scenarie")
1458
+ r1 = nil
1459
+ end
1460
+ s0 << r1
1461
+ if r1
1462
+ if input.index(":", index) == index
1463
+ r3 = (SyntaxNode).new(input, index...(index + 1))
1464
+ @index += 1
1465
+ else
1466
+ terminal_parse_failure(":")
1467
+ r3 = nil
1468
+ end
1469
+ if r3
1470
+ r2 = r3
1471
+ else
1472
+ r2 = SyntaxNode.new(input, index...index)
1473
+ end
1474
+ s0 << r2
1475
+ end
1476
+ if s0.last
1477
+ r0 = (SyntaxNode).new(input, i0...index, s0)
1478
+ r0.extend(ScenarioKeyword0)
1186
1479
  else
1187
- terminal_parse_failure('Scenarie:')
1480
+ self.index = i0
1188
1481
  r0 = nil
1189
1482
  end
1190
1483
 
@@ -1193,6 +1486,54 @@ module Feature #:nodoc:
1193
1486
  return r0
1194
1487
  end
1195
1488
 
1489
+ module MoreExamplesKeyword0 #:nodoc:
1490
+ end
1491
+
1492
+ def _nt_more_examples_keyword #:nodoc:
1493
+ start_index = index
1494
+ if node_cache[:more_examples_keyword].has_key?(index)
1495
+ cached = node_cache[:more_examples_keyword][index]
1496
+ @index = cached.interval.end if cached
1497
+ return cached
1498
+ end
1499
+
1500
+ i0, s0 = index, []
1501
+ if input.index("More Examples", index) == index
1502
+ r1 = (SyntaxNode).new(input, index...(index + 13))
1503
+ @index += 13
1504
+ else
1505
+ terminal_parse_failure("More Examples")
1506
+ r1 = nil
1507
+ end
1508
+ s0 << r1
1509
+ if r1
1510
+ if input.index(":", index) == index
1511
+ r3 = (SyntaxNode).new(input, index...(index + 1))
1512
+ @index += 1
1513
+ else
1514
+ terminal_parse_failure(":")
1515
+ r3 = nil
1516
+ end
1517
+ if r3
1518
+ r2 = r3
1519
+ else
1520
+ r2 = SyntaxNode.new(input, index...index)
1521
+ end
1522
+ s0 << r2
1523
+ end
1524
+ if s0.last
1525
+ r0 = (SyntaxNode).new(input, i0...index, s0)
1526
+ r0.extend(MoreExamplesKeyword0)
1527
+ else
1528
+ self.index = i0
1529
+ r0 = nil
1530
+ end
1531
+
1532
+ node_cache[:more_examples_keyword][start_index] = r0
1533
+
1534
+ return r0
1535
+ end
1536
+
1196
1537
  module GivenScenarioKeyword0 #:nodoc:
1197
1538
  end
1198
1539
 
@@ -1205,20 +1546,20 @@ module Feature #:nodoc:
1205
1546
  end
1206
1547
 
1207
1548
  i0, s0 = index, []
1208
- if input.index('GivetScenarie', index) == index
1549
+ if input.index("GivetScenarie", index) == index
1209
1550
  r1 = (SyntaxNode).new(input, index...(index + 13))
1210
1551
  @index += 13
1211
1552
  else
1212
- terminal_parse_failure('GivetScenarie')
1553
+ terminal_parse_failure("GivetScenarie")
1213
1554
  r1 = nil
1214
1555
  end
1215
1556
  s0 << r1
1216
1557
  if r1
1217
- if input.index(':', index) == index
1558
+ if input.index(":", index) == index
1218
1559
  r3 = (SyntaxNode).new(input, index...(index + 1))
1219
1560
  @index += 1
1220
1561
  else
1221
- terminal_parse_failure(':')
1562
+ terminal_parse_failure(":")
1222
1563
  r3 = nil
1223
1564
  end
1224
1565
  if r3