cucumber 0.3.0 → 0.3.1

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 (66) hide show
  1. data/History.txt +26 -1
  2. data/Manifest.txt +20 -1
  3. data/config/hoe.rb +5 -4
  4. data/examples/i18n/hu/Rakefile +6 -0
  5. data/examples/i18n/hu/features/addition.feature +16 -0
  6. data/examples/i18n/hu/features/division.feature +9 -0
  7. data/examples/i18n/hu/features/step_definitons/calculator_steps.rb +25 -0
  8. data/examples/i18n/hu/lib/calculator.rb +14 -0
  9. data/examples/i18n/lv/Rakefile +6 -0
  10. data/examples/i18n/lv/features/addition.feature +16 -0
  11. data/examples/i18n/lv/features/division.feature +9 -0
  12. data/examples/i18n/lv/features/step_definitons/calculator_steps.rb +24 -0
  13. data/examples/i18n/lv/lib/calculator.rb +14 -0
  14. data/examples/self_test/features/background/failing_background.feature +1 -0
  15. data/examples/self_test/features/multiline_name.feature +27 -0
  16. data/examples/self_test/features/search_sample.feature +22 -0
  17. data/examples/self_test/features/step_definitions/sample_steps.rb +3 -2
  18. data/examples/tickets/Rakefile +3 -3
  19. data/examples/tickets/features/236.feature +9 -9
  20. data/examples/tickets/features/272/hooks.feature +26 -0
  21. data/examples/tickets/features/272/hooks_steps.rb +53 -0
  22. data/examples/tickets/features/301/filter_background_tagged_hooks.feature +6 -0
  23. data/examples/tickets/features/301/filter_background_tagged_hooks_steps.rb +12 -0
  24. data/examples/tickets/features/306/only_background.feature +4 -0
  25. data/features/background.feature +2 -1
  26. data/features/cucumber_cli.feature +88 -12
  27. data/features/cucumber_cli_outlines.feature +32 -0
  28. data/features/custom_formatter.feature +2 -2
  29. data/features/multiline_names.feature +43 -0
  30. data/features/report_called_undefined_steps.feature +1 -1
  31. data/features/usage.feature +13 -4
  32. data/lib/cucumber/ast/background.rb +10 -13
  33. data/lib/cucumber/ast/feature.rb +5 -0
  34. data/lib/cucumber/ast/feature_element.rb +23 -12
  35. data/lib/cucumber/ast/outline_table.rb +10 -0
  36. data/lib/cucumber/ast/py_string.rb +5 -1
  37. data/lib/cucumber/ast/scenario.rb +17 -6
  38. data/lib/cucumber/ast/scenario_outline.rb +1 -6
  39. data/lib/cucumber/ast/step.rb +6 -3
  40. data/lib/cucumber/ast/step_collection.rb +9 -1
  41. data/lib/cucumber/ast/table.rb +8 -0
  42. data/lib/cucumber/ast/visitor.rb +2 -2
  43. data/lib/cucumber/cli/configuration.rb +15 -14
  44. data/lib/cucumber/formatter/console.rb +1 -1
  45. data/lib/cucumber/formatter/html.rb +1 -1
  46. data/lib/cucumber/formatter/pretty.rb +7 -8
  47. data/lib/cucumber/languages.yml +30 -0
  48. data/lib/cucumber/parser/feature.rb +214 -14
  49. data/lib/cucumber/parser/feature.tt +44 -14
  50. data/lib/cucumber/parser/treetop_ext.rb +3 -3
  51. data/lib/cucumber/rails/world.rb +6 -0
  52. data/lib/cucumber/step_mother.rb +2 -1
  53. data/lib/cucumber/version.rb +1 -1
  54. data/lib/cucumber/world.rb +2 -2
  55. data/rails_generators/cucumber/templates/paths.rb +11 -13
  56. data/rails_generators/feature/feature_generator.rb +1 -1
  57. data/spec/cucumber/ast/feature_element_spec.rb +40 -0
  58. data/spec/cucumber/ast/py_string_spec.rb +4 -0
  59. data/spec/cucumber/ast/table_spec.rb +20 -4
  60. data/spec/cucumber/ast/visitor_spec.rb +27 -0
  61. data/spec/cucumber/cli/configuration_spec.rb +4 -13
  62. data/spec/cucumber/cli/main_spec.rb +55 -153
  63. data/spec/cucumber/parser/feature_parser_spec.rb +79 -0
  64. data/spec/cucumber/step_mother_spec.rb +12 -5
  65. metadata +22 -13
  66. data/spec/cucumber/formatters/profile_formatter_spec.rb +0 -198
