cucumber 0.3.0 → 0.3.1

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