gherkin 0.0.4-i386-mswin32
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.
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +66 -0
- data/Rakefile +49 -0
- data/VERSION.yml +4 -0
- data/bin/gherkin +10 -0
- data/cucumber.yml +3 -0
- data/features/feature_parser.feature +206 -0
- data/features/native_lexer.feature +19 -0
- data/features/parser_with_native_lexer.feature +205 -0
- data/features/pretty_printer.feature +14 -0
- data/features/step_definitions/gherkin_steps.rb +34 -0
- data/features/step_definitions/pretty_printer_steps.rb +56 -0
- data/features/steps_parser.feature +46 -0
- data/features/support/env.rb +33 -0
- data/gherkin.gemspec +180 -0
- data/java/.gitignore +2 -0
- data/java/Gherkin.iml +24 -0
- data/java/build.xml +13 -0
- data/java/src/gherkin/FixJava.java +34 -0
- data/java/src/gherkin/Lexer.java +5 -0
- data/java/src/gherkin/LexingError.java +7 -0
- data/java/src/gherkin/Listener.java +27 -0
- data/java/src/gherkin/ParseError.java +22 -0
- data/java/src/gherkin/Parser.java +185 -0
- data/java/src/gherkin/lexer/.gitignore +1 -0
- data/java/src/gherkin/parser/StateMachineReader.java +62 -0
- data/lib/.gitignore +4 -0
- data/lib/gherkin.rb +2 -0
- data/lib/gherkin/c_lexer.rb +10 -0
- data/lib/gherkin/core_ext/array.rb +5 -0
- data/lib/gherkin/i18n.yml +535 -0
- data/lib/gherkin/i18n_lexer.rb +29 -0
- data/lib/gherkin/java_lexer.rb +10 -0
- data/lib/gherkin/lexer.rb +43 -0
- data/lib/gherkin/parser.rb +19 -0
- data/lib/gherkin/parser/meta.txt +4 -0
- data/lib/gherkin/parser/root.txt +9 -0
- data/lib/gherkin/parser/steps.txt +3 -0
- data/lib/gherkin/rb_lexer.rb +10 -0
- data/lib/gherkin/rb_lexer/.gitignore +1 -0
- data/lib/gherkin/rb_lexer/README.rdoc +8 -0
- data/lib/gherkin/rb_parser.rb +117 -0
- data/lib/gherkin/tools/pretty_printer.rb +83 -0
- data/nativegems.sh +5 -0
- data/ragel/i18n/.gitignore +1 -0
- data/ragel/lexer.c.rl.erb +401 -0
- data/ragel/lexer.java.rl.erb +200 -0
- data/ragel/lexer.rb.rl.erb +171 -0
- data/ragel/lexer_common.rl.erb +46 -0
- data/spec/gherkin/c_lexer_spec.rb +21 -0
- data/spec/gherkin/fixtures/1.feature +8 -0
- data/spec/gherkin/fixtures/complex.feature +43 -0
- data/spec/gherkin/fixtures/i18n_fr.feature +13 -0
- data/spec/gherkin/fixtures/i18n_no.feature +6 -0
- data/spec/gherkin/fixtures/i18n_zh-CN.feature +8 -0
- data/spec/gherkin/fixtures/simple.feature +3 -0
- data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
- data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
- data/spec/gherkin/i18n_spec.rb +57 -0
- data/spec/gherkin/java_lexer_spec.rb +20 -0
- data/spec/gherkin/parser_spec.rb +28 -0
- data/spec/gherkin/rb_lexer_spec.rb +18 -0
- data/spec/gherkin/sexp_recorder.rb +29 -0
- data/spec/gherkin/shared/lexer_spec.rb +433 -0
- data/spec/gherkin/shared/py_string_spec.rb +124 -0
- data/spec/gherkin/shared/table_spec.rb +97 -0
- data/spec/gherkin/shared/tags_spec.rb +50 -0
- data/spec/spec_helper.rb +53 -0
- data/tasks/bench.rake +193 -0
- data/tasks/bench/feature_builder.rb +49 -0
- data/tasks/bench/generated/.gitignore +1 -0
- data/tasks/bench/null_listener.rb +4 -0
- data/tasks/compile.rake +70 -0
- data/tasks/cucumber.rake +20 -0
- data/tasks/ragel_task.rb +83 -0
- data/tasks/rdoc.rake +12 -0
- data/tasks/rspec.rake +15 -0
- metadata +214 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
3
|
+
|
4
|
+
module Gherkin
|
5
|
+
module Lexer
|
6
|
+
shared_examples_for "a Gherkin lexer lexing py_strings" do
|
7
|
+
|
8
|
+
def ps(content)
|
9
|
+
'"""%s"""' % ("\n" + content + "\n")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should provide the amount of indentation of the triple quotes to the listener" do
|
13
|
+
str = <<EOS
|
14
|
+
Feature: some feature
|
15
|
+
Scenario: some scenario
|
16
|
+
Given foo
|
17
|
+
"""
|
18
|
+
Hello
|
19
|
+
Goodbye
|
20
|
+
"""
|
21
|
+
Then bar
|
22
|
+
EOS
|
23
|
+
@listener.should_receive(:py_string).with(" Hello\nGoodbye", 4)
|
24
|
+
@lexer.scan(str)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should parse a simple py_string" do
|
28
|
+
@listener.should_receive(:py_string).with("I am a py_string", 1)
|
29
|
+
@lexer.scan ps("I am a py_string")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should parse an empty py_string" do
|
33
|
+
@listener.should_receive(:py_string).with("", 4)
|
34
|
+
@lexer.scan("Feature: Hi\nScenario: Hi\nGiven a step\n\"\"\"\n\"\"\"")
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should treat a string containing only newlines as only newlines" do
|
38
|
+
py_string = <<EOS
|
39
|
+
"""
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
"""
|
44
|
+
EOS
|
45
|
+
@listener.should_receive(:py_string).with("\n\n", 1)
|
46
|
+
@lexer.scan(py_string)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should parse content separated by two newlines" do
|
50
|
+
@lexer.scan ps("A\n\nB")
|
51
|
+
@listener.to_sexp.should == [
|
52
|
+
[:py_string, "A\n\nB", 1],
|
53
|
+
]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should parse a multiline string" do
|
57
|
+
@listener.should_receive(:py_string).with("A\nB\nC\nD", 1)
|
58
|
+
@lexer.scan ps("A\nB\nC\nD")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should ignore unescaped quotes inside the string delimeters" do
|
62
|
+
@listener.should_receive(:py_string).with("What does \"this\" mean?", 1)
|
63
|
+
@lexer.scan ps('What does "this" mean?')
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should preserve whitespace within the triple quotes" do
|
67
|
+
str = <<EOS
|
68
|
+
"""
|
69
|
+
Line one
|
70
|
+
Line two
|
71
|
+
"""
|
72
|
+
EOS
|
73
|
+
@listener.should_receive(:py_string).with(" Line one\nLine two", 1)
|
74
|
+
@lexer.scan(str)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should preserve tabs within the content" do
|
78
|
+
@listener.should_receive(:py_string).with("I have\tsome tabs\nInside\t\tthe content", 1)
|
79
|
+
@lexer.scan ps("I have\tsome tabs\nInside\t\tthe content")
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should handle complex py_strings" do
|
83
|
+
py_string = <<EOS
|
84
|
+
# Feature comment
|
85
|
+
@one
|
86
|
+
Feature: Sample
|
87
|
+
|
88
|
+
@two @three
|
89
|
+
Scenario: Missing
|
90
|
+
Given missing
|
91
|
+
|
92
|
+
1 scenario (1 passed)
|
93
|
+
1 step (1 passed)
|
94
|
+
|
95
|
+
EOS
|
96
|
+
|
97
|
+
@listener.should_receive(:py_string).with(py_string, 1)
|
98
|
+
@lexer.scan ps(py_string)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should allow whitespace after the closing py_string delimiter" do
|
102
|
+
str = <<EOS
|
103
|
+
"""
|
104
|
+
Line one
|
105
|
+
"""
|
106
|
+
EOS
|
107
|
+
@listener.should_receive(:py_string).with(" Line one", 1)
|
108
|
+
@lexer.scan(str)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should preserve the last newline(s) at the end of a py_string" do
|
112
|
+
str = <<EOS
|
113
|
+
"""
|
114
|
+
PyString text
|
115
|
+
|
116
|
+
|
117
|
+
"""
|
118
|
+
EOS
|
119
|
+
@listener.should_receive(:py_string).with("PyString text\n\n",1)
|
120
|
+
@lexer.scan(str)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
3
|
+
|
4
|
+
module Gherkin
|
5
|
+
module Lexer
|
6
|
+
shared_examples_for "a Gherkin lexer lexing tables" do
|
7
|
+
tables = {
|
8
|
+
"|a|b|\n" => [%w{a b}],
|
9
|
+
"|a|b|c|\n" => [%w{a b c}],
|
10
|
+
"|c|d|\n|e|f|\n" => [%w{c d}, %w{e f}]
|
11
|
+
}
|
12
|
+
|
13
|
+
tables.each do |text, expected|
|
14
|
+
it "should parse #{text}" do
|
15
|
+
@listener.should_receive(:table).with(t(expected), 1)
|
16
|
+
@lexer.scan(text.dup)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should parse a table with many columns" do
|
21
|
+
@listener.should_receive(:table).with(t([%w{a b c d e f g h i j k l m n o p}]), 1)
|
22
|
+
@lexer.scan("|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should parse a multicharacter cell content" do
|
26
|
+
@listener.should_receive(:table).with(t([%w{foo bar}]), 1)
|
27
|
+
@lexer.scan("| foo | bar |\n")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should parse cells with spaces within the content" do
|
31
|
+
@listener.should_receive(:table).with(t([["Dill pickle", "Valencia orange"], ["Ruby red grapefruit", "Tire iron"]]), 1)
|
32
|
+
@lexer.scan("| Dill pickle | Valencia orange |\n| Ruby red grapefruit | Tire iron |\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should allow utf-8" do
|
36
|
+
# Fails in 1.9.1!
|
37
|
+
# 'Gherkin::Lexer::Table should allow utf-8 with using == to evaluate' FAILED
|
38
|
+
# expected: [[:table, [["ůﻚ", "2"]], 1]],
|
39
|
+
# got: [[:table, [["\xC5\xAF\xEF\xBB\x9A", "2"]], 1]] (using ==)
|
40
|
+
# BUT, simply running:
|
41
|
+
# [[:table, [["ůﻚ", "2"]], 1]].should == [[:table, [["\xC5\xAF\xEF\xBB\x9A", "2"]], 1]]
|
42
|
+
# passes
|
43
|
+
#
|
44
|
+
@lexer.scan(" | ůﻚ | 2 | \n")
|
45
|
+
@listener.to_sexp.should == [
|
46
|
+
[:table, [["ůﻚ", "2"]], 1]
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should allow utf-8 using should_receive" do
|
51
|
+
@listener.should_receive(:table).with(t([['繁體中文 而且','並且','繁體中文 而且','並且']]), 1)
|
52
|
+
@lexer.scan("| 繁體中文 而且|並且| 繁體中文 而且|並且|\n")
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should parse a 2x2 table" do
|
56
|
+
@listener.should_receive(:table).with(t([%w{1 2}, %w{3 4}]), 1)
|
57
|
+
@lexer.scan("| 1 | 2 |\n| 3 | 4 |\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should parse a 2x2 table with several newlines" do
|
61
|
+
@listener.should_receive(:table).with(t([%w{1 2}, %w{3 4}]), 1)
|
62
|
+
@lexer.scan("| 1 | 2 |\n| 3 | 4 |\n\n\n")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should parse a 2x2 table with empty cells" do
|
66
|
+
@listener.should_receive(:table).with(t([['1', ''], ['', '4']]), 1)
|
67
|
+
@lexer.scan("| 1 | |\n|| 4 |\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should parse a 1x2 table that does not end in a newline" do
|
71
|
+
@listener.should_receive(:table).with(t([%w{1 2}]), 1)
|
72
|
+
@lexer.scan("| 1 | 2 |")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should parse a 1x2 table without spaces and newline" do
|
76
|
+
@listener.should_receive(:table).with(t([%w{1 2}]), 1)
|
77
|
+
@lexer.scan("|1|2|\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should parse a row with whitespace after the rows" do
|
81
|
+
@listener.should_receive(:table).with(t([%w{1 2}, %w{a b}]), 1)
|
82
|
+
@lexer.scan("| 1 | 2 | \n | a | b | \n")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should parse a table with lots of whitespace" do
|
86
|
+
@listener.should_receive(:table).with(t([["abc", "123"]]), 1)
|
87
|
+
@lexer.scan(" \t| \t abc\t| \t123\t \t\t| \t\t \t \t\n ")
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should raise LexingError for rows that aren't closed" do
|
91
|
+
lambda {
|
92
|
+
@lexer.scan("|| oh hello \n")
|
93
|
+
}.should raise_error(/Parsing error on line 1: '|| oh hello/)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
3
|
+
|
4
|
+
module Gherkin
|
5
|
+
module Lexer
|
6
|
+
shared_examples_for "a Gherkin lexer lexing tags" do
|
7
|
+
it "should lex a single tag" do
|
8
|
+
@listener.should_receive(:tag).with("dog", 1)
|
9
|
+
@lexer.scan("@dog\n")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should lex multiple tags" do
|
13
|
+
@listener.should_receive(:tag).twice
|
14
|
+
@lexer.scan("@dog @cat\n")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should lex UTF-8 tags" do
|
18
|
+
@listener.should_receive(:tag).with("シナリオテンプレート", 1)
|
19
|
+
@lexer.scan("@シナリオテンプレート\n")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should lex mixed tags" do
|
23
|
+
@listener.should_receive(:tag).with("wip", 1).ordered
|
24
|
+
@listener.should_receive(:tag).with("Значения", 1).ordered
|
25
|
+
@lexer.scan("@wip @Значения\n")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should lex wacky identifiers" do
|
29
|
+
@listener.should_receive(:tag).exactly(4).times
|
30
|
+
@lexer.scan("@BJ-x98.77 @BJ-z12.33 @O_o" "@#not_a_comment\n")
|
31
|
+
end
|
32
|
+
|
33
|
+
# TODO: Ask on ML for opinions about this one
|
34
|
+
it "should lex tags without spaces between them?" do
|
35
|
+
@listener.should_receive(:tag).twice
|
36
|
+
@lexer.scan("@one@two\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not lex tags beginning with two @@ signs" do
|
40
|
+
@listener.should_not_receive(:tag)
|
41
|
+
lambda { @lexer.scan("@@test\n") }.should raise_error(/Lexing error on line 1/)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not lex a lone @ sign" do
|
45
|
+
@listener.should_not_receive(:tag)
|
46
|
+
lambda { @lexer.scan("@\n") }.should raise_error(/Lexing error on line 1/)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'spec/gherkin'))
|
4
|
+
require 'gherkin'
|
5
|
+
require 'gherkin/sexp_recorder'
|
6
|
+
require 'rubygems'
|
7
|
+
require 'spec'
|
8
|
+
require 'spec/autorun'
|
9
|
+
require 'shared/lexer_spec'
|
10
|
+
require 'shared/tags_spec'
|
11
|
+
require 'shared/py_string_spec'
|
12
|
+
require 'shared/table_spec'
|
13
|
+
|
14
|
+
module GherkinSpecHelper
|
15
|
+
def scan_file(file)
|
16
|
+
@lexer.scan(File.new(File.dirname(__FILE__) + "/gherkin/fixtures/" + file).read)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Spec::Runner.configure do |c|
|
21
|
+
c.include(GherkinSpecHelper)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Allows comparison of Java List with Ruby Array (tables)
|
25
|
+
Spec::Matchers.define :t do |expected|
|
26
|
+
match do |table|
|
27
|
+
def table.inspect
|
28
|
+
"t " + self.map{|row| row.map{|cell| cell}}.inspect
|
29
|
+
end
|
30
|
+
table.map{|row| row.map{|cell| cell}}.should == expected
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Spec::Matchers.define :a do |expected|
|
35
|
+
match do |array|
|
36
|
+
def array.inspect
|
37
|
+
"a " + self.map{|e| e.to_sym}.inspect
|
38
|
+
end
|
39
|
+
array.map{|e| e.to_sym}.should == expected
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Spec::Matchers.define :sym do |expected|
|
44
|
+
match do |actual|
|
45
|
+
expected.to_s == actual.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Spec::Matchers.define :allow do |event|
|
50
|
+
match do |parser|
|
51
|
+
parser.expected.index(event)
|
52
|
+
end
|
53
|
+
end
|
data/tasks/bench.rake
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
%w{/../lib /bench}.each do |l|
|
2
|
+
$LOAD_PATH << File.expand_path(File.dirname(__FILE__) + l)
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'benchmark'
|
6
|
+
|
7
|
+
GENERATED_FEATURES = File.expand_path(File.dirname(__FILE__) + "/bench/generated")
|
8
|
+
|
9
|
+
class RandomFeatureGenerator
|
10
|
+
def initialize(number)
|
11
|
+
require 'faker'
|
12
|
+
require 'feature_builder'
|
13
|
+
|
14
|
+
@number = number
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate
|
18
|
+
@number.times do
|
19
|
+
name = catch_phrase
|
20
|
+
feature = FeatureBuilder.new(name) do |f|
|
21
|
+
num_scenarios = rand_in(1..10)
|
22
|
+
num_scenarios.times do
|
23
|
+
f.scenario(bs) do |steps|
|
24
|
+
num_steps = rand_in(3..10)
|
25
|
+
num_steps.times do
|
26
|
+
steps.step(sentence, self)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
write feature.to_s, name
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def write(content, name)
|
36
|
+
File.open(GENERATED_FEATURES + "/#{name.downcase.gsub(/[\s\-\/]/, '_')}.feature", "w+") do |file|
|
37
|
+
file << content
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def rand_in(range)
|
42
|
+
ary = range.to_a
|
43
|
+
ary[rand(ary.length - 1)]
|
44
|
+
end
|
45
|
+
|
46
|
+
def catch_phrase
|
47
|
+
Faker::Company.catch_phrase
|
48
|
+
end
|
49
|
+
|
50
|
+
def bs
|
51
|
+
Faker::Company.bs.capitalize
|
52
|
+
end
|
53
|
+
|
54
|
+
def sentence
|
55
|
+
Faker::Lorem.sentence
|
56
|
+
end
|
57
|
+
|
58
|
+
def table_cell
|
59
|
+
Faker::Lorem.words(rand(2)+1).join(" ")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Benchmarker
|
64
|
+
def initialize
|
65
|
+
@features = Dir[GENERATED_FEATURES + "/**/*feature"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def report(lexer)
|
69
|
+
Benchmark.bm do |x|
|
70
|
+
x.report("#{lexer}:") { send :"run_#{lexer}" }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def report_all
|
75
|
+
Benchmark.bmbm do |x|
|
76
|
+
x.report("c_gherkin:") { run_c_gherkin }
|
77
|
+
x.report("c_gherkin_no_parser:") { run_c_gherkin_no_parser }
|
78
|
+
x.report("rb_gherkin:") { run_rb_gherkin }
|
79
|
+
x.report("cucumber:") { run_cucumber }
|
80
|
+
x.report("tt:") { run_tt }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def run_cucumber
|
85
|
+
require 'cucumber'
|
86
|
+
require 'logger'
|
87
|
+
step_mother = Cucumber::StepMother.new
|
88
|
+
logger = Logger.new(STDOUT)
|
89
|
+
logger.level = Logger::INFO
|
90
|
+
step_mother.log = logger
|
91
|
+
step_mother.load_plain_text_features(@features)
|
92
|
+
end
|
93
|
+
|
94
|
+
def run_tt
|
95
|
+
require 'cucumber'
|
96
|
+
# Using Cucumber's Treetop lexer, but never calling #build to build the AST
|
97
|
+
lexer = Cucumber::Parser::NaturalLanguage.new(nil, 'en').parser
|
98
|
+
@features.each do |file|
|
99
|
+
source = IO.read(file)
|
100
|
+
parse_tree = lexer.parse(source)
|
101
|
+
if parse_tree.nil?
|
102
|
+
raise Cucumber::Parser::SyntaxError.new(lexer, file, 0)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def run_rb_gherkin
|
108
|
+
require 'gherkin'
|
109
|
+
require 'gherkin/rb_lexer'
|
110
|
+
require 'null_listener'
|
111
|
+
@features.each do |feature|
|
112
|
+
parser = Gherkin::Parser.new(NullListener.new, true, "root")
|
113
|
+
lexer = Gherkin::RbLexer['en'].new(parser)
|
114
|
+
lexer.scan(File.read(feature))
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def run_c_gherkin
|
119
|
+
require 'gherkin'
|
120
|
+
require 'null_listener'
|
121
|
+
@features.each do |feature|
|
122
|
+
parser = Gherkin::Parser.new(NullListener.new, true, "root")
|
123
|
+
lexer = Gherkin::CLexer['en'].new(parser)
|
124
|
+
lexer.scan(File.read(feature))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def run_c_gherkin_no_parser
|
129
|
+
require 'gherkin'
|
130
|
+
require 'null_listener'
|
131
|
+
@features.each do |feature|
|
132
|
+
lexer = Gherkin::CLexer['en'].new(NullListener.new)
|
133
|
+
lexer.scan(File.read(feature))
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
desc "Generate 500 random features and benchmark Cucumber, Treetop and Gherkin with them"
|
139
|
+
task :bench => ["bench:clean", "bench:gen"] do
|
140
|
+
benchmarker = Benchmarker.new
|
141
|
+
benchmarker.report_all
|
142
|
+
end
|
143
|
+
|
144
|
+
namespace :bench do
|
145
|
+
desc "Generate [number] features with random content, or 500 features if number is not provided"
|
146
|
+
task :gen, :number do |t, args|
|
147
|
+
args.with_defaults(:number => 500)
|
148
|
+
generator = RandomFeatureGenerator.new(args.number.to_i)
|
149
|
+
generator.generate
|
150
|
+
end
|
151
|
+
|
152
|
+
desc "Benchmark Cucumber AST building from the features in tasks/bench/generated"
|
153
|
+
task :cucumber do
|
154
|
+
benchmarker = Benchmarker.new
|
155
|
+
benchmarker.report("cucumber")
|
156
|
+
end
|
157
|
+
|
158
|
+
desc "Benchmark the Treetop parser with the features in tasks/bench/generated"
|
159
|
+
task :tt do
|
160
|
+
benchmarker = Benchmarker.new
|
161
|
+
benchmarker.report("tt")
|
162
|
+
end
|
163
|
+
|
164
|
+
desc "Benchmark the Ruby Gherkin lexer+parser with the features in tasks/bench/generated"
|
165
|
+
task :rb_gherkin do
|
166
|
+
benchmarker = Benchmarker.new
|
167
|
+
benchmarker.report("rb_gherkin")
|
168
|
+
end
|
169
|
+
|
170
|
+
desc "Benchmark the C Gherkin lexer+parser with the features in tasks/bench/generated"
|
171
|
+
task :c_gherkin do
|
172
|
+
benchmarker = Benchmarker.new
|
173
|
+
benchmarker.report("c_gherkin")
|
174
|
+
end
|
175
|
+
|
176
|
+
desc "Benchmark the C Gherkin lexer (no parser) with the features in tasks/bench/generated"
|
177
|
+
task :c_gherkin_no_parser do
|
178
|
+
benchmarker = Benchmarker.new
|
179
|
+
benchmarker.report("c_gherkin_no_parser")
|
180
|
+
end
|
181
|
+
|
182
|
+
desc "Show basic statistics about the features in tasks/bench/generated"
|
183
|
+
task :stats do
|
184
|
+
["Feature", "Scenario", "Given"].each do |kw|
|
185
|
+
sh "grep #{kw} #{GENERATED_FEATURES}/* | wc -l"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
desc "Remove all generated features in tasks/bench/generated"
|
190
|
+
task :clean do
|
191
|
+
rm_f FileList[GENERATED_FEATURES + "/**/*feature"]
|
192
|
+
end
|
193
|
+
end
|