@@ -70,6 +70,16 @@ module Cucumber
70
70
  @table.accept_hook?(hook)
71
71
  end
72
72
 
73
+ # Returns true if one or more steps failed
74
+ def failed?
75
+ @step_invocations.failed?
76
+ end
77
+
78
+ # Returns true if all steps passed
79
+ def passed?
80
+ @step_invocations.passed?
81
+ end
82
+
73
83
  private
74
84
 
75
85
  def header?
@@ -43,7 +43,11 @@ module Cucumber
43
43
  end
44
44
  PyString.new(@start_line, @end_line, string, @quotes_indent)
45
45
  end
46
-
46
+
47
+ def has_text?(text)
48
+ @string.index(text)
49
+ end
50
+
47
51
  # For testing only
48
52
  def to_sexp #:nodoc:
49
53
  [:py_string, to_s]
@@ -12,20 +12,16 @@ module Cucumber
12
12
  step_invocations = steps.map{|step| step.step_invocation}
13
13
  if @background
14
14
  @steps = @background.step_collection(step_invocations)
15
+ @background.feature_elements << self
15
16
  else
16
17
  @steps = StepCollection.new(step_invocations)
17
18
  end
18
19
  end
19
20
 
20
- def feature=(feature)
21
- @feature = feature
22
- @background.feature = feature if @background
23
- end
24
-
25
21
  def accept(visitor)
26
22
  visitor.visit_comment(@comment)
27
23
  visitor.visit_tags(@tags)
28
- visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(text_length))
24
+ visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
29
25
 
30
26
  skip = @background && @background.failed?
31
27
  skip_invoke! if skip
@@ -34,6 +30,21 @@ module Cucumber
34
30
  end
35
31
  end
36
32
 
33
+ # Returns true if one or more steps failed
34
+ def failed?
35
+ @steps.failed?
36
+ end
37
+
38
+ # Returns true if all steps passed
39
+ def passed?
40
+ @steps.passed?
41
+ end
42
+
43
+ # Returns the first exception (if any)
44
+ def exception
45
+ @steps.exception
46
+ end
47
+
37
48
  def skip_invoke!
38
49
  @steps.each{|step_invocation| step_invocation.skip_invoke!}
39
50
  @feature.next_feature_element(self) do |next_one|
@@ -25,15 +25,10 @@ module Cucumber
25
25
  end
26
26
  end
27
27
 
28
- def feature=(feature)
29
- @feature = feature
30
- @background.feature = feature if @background
31
- end
32
-
33
28
  def accept(visitor)
34
29
  visitor.visit_comment(@comment)
35
30
  visitor.visit_tags(@tags)
36
- visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(text_length))
31
+ visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
37
32
  visitor.visit_steps(@steps)
38
33
 
39
34
  skip_invoke! if @background && @background.failed?
@@ -8,6 +8,8 @@ module Cucumber
8
8
  attr_writer :step_collection, :options
9
9
  attr_accessor :feature_element, :exception
10
10
 
11
+ INDENT = 2
12
+
11
13
  def initialize(line, keyword, name, multiline_arg=nil)
