gherkin 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitattributes +1 -0
- data/History.txt +18 -0
- data/README.rdoc +4 -1
- data/Rakefile +4 -2
- data/VERSION.yml +1 -1
- data/bin/gherkin +1 -1
- data/dotnet/.gitignore +13 -0
- data/features/feature_parser.feature +22 -2
- data/features/native_lexer.feature +1 -1
- data/features/parser_with_native_lexer.feature +1 -1
- data/features/step_definitions/gherkin_steps.rb +2 -6
- data/features/step_definitions/pretty_printer_steps.rb +2 -3
- data/features/steps_parser.feature +1 -1
- data/gherkin.gemspec +53 -24
- data/java/Gherkin.iml +2 -4
- data/java/build.xml +3 -0
- data/java/src/gherkin/FixJava.java +6 -3
- data/java/src/gherkin/I18nLexer.java +48 -0
- data/java/src/gherkin/Listener.java +3 -1
- data/java/src/gherkin/Main.java +17 -0
- data/java/src/gherkin/Parser.java +9 -3
- data/java/src/gherkin/formatter/Argument.java +39 -0
- data/java/src/gherkin/formatter/ArgumentFormat.java +17 -0
- data/java/src/gherkin/formatter/Colors.java +7 -0
- data/java/src/gherkin/formatter/Formatter.java +15 -0
- data/java/src/gherkin/formatter/PrettyFormatter.java +219 -0
- data/java/src/gherkin/parser/StateMachineReader.java +8 -3
- data/java/test/gherkin/formatter/ArgumentTest.java +17 -0
- data/lib/gherkin/csharp_lexer.rb +15 -0
- data/lib/gherkin/format/argument.rb +35 -0
- data/lib/gherkin/format/monochrome_format.rb +9 -0
- data/lib/gherkin/i18n.rb +22 -0
- data/lib/gherkin/i18n.yml +34 -20
- data/lib/gherkin/i18n_lexer.rb +57 -13
- data/lib/gherkin/lexer.rb +9 -18
- data/lib/gherkin/parser.rb +3 -3
- data/lib/gherkin/parser/meta.txt +5 -4
- data/lib/gherkin/parser/root.txt +11 -9
- data/lib/gherkin/parser/steps.txt +4 -3
- data/lib/gherkin/rb_parser.rb +13 -5
- data/lib/gherkin/tools/colors.rb +119 -0
- data/lib/gherkin/tools/files.rb +6 -1
- data/lib/gherkin/tools/pretty_listener.rb +115 -23
- data/ragel/lexer.c.rl.erb +67 -51
- data/ragel/lexer.csharp.rl.erb +240 -0
- data/ragel/lexer.java.rl.erb +27 -18
- data/ragel/lexer.rb.rl.erb +17 -17
- data/ragel/lexer_common.rl.erb +8 -8
- data/spec/gherkin/c_lexer_spec.rb +4 -4
- data/spec/gherkin/csharp_lexer_spec.rb +20 -0
- data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
- data/spec/gherkin/fixtures/complex.feature +2 -0
- data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
- data/spec/gherkin/fixtures/i18n_fr.feature +1 -0
- data/spec/gherkin/fixtures/i18n_no.feature +1 -0
- data/spec/gherkin/fixtures/i18n_zh-CN.feature +1 -0
- data/spec/gherkin/format/argument_spec.rb +28 -0
- data/spec/gherkin/i18n_lexer_spec.rb +4 -4
- data/spec/gherkin/i18n_spec.rb +31 -23
- data/spec/gherkin/java_lexer_spec.rb +4 -3
- data/spec/gherkin/parser_spec.rb +5 -0
- data/spec/gherkin/rb_lexer_spec.rb +4 -2
- data/spec/gherkin/sexp_recorder.rb +1 -1
- data/spec/gherkin/shared/lexer_spec.rb +169 -60
- data/spec/gherkin/shared/py_string_spec.rb +6 -0
- data/spec/gherkin/shared/row_spec.rb +107 -0
- data/spec/gherkin/shared/tags_spec.rb +1 -1
- data/spec/gherkin/tools/colors_spec.rb +19 -0
- data/spec/gherkin/tools/pretty_listener_spec.rb +147 -0
- data/spec/spec_helper.rb +31 -7
- data/tasks/compile.rake +81 -7
- data/tasks/ragel_task.rb +6 -4
- data/tasks/rspec.rake +2 -2
- metadata +104 -41
- data/lib/gherkin/java_lexer.rb +0 -10
- data/spec/gherkin/shared/table_spec.rb +0 -97
@@ -0,0 +1,17 @@
|
|
1
|
+
package gherkin.formatter;
|
2
|
+
|
3
|
+
import org.junit.Test;
|
4
|
+
|
5
|
+
import java.io.UnsupportedEncodingException;
|
6
|
+
|
7
|
+
import static org.junit.Assert.assertEquals;
|
8
|
+
|
9
|
+
public class ArgumentTest {
|
10
|
+
@Test
|
11
|
+
public void shouldFormatAscii() throws UnsupportedEncodingException {
|
12
|
+
assertEquals("I have [[[[åtte] cukes i [[[[bøtta]", Argument.format("I have åtte cukes i bøtta", new ArgumentFormat("[[[[", "]"),
|
13
|
+
new Argument(7, "åtte"),
|
14
|
+
new Argument(21, "bøtta")
|
15
|
+
));
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'Gherkin.dll'
|
2
|
+
|
3
|
+
module Gherkin
|
4
|
+
module CSharpLexer
|
5
|
+
def self.[](i18n_language)
|
6
|
+
i18n_lexer_class_name = i18n_language.gsub(/[\s-]/, '').capitalize
|
7
|
+
puts "In C# lexer: #{i18n_lexer_class_name}"
|
8
|
+
Gherkin::ILexer
|
9
|
+
puts "OK1"
|
10
|
+
l = Gherkin::Lexer.__send__(i18n_lexer_class_name)
|
11
|
+
puts "OK2"
|
12
|
+
l
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Gherkin
|
2
|
+
module Format
|
3
|
+
class Argument
|
4
|
+
attr_reader :byte_offset, :val
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def new(byte_offset, val)
|
8
|
+
if defined?(JRUBY_VERSION)
|
9
|
+
require 'gherkin.jar'
|
10
|
+
Java::GherkinFormatter::Argument.new(byte_offset, val)
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(byte_offset, val)
|
18
|
+
@byte_offset, @val = byte_offset, val
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.format(string, argument_format, arguments)
|
22
|
+
s = string.dup
|
23
|
+
offset = past_offset = 0
|
24
|
+
arguments.each do |arg|
|
25
|
+
next if arg.byte_offset.nil? || arg.byte_offset < past_offset
|
26
|
+
replacement = argument_format.format_argument(arg.val)
|
27
|
+
s[arg.byte_offset + offset, arg.val.length] = replacement
|
28
|
+
offset += replacement.unpack("U*").length - arg.val.unpack("U*").length
|
29
|
+
past_offset = arg.byte_offset + arg.val.length
|
30
|
+
end
|
31
|
+
s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/gherkin/i18n.rb
CHANGED
@@ -18,6 +18,23 @@ module Gherkin
|
|
18
18
|
def languages
|
19
19
|
@languages ||= {}
|
20
20
|
end
|
21
|
+
|
22
|
+
# Returns all keyword translations and aliases of +keywords+, escaped and joined with <tt>|</tt>.
|
23
|
+
# This method is convenient for editor support and syntax highlighting engines for Gherkin, where
|
24
|
+
# there is typically a code generation tool to generate regular expressions for recognising the
|
25
|
+
# various I18n translations of Gherkin's keywords.
|
26
|
+
#
|
27
|
+
# The +keywords+ arguments can be one of <tt>:feature</tt>, <tt>:background</tt>, <tt>:scenario</tt>,
|
28
|
+
# <tt>:scenario_outline</tt>, <tt>:examples</tt>, <tt>:step</tt>.
|
29
|
+
def keyword_regexp(*keywords)
|
30
|
+
unique_keywords = all.map do |lang|
|
31
|
+
keywords.map do |keyword|
|
32
|
+
lang.__send__("#{keyword}_keywords".to_sym)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
unique_keywords.flatten.compact.sort.reverse.uniq.join('|').gsub(/\*/, '\*')
|
37
|
+
end
|
21
38
|
end
|
22
39
|
|
23
40
|
attr_reader :key
|
@@ -69,12 +86,17 @@ module Gherkin
|
|
69
86
|
%w{given when then and but}.map{|key| keywords(key, true)}.flatten.uniq
|
70
87
|
end
|
71
88
|
|
89
|
+
def gwt_keywords
|
90
|
+
%w{given when then}.map{|key| keywords(key, true)}.flatten.uniq
|
91
|
+
end
|
92
|
+
|
72
93
|
def keywords(key, space=false)
|
73
94
|
raise "No #{key} in #{@keywords.inspect}" if @keywords[key].nil?
|
74
95
|
@keywords[key].split('|').map{|kw| space ? keyword_space(kw) : kw}
|
75
96
|
end
|
76
97
|
|
77
98
|
def adverbs
|
99
|
+
# TODO: looks very similar to #step_keywords. Lose this? Where is it used from?
|
78
100
|
%w{given when then and but}.map{|keyword| @keywords[keyword].split('|').map{|w| w.gsub(/[\s<']/, '')}}.flatten
|
79
101
|
end
|
80
102
|
|
data/lib/gherkin/i18n.yml
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
#
|
3
|
-
#
|
2
|
+
#
|
3
|
+
# We use ISO 639-1 (language) and ISO 3166 alpha-2 (region - if appliccable):
|
4
|
+
# http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
5
|
+
# http://en.wikipedia.org/wiki/ISO_3166-1
|
4
6
|
#
|
5
7
|
# If you want several aliases for a keyword, just separate them
|
6
8
|
# with a | character. Make sure there are no ambiguities in the
|
7
9
|
# keywords.
|
8
10
|
#
|
11
|
+
# If you do *not* want a trailing space after a keyword, end it with a < character.
|
12
|
+
# (See Chinese for examples).
|
13
|
+
#
|
9
14
|
"en":
|
10
15
|
name: English
|
11
16
|
native: English
|
@@ -20,10 +25,6 @@
|
|
20
25
|
and: "*|And"
|
21
26
|
but: "*|But"
|
22
27
|
|
23
|
-
# Please help us keeping the languages below uptodate. The parsers for a language
|
24
|
-
# that is missing a keyword will expect the English word until the missing word(s)
|
25
|
-
# are added.
|
26
|
-
#
|
27
28
|
# Please keep the grammars in alphabetical order by name from here and down.
|
28
29
|
|
29
30
|
"ar":
|
@@ -52,20 +53,20 @@
|
|
52
53
|
then: "*|То"
|
53
54
|
and: "*|И"
|
54
55
|
but: "*|Но"
|
55
|
-
"
|
56
|
+
"ca":
|
56
57
|
name: Catalan
|
57
58
|
native: català
|
58
59
|
background: Rerefons|Antecedents
|
59
|
-
feature: Característica
|
60
|
+
feature: Característica|Funcionalitat
|
60
61
|
scenario: Escenari
|
61
62
|
scenario_outline: Esquema de l'escenari
|
62
63
|
examples: Exemples
|
63
|
-
given: "*|Donat|Donada"
|
64
|
+
given: "*|Donat|Donada|Atès|Atesa"
|
64
65
|
when: "*|Quan"
|
65
|
-
then: "*|Aleshores"
|
66
|
+
then: "*|Aleshores|Cal"
|
66
67
|
and: "*|I"
|
67
68
|
but: "*|Però"
|
68
|
-
"cy":
|
69
|
+
"cy-GB":
|
69
70
|
name: Welsh
|
70
71
|
native: Cymraeg
|
71
72
|
background: Cefndir
|
@@ -112,7 +113,7 @@
|
|
112
113
|
scenario: Szenario
|
113
114
|
scenario_outline: Szenariogrundriss
|
114
115
|
examples: Beispiele
|
115
|
-
given: "*|Gegeben sei"
|
116
|
+
given: "*|Angenommen|Gegeben sei"
|
116
117
|
when: "*|Wenn"
|
117
118
|
then: "*|Dann"
|
118
119
|
and: "*|Und"
|
@@ -143,6 +144,19 @@
|
|
143
144
|
then: "*|DEN"
|
144
145
|
and: "*|AN"
|
145
146
|
but: "*|BUT"
|
147
|
+
"en-Scouse":
|
148
|
+
name: Scouse
|
149
|
+
native: Scouse
|
150
|
+
feature: Feature
|
151
|
+
background: "Dis is what went down"
|
152
|
+
scenario: "The thing of it is"
|
153
|
+
scenario_outline: "Wharrimean is"
|
154
|
+
examples: Examples
|
155
|
+
given: "*|Givun|Youse know when youse got"
|
156
|
+
when: "*|Wun|Youse know like when"
|
157
|
+
then: "*|Dun|Den youse gotta"
|
158
|
+
and: "*|An"
|
159
|
+
but: "*|Buh"
|
146
160
|
"en-tx":
|
147
161
|
name: Texan
|
148
162
|
native: Texan
|
@@ -294,11 +308,11 @@
|
|
294
308
|
scenario: 시나리오
|
295
309
|
scenario_outline: 시나리오 개요
|
296
310
|
examples: 예
|
297
|
-
given: "
|
298
|
-
when: "
|
311
|
+
given: "*|조건<|먼저<"
|
312
|
+
when: "*|만일<|만약<"
|
299
313
|
then: "*|그러면<"
|
300
314
|
and: "*|그리고<"
|
301
|
-
but: "
|
315
|
+
but: "*|하지만<|단<"
|
302
316
|
"lt":
|
303
317
|
name: Lithuanian
|
304
318
|
native: lietuvių kalba
|
@@ -390,7 +404,7 @@
|
|
390
404
|
then: "*|Atunci"
|
391
405
|
and: "*|Si"
|
392
406
|
but: "*|Dar"
|
393
|
-
"
|
407
|
+
"ro-RO":
|
394
408
|
name: Romanian (diacritical)
|
395
409
|
native: română (diacritical)
|
396
410
|
background: Condiţii
|
@@ -416,7 +430,7 @@
|
|
416
430
|
then: "*|То"
|
417
431
|
and: "*|И|К тому же"
|
418
432
|
but: "*|Но|А"
|
419
|
-
"
|
433
|
+
"sv":
|
420
434
|
name: Swedish
|
421
435
|
native: Svenska
|
422
436
|
feature: Egenskap
|
@@ -443,8 +457,8 @@
|
|
443
457
|
and: "*|A"
|
444
458
|
but: "*|Ale"
|
445
459
|
"sr-Latn":
|
446
|
-
name:
|
447
|
-
native:
|
460
|
+
name: Serbian (Latin)
|
461
|
+
native: Srpski (Latinica)
|
448
462
|
feature: Funkcionalnost|Mogućnost|Mogucnost|Osobina
|
449
463
|
background: Kontekst|Osnova|Pozadina
|
450
464
|
scenario: Scenario|Primer
|
@@ -455,7 +469,7 @@
|
|
455
469
|
then: "*|Onda"
|
456
470
|
and: "*|I"
|
457
471
|
but: "*|Ali"
|
458
|
-
"sr":
|
472
|
+
"sr-Cyrl":
|
459
473
|
name: Serbian
|
460
474
|
native: Српски
|
461
475
|
feature: Функционалност|Могућност|Особина
|
data/lib/gherkin/i18n_lexer.rb
CHANGED
@@ -1,29 +1,73 @@
|
|
1
|
-
require 'gherkin/lexer'
|
2
1
|
require 'gherkin/i18n'
|
3
2
|
|
4
3
|
module Gherkin
|
4
|
+
I18nLexerNotFound = Class.new(LoadError)
|
5
|
+
LexingError = Class.new(StandardError)
|
6
|
+
|
5
7
|
# The main entry point to lexing Gherkin source.
|
6
8
|
class I18nLexer
|
7
9
|
LANGUAGE_PATTERN = /language\s*:\s*(.*)/ #:nodoc:
|
8
10
|
|
9
|
-
attr_reader :
|
11
|
+
attr_reader :i18n_language
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def new(parser, force_ruby)
|
15
|
+
if !force_ruby && defined?(JRUBY_VERSION)
|
16
|
+
require 'gherkin.jar'
|
17
|
+
Java::Gherkin::I18nLexer.new(parser)
|
18
|
+
else
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def lexer_class(i18n_lang, force_ruby)
|
24
|
+
begin
|
25
|
+
if force_ruby
|
26
|
+
rb[i18n_lang]
|
27
|
+
else
|
28
|
+
begin
|
29
|
+
c[i18n_lang]
|
30
|
+
rescue NameError, LoadError => e
|
31
|
+
warn("WARNING: #{e.message}. Reverting to Ruby lexer.")
|
32
|
+
rb[i18n_lang]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
rescue LoadError => e
|
36
|
+
raise I18nLexerNotFound, "No lexer was found for #{i18n_lang} (#{e.message}). Supported languages are listed in gherkin/i18n.yml."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def i18n_language(source)
|
41
|
+
line_one = source.split(/\n/)[0]
|
42
|
+
match = LANGUAGE_PATTERN.match(line_one)
|
43
|
+
I18n.get(match ? match[1] : 'en').key
|
44
|
+
end
|
45
|
+
|
46
|
+
def c
|
47
|
+
require 'gherkin/c_lexer'
|
48
|
+
CLexer
|
49
|
+
end
|
50
|
+
|
51
|
+
def csharp
|
52
|
+
require 'gherkin/csharp_lexer'
|
53
|
+
CSharpLexer
|
54
|
+
end
|
10
55
|
|
11
|
-
|
56
|
+
def rb
|
57
|
+
require 'gherkin/rb_lexer'
|
58
|
+
RbLexer
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def initialize(parser, force_ruby)
|
12
63
|
@parser = parser
|
64
|
+
@force_ruby = force_ruby
|
13
65
|
end
|
14
66
|
|
15
67
|
def scan(source)
|
16
|
-
@
|
17
|
-
delegate =
|
68
|
+
@i18n_language = self.class.i18n_language(source)
|
69
|
+
delegate = self.class.lexer_class(@i18n_language, @force_ruby).new(@parser)
|
18
70
|
delegate.scan(source)
|
19
71
|
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def lang(source)
|
24
|
-
line_one = source.split(/\n/)[0]
|
25
|
-
match = LANGUAGE_PATTERN.match(line_one)
|
26
|
-
I18n.get(match ? match[1] : 'en')
|
27
|
-
end
|
28
72
|
end
|
29
73
|
end
|
data/lib/gherkin/lexer.rb
CHANGED
@@ -1,24 +1,15 @@
|
|
1
1
|
module Gherkin
|
2
2
|
module Lexer
|
3
|
-
I18nLexerNotFound = Class.new(LoadError)
|
4
|
-
LexingError = Class.new(StandardError)
|
5
3
|
|
6
4
|
class << self
|
7
5
|
def [](i18n_lang)
|
8
6
|
begin
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
begin
|
16
|
-
c[i18n_lang]
|
17
|
-
rescue NameError, LoadError => e
|
18
|
-
warn("WARNING: #{e.message}. Reverting to Ruby lexer.") unless defined?(@warned)
|
19
|
-
@warned = true
|
20
|
-
rb[i18n_lang]
|
21
|
-
end
|
7
|
+
begin
|
8
|
+
c[i18n_lang]
|
9
|
+
rescue NameError, LoadError => e
|
10
|
+
raise("WARNING: #{e.message}. Reverting to Ruby lexer.") unless defined?(@warned)
|
11
|
+
@warned = true
|
12
|
+
rb[i18n_lang]
|
22
13
|
end
|
23
14
|
rescue LoadError => e
|
24
15
|
raise I18nLexerNotFound, "No lexer was found for #{i18n_lang} (#{e.message}). Supported languages are listed in gherkin/i18n.yml."
|
@@ -30,9 +21,9 @@ module Gherkin
|
|
30
21
|
CLexer
|
31
22
|
end
|
32
23
|
|
33
|
-
def
|
34
|
-
require 'gherkin/
|
35
|
-
|
24
|
+
def csharp
|
25
|
+
require 'gherkin/csharp_lexer'
|
26
|
+
CSharpLexer
|
36
27
|
end
|
37
28
|
|
38
29
|
def rb
|
data/lib/gherkin/parser.rb
CHANGED
@@ -6,13 +6,13 @@ module Gherkin
|
|
6
6
|
end
|
7
7
|
|
8
8
|
class Parser
|
9
|
-
def self.new(listener, raise_on_error=false,
|
9
|
+
def self.new(listener, raise_on_error=false, machine_name='root')
|
10
10
|
if defined?(JRUBY_VERSION)
|
11
11
|
require 'gherkin.jar'
|
12
|
-
Java::Gherkin::Parser.new(listener, raise_on_error,
|
12
|
+
Java::Gherkin::Parser.new(listener, raise_on_error, machine_name)
|
13
13
|
else
|
14
14
|
require 'gherkin/rb_parser'
|
15
|
-
Gherkin::RbParser.new(listener, raise_on_error,
|
15
|
+
Gherkin::RbParser.new(listener, raise_on_error, machine_name)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/lib/gherkin/parser/meta.txt
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
| | feature | background | scenario | scenario_outline | examples | step |
|
2
|
-
| meta | E | E | E | E | E | E | E | E | comment | tag |
|
3
|
-
| comment | pop() | pop() | pop() | pop() | pop() | pop() | pop() | pop() | pop() | tag |
|
4
|
-
| tag | pop() | E | pop() | pop() | pop() | E | E | E | E | tag |
|
1
|
+
| | feature | background | scenario | scenario_outline | examples | step | row | py_string | eof | comment | tag |
|
2
|
+
| meta | E | E | E | E | E | E | E | E | eof | comment | tag |
|
3
|
+
| comment | pop() | pop() | pop() | pop() | pop() | pop() | pop() | pop() | eof | pop() | tag |
|
4
|
+
| tag | pop() | E | pop() | pop() | pop() | E | E | E | E | E | tag |
|
5
|
+
| eof | E | E | E | E | E | E | E | E | E | E | E |
|
data/lib/gherkin/parser/root.txt
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
| | feature | background | scenario | scenario_outline | examples | step
|
2
|
-
| root | feature | E | E | E | E | E
|
3
|
-
| feature | E | background | scenario | scenario_outline | E | E
|
4
|
-
| step | E | E | scenario | scenario_outline |
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
| | feature | background | scenario | scenario_outline | examples | step | row | py_string | eof | comment | tag |
|
2
|
+
| root | feature | E | E | E | E | E | E | E | eof | push(meta) | push(meta) |
|
3
|
+
| feature | E | background | scenario | scenario_outline | E | E | E | E | eof | push(meta) | push(meta) |
|
4
|
+
| step | E | E | scenario | scenario_outline | E | step | step | step | eof | push(meta) | push(meta) |
|
5
|
+
| outline_step | E | E | scenario | scenario_outline | examples | outline_step | outline_step | outline_step | eof | push(meta) | push(meta) |
|
6
|
+
| background | E | E | scenario | scenario_outline | E | step | E | E | eof | push(meta) | push(meta) |
|
7
|
+
| scenario | E | E | scenario | scenario_outline | E | step | E | E | eof | push(meta) | push(meta) |
|
8
|
+
| scenario_outline | E | E | E | E | E | outline_step | E | E | eof | push(meta) | push(meta) |
|
9
|
+
| examples | E | E | E | E | E | E | examples_table | E | eof | push(meta) | push(meta) |
|
10
|
+
| examples_table | E | E | scenario | scenario_outline | examples | E | examples_table | E | eof | push(meta) | push(meta) |
|
11
|
+
| eof | E | E | E | E | E | E | E | E | E | E | E |
|
@@ -1,3 +1,4 @@
|
|
1
|
-
| | feature | background | scenario | scenario_outline | examples | step |
|
2
|
-
| steps | E | E | E | E | E | step | E
|
3
|
-
| step | E | E | E | E | E | step |
|
1
|
+
| | feature | background | scenario | scenario_outline | examples | step | row | py_string | eof | comment | tag |
|
2
|
+
| steps | E | E | E | E | E | step | E | E | eof | E | E |
|
3
|
+
| step | E | E | E | E | E | step | step | steps | eof | E | E |
|
4
|
+
| eof | E | E | E | E | E | E | E | E | E | E | E |
|