12
14
  @line, @keyword, @name, @multiline_arg = line, keyword, name, multiline_arg
13
15
  end
@@ -32,7 +34,7 @@ module Cucumber
32
34
 
33
35
  def accept(visitor)
34
36
  # The only time a Step is visited is when it is in a ScenarioOutline.
35
- # Otherwise it's always StepInvocation that gest visited instead.
37
+ # Otherwise it's always StepInvocation that gets visited instead.
36
38
  visit_step_result(visitor, first_match(visitor), @multiline_arg, :skipped, nil, nil)
37
39
  end
38
40
 
@@ -61,7 +63,7 @@ module Cucumber
61
63
  end
62
64
 
63
65
  def text_length
64
- @keyword.jlength + @name.jlength + 2 # Add 2 because steps get indented 2 more than scenarios
66
+ @keyword.jlength + @name.jlength + INDENT # Add indent as steps get indented more than scenarios
65
67
  end
66
68
 
67
69
  def backtrace_line
@@ -80,7 +82,8 @@ module Cucumber
80
82
 
81
83
  def matched_cells(cells)
82
84
  cells.select do |cell|
83
- @name.index(delimited(cell.header_cell.value))
85
+ delimited = delimited(cell.header_cell.value)
86
+ @name.index(delimited) || (@multiline_arg && @multiline_arg.has_text?(delimited))
84
87
  end
85
88
  end
86
89
 
@@ -54,9 +54,17 @@ module Cucumber
54
54
  @exception ||= ((failed = @steps.detect {|step| step.exception}) && failed.exception)
55
55
  end
56
56
 
57
+ def failed?
58
+ @steps.detect{|step_invocation| step_invocation.status == :failed}
59
+ end
60
+
61
+ def passed?
62
+ @steps.detect{|step_invocation| step_invocation.status != :passed}.nil?
63
+ end
64
+
57
65
  def to_sexp
58
66
  @steps.map{|step| step.to_sexp}
59
67
  end
60
68
  end
61
69
  end
62
- end
70
+ end
@@ -191,12 +191,20 @@ module Cucumber
191
191
  Table.new(raw_with_replaced_args)
192
192
  end
193
193
 
194
+ def has_text?(text)
195
+ raw.flatten.detect{|cell_value| cell_value.index(text)}
196
+ end
197
+
194
198
  def cells_rows
195
199
  @rows ||= cell_matrix.map do |cell_row|
196
200
  @cells_class.new(self, cell_row)
197
201
  end
198
202
  end
199
203
 
204
+ def headers
205
+ @raw.first
206
+ end
207
+
200
208
  def header_cell(col)
201
209
  cells_rows[0][col]
202
210
  end
@@ -11,8 +11,8 @@ module Cucumber
11
11
  end
12
12
 
13
13
  def matches_scenario_names?(node)
14
- scenario_names = options[:scenario_names] || []
15
- scenario_names.empty? || node.matches_scenario_names?(scenario_names)
14
+ scenario_name_regexps = options[:name_regexps] || []
15
+ scenario_name_regexps.empty? || node.matches_scenario_names?(scenario_name_regexps)
16
16
  end
17
17
 
18
18
  def visit_features(features)
@@ -78,10 +78,11 @@ module Cucumber
78
78
  "with or without the @ prefix.") do |v|
79
79
  @options[:include_tags], @options[:exclude_tags] = *parse_tags(v)
80
80
  end
81
- opts.on("-s SCENARIO", "--scenario SCENARIO",
82
- "Only execute the scenario with the given name. If this option",
83
- "is given more than once, run all the specified scenarios.") do |v|
84
- @options[:scenario_names] << v
81
+ opts.on("-n NAME", "--name NAME",
82
+ "Only execute the feature elements which match part of the given name.",
83
+ "If this option is given more than once, it will match against all the",
84
+ "given names.") do |v|
85
+ @options[:name_regexps] << /#{v}/
85
86
  end
86
87
  opts.on("-e", "--exclude PATTERN", "Don't run feature files matching PATTERN") do |v|
87
88
  @options[:excludes] << v
@@ -334,16 +335,16 @@ Defined profiles in cucumber.yml:
334
335
 
335
336
  def default_options
336
337
  {
337
- :strict => false,
338
- :require => nil,
339
- :lang => 'en',
340
- :dry_run => false,
341
- :formats => {},
342
- :excludes => [],
343
- :include_tags => [],
344
- :exclude_tags => [],
345
- :scenario_names => [],
346
- :diff_enabled => true
338
+ :strict => false,
339
+ :require => nil,
340
+ :lang => 'en',
341
+ :dry_run => false,
342
+ :formats => {},
343
+ :excludes => [],
344
+ :include_tags => [],
345
+ :exclude_tags => [],
346
+ :name_regexps => [],
347
+ :diff_enabled => true
347
348
  }
348
349
  end
349
350
 
@@ -79,7 +79,7 @@ module Cucumber
79
79
  snippet
80
80
  end.compact.uniq
81
81
 
82
- text = "\nYou can implement step definitions for missing steps with these snippets:\n\n"
82
+ text = "\nYou can implement step definitions for undefined steps with these snippets:\n\n"
83
83
  text += snippets.join("\n\n")
84
84
 
85
85
  @io.puts format_string(text, :undefined)
@@ -114,7 +114,7 @@ module Cucumber
114
114
  unless @skip_step
115
115
  step_name = step_match.format_args(lambda{|param| "<span>#{param}</span>"})
116
116
  @builder.div do |div|
117
- div << h("#{keyword} #{step_name}")
117
+ div << h("#{keyword} #{step_name}").gsub(/&lt;span&gt;/, '<span>').gsub(/&lt;\/span&gt;/, '</span>')
118
118
  end
119
119
  end
120
120
  end
@@ -95,7 +95,9 @@ module Cucumber
95
95
  end
96
96
 
97
97
  def visit_examples_name(keyword, name)
98
- @io.puts("\n #{keyword} #{name}")
98
+ names = name.empty? ? [name] : name.split("\n")
99
+ @io.puts("\n #{keyword} #{names[0]}")
100
+ names[1..-1].each {|s| @io.puts " #{s}" }
99
101
  @io.flush
100
102
  @indent = 4
101
103
  end
@@ -105,13 +107,15 @@ module Cucumber
105
107
  end
106
108
 
107
109
  def visit_feature_element_name(keyword, name, file_colon_line, source_indent)
108
- line = " #{keyword} #{name}"
110
+ names = name.empty? ? [name] : name.split("\n")
111
+ line = " #{keyword} #{names[0]}"
109
112
  @io.print(line)
110
113
  if @options[:source]
111
114
  line_comment = " # #{file_colon_line}".indent(source_indent)
112
115
  @io.print(format_string(line_comment, :comment))
113
116
  end
114
117
  @io.puts
118
+ names[1..-1].each {|s| @io.puts " #{s}"}
115
119
  @io.flush
116
120
  end
117
121
 
@@ -126,11 +130,6 @@ module Cucumber
126
130
  @exceptions << exception
127
131
  end
128
132
  return if status != :failed && @in_background ^ background
129
-
130
- # @step_matches ||= []
131
- # return if @step_matches.index(step_match)
132
- # @step_matches << step_match
133
-
134
133
  @status = status
135
134
  super
136
135
  end
@@ -169,7 +168,7 @@ module Cucumber
169
168
 
170
169
  def visit_table_cell_value(value, width, status)
171
170
  status ||= @status || :passed
172
- @io.print(' ' + format_string((value.to_s || '').ljust(width), status) + " #{@delim}")
171
+ @io.print(' ' + format_string((value.to_s || '').ljust(width), status) + ::Term::ANSIColor.reset(" #{@delim}"))
173
172
  @io.flush
174
173
  end
175
174
 
@@ -206,6 +206,21 @@
206
206
  and: Et
207
207
  but: Mais
208
208
  space_after_keyword: true
209
+ "hu":
210
+ name: Hungarian
211
+ native: magyar
212
+ encoding: UTF-8
213
+ feature: Jellemző
214
+ background: Háttér
215
+ scenario: Forgatókönyv
216
+ scenario_outline: Forgatókönyv vázlat
217
+ examples: Példák
218
+ given: Ha
219
+ when: Majd
220
+ then: Akkor
221
+ and: És
222
+ but: De
223
+ space_after_keyword: true
209
224
  "id":
210
225
  name: Indonesian
211
226
  native: Bahasa Indonesia
@@ -264,6 +279,21 @@
264
279
  and: Ir
265
280
  but: Bet
266
281
  space_after_keyword: true
282
+ "lv":
283
+ name: Latvian
284
+ native: latviešu
285
+ encoding: UTF-8
286
+ feature: Funkcionalitāte|Fīča
287
+ background: Konteksts|Situācija
288
+ scenario: Scenārijs
289
+ scenario_outline: Scenārijs pēc parauga
290
+ examples: Piemēri|Paraugs
291
+ given: Kad
292
+ when: Ja
293
+ then: Tad
294
+ and: Un
295
+ but: Bet
296
+ space_after_keyword: true
267
297
  "nl":
268
298
  name: Dutch
269
299
  native: Nederlands
@@ -61,8 +61,8 @@ module Cucumber
61
61
  end
62
62
 
63
63
  def build(filter)
64
- if(filter.nil? || feature_elements.accept?(filter))
65
- background = bg.respond_to?(:build) ? bg.build : nil
64
+ if(filter.nil? || feature_elements.accept?(filter) || (!bg.empty? && filter.accept?(bg)))
65
+ background = bg.respond_to?(:build) ? bg.build : nil
66
66
  Ast::Feature.new(
67
67
  background,
68
68
  comment.build,
@@ -481,12 +481,22 @@ module Cucumber
481
481
  end
482
482
 
483
483
  module Background1
484
+
485
+ def matches_name?(regexp_to_match)
486
+ name.build =~ regexp_to_match
487
+ end
488
+
489
+ def has_tags?(tag_names)
490
+ feature_tags = self.parent.tags
491
+ feature_tags.has_tags?(tag_names)
492
+ end
493
+
484
494
  def build
485
495
  Ast::Background.new(
486
496
  comment.build,
487
497
  background_keyword.line,
488
498
  background_keyword.text_value,
489
- name.text_value,
499
+ name.build,
490
500
  steps.build
491
501
  )
492
502
  end
@@ -522,7 +532,7 @@ module Cucumber
522
532
  r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
523
533
  s0 << r4
524
534
  if r4
525
- r7 = _nt_line_to_eol
535
+ r7 = _nt_lines_to_keyword
526
536
  if r7
527
537
  r6 = r7
528
538
  else
@@ -678,8 +688,8 @@ module Cucumber
678
688
  tags.has_tags?(tag_names) || feature_tags.has_tags?(tag_names)
679
689
  end
680
690
 
681
- def matches_name?(name_to_match)
682
- name.text_value == name_to_match
691
+ def matches_name?(regexp_to_match)
692
+ name.build =~ regexp_to_match
683
693
  end
684
694
 
685
695
  def build(background, filter)
@@ -689,7 +699,7 @@ module Cucumber
689
699
  tags.build,
690
700
  scenario_keyword.line,
691
701
  scenario_keyword.text_value,
692
- name.text_value,
702
+ name.build,
693
703
  steps.build
694
704
  )
695
705
  end
@@ -728,7 +738,7 @@ module Cucumber
728
738
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
729
739
  s0 << r5
730
740
  if r5
731
- r7 = _nt_line_to_eol
741
+ r7 = _nt_lines_to_keyword
732
742
  s0 << r7
733
743
  if r7
734
744
  r8 = _nt_white
@@ -816,8 +826,8 @@ module Cucumber
816
826
  tags.has_tags?(tag_names) || feature_tags.has_tags?(tag_names)
817
827
  end
818
828
 
819
- def matches_name?(name_to_match)
820
- name.text_value == name_to_match
829
+ def matches_name?(regexp_to_match)
830
+ name.build =~ regexp_to_match
821
831
  end
822
832
 
823
833
  def build(background, filter)
@@ -827,7 +837,7 @@ module Cucumber
827
837
  tags.build,
828
838
  scenario_outline_keyword.line,
829
839
  scenario_outline_keyword.text_value,
830
- name.text_value,
840
+ name.build,
831
841
  steps.build,
832
842
  examples_sections.build(filter, self)
833
843
  )
@@ -867,7 +877,7 @@ module Cucumber
867
877
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
868
878
  s0 << r5
869
879
  if r5
870
- r7 = _nt_line_to_eol
880
+ r7 = _nt_lines_to_keyword
871
881
  s0 << r7
872
882
  if r7
873
883
  r8 = _nt_white
@@ -1148,8 +1158,12 @@ module Cucumber
1148
1158
  true
1149
1159
  end
1150
1160
 
1161
+ def matches_name?(regexp_to_match)
1162
+ name.build =~ regexp_to_match
1163
+ end
1164
+
1151
1165
  def build(filter, scenario_outline)
1152
- [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw(filter, scenario_outline)]
1166
+ [examples_keyword.line, examples_keyword.text_value, name.build, table.raw(filter, scenario_outline)]
1153
1167
  end
1154
1168
  end
1155
1169
 
@@ -1189,7 +1203,7 @@ module Cucumber
1189
1203
  r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
1190
1204
  s0 << r4
1191
1205
  if r4
1192
- r7 = _nt_line_to_eol
1206
+ r7 = _nt_lines_to_keyword
1193
1207
  if r7
1194
1208
  r6 = r7
1195
1209
  else
@@ -1305,6 +1319,192 @@ module Cucumber
1305
1319
  return r0
1306
1320
  end
1307
1321
 
1322
+ module LineToKeyword0
1323
+ end
1324
+
1325
+ module LineToKeyword1
1326
+ def white
1327
+ elements[0]
1328
+ end
1329
+
1330
+ def text
1331
+ elements[1]
1332
+ end
1333
+ end
1334
+
1335
+ module LineToKeyword2
1336
+ def build
1337
+ text.text_value.strip
1338
+ end
1339
+ end
1340
+
1341
+ def _nt_line_to_keyword
1342
+ start_index = index
1343
+ if node_cache[:line_to_keyword].has_key?(index)
1344
+ cached = node_cache[:line_to_keyword][index]
1345
+ @index = cached.interval.end if cached
1346
+ return cached
1347
+ end
1348
+
1349
+ i0, s0 = index, []
1350
+ r1 = _nt_white
1351
+ s0 << r1
1352
+ if r1
1353
+ s2, i2 = [], index
1354
+ loop do
1355
+ i3, s3 = index, []
1356
+ i4 = index
1357
+ r5 = _nt_step_keyword
1358
+ if r5
1359
+ r4 = nil
1360
+ else
1361
+ self.index = i4
1362
+ r4 = instantiate_node(SyntaxNode,input, index...index)
1363
+ end
1364
+ s3 << r4
1365
+ if r4
1366
+ i6 = index
1367
+ r7 = _nt_scenario_keyword
1368
+ if r7
1369
+ r6 = nil
1370
+ else
1371
+ self.index = i6
1372
+ r6 = instantiate_node(SyntaxNode,input, index...index)
1373
+ end
1374
+ s3 << r6
1375
+ if r6
1376
+ i8 = index
1377
+ r9 = _nt_scenario_outline_keyword
1378
+ if r9
1379
+ r8 = nil
1380
+ else
1381
+ self.index = i8
1382
+ r8 = instantiate_node(SyntaxNode,input, index...index)
1383
+ end
1384
+ s3 << r8
1385
+ if r8
1386
+ i10 = index
1387
+ r11 = _nt_table
1388
+ if r11
1389
+ r10 = nil
1390
+ else
1391
+ self.index = i10
1392
+ r10 = instantiate_node(SyntaxNode,input, index...index)
1393
+ end
1394
+ s3 << r10
1395
+ if r10
1396
+ i12 = index
1397
+ r13 = _nt_tag
1398
+ if r13
1399
+ r12 = nil
1400
+ else
1401
+ self.index = i12
1402
+ r12 = instantiate_node(SyntaxNode,input, index...index)
1403
+ end
1404
+ s3 << r12
1405
+ if r12
1406
+ i14 = index
1407
+ r15 = _nt_comment_line
1408
+ if r15
1409
+ r14 = nil
1410
+ else
1411
+ self.index = i14
1412
+ r14 = instantiate_node(SyntaxNode,input, index...index)
1413
+ end
1414
+ s3 << r14
1415
+ if r14
1416
+ i16 = index
1417
+ r17 = _nt_eol
1418
+ if r17
1419
+ r16 = nil
1420
+ else
1421
+ self.index = i16
1422
+ r16 = instantiate_node(SyntaxNode,input, index...index)
1423
+ end
1424
+ s3 << r16
1425
+ if r16
1426
+ if index < input_length
1427
+ r18 = instantiate_node(SyntaxNode,input, index...(index + 1))
1428
+ @index += 1
1429
+ else
1430
+ terminal_parse_failure("any character")
1431
+ r18 = nil
1432
+ end
1433
+ s3 << r18
1434
+ end
1435
+ end
1436
+ end
1437
+ end
1438
+ end
1439
+ end
1440
+ end
1441
+ if s3.last
1442
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
1443
+ r3.extend(LineToKeyword0)
1444
+ else
1445
+ self.index = i3
1446
+ r3 = nil
1447
+ end
1448
+ if r3
1449
+ s2 << r3
1450
+ else
1451
+ break
1452
+ end
1453
+ end
1454
+ if s2.empty?
1455
+ self.index = i2
1456
+ r2 = nil
1457
+ else
1458
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
1459
+ end
1460
+ s0 << r2
1461
+ end
1462
+ if s0.last
1463
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
1464
+ r0.extend(LineToKeyword1)
1465
+ r0.extend(LineToKeyword2)
1466
+ else
1467
+ self.index = i0
1468
+ r0 = nil
1469
+ end
1470
+
1471
+ node_cache[:line_to_keyword][start_index] = r0
1472
+
1473
+ return r0
1474
+ end
1475
+
1476
+ module LinesToKeyword0
1477
+
1478
+ def build
1479
+ elements.map{|s| s.build}.join("\n")
1480
+ end
1481
+ end
1482
+
1483
+ def _nt_lines_to_keyword
1484
+ start_index = index
1485
+ if node_cache[:lines_to_keyword].has_key?(index)
1486
+ cached = node_cache[:lines_to_keyword][index]
1487
+ @index = cached.interval.end if cached
1488
+ return cached
1489
+ end
1490
+
1491
+ s0, i0 = [], index
1492
+ loop do
1493
+ r1 = _nt_line_to_keyword
1494
+ if r1
1495
+ s0 << r1
1496
+ else
1497
+ break
1498
+ end
1499
+ end
1500
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
1501
+ r0.extend(LinesToKeyword0)
1502
+
1503
+ node_cache[:lines_to_keyword][start_index] = r0
1504
+
1505
+ return r0
1506
+ end
1507
+
1308
1508
  module PyString0
1309
1509
  end
1310
1510