bryanl-gherkin 2.11.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitattributes +2 -0
- data/.mailmap +2 -0
- data/.rbenv-gemsets +1 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +16 -0
- data/.yardopts +5 -0
- data/Gemfile +5 -0
- data/History.md +788 -0
- data/LICENSE +20 -0
- data/README.md +272 -0
- data/Rakefile +26 -0
- data/build_native_gems.sh +7 -0
- data/cucumber.yml +4 -0
- data/examples/parse_and_output_json.rb +19 -0
- data/features/.cucumber/stepdefs.json +244 -0
- data/features/escaped_pipes.feature +8 -0
- data/features/feature_parser.feature +237 -0
- data/features/json_formatter.feature +498 -0
- data/features/json_parser.feature +331 -0
- data/features/native_lexer.feature +19 -0
- data/features/parser_with_native_lexer.feature +205 -0
- data/features/pretty_formatter.feature +16 -0
- data/features/step_definitions/eyeball_steps.rb +3 -0
- data/features/step_definitions/gherkin_steps.rb +29 -0
- data/features/step_definitions/json_formatter_steps.rb +30 -0
- data/features/step_definitions/json_parser_steps.rb +20 -0
- data/features/step_definitions/pretty_formatter_steps.rb +85 -0
- data/features/steps_parser.feature +46 -0
- data/features/support/env.rb +42 -0
- data/gherkin.gemspec +77 -0
- data/install_mingw_os_x.sh +7 -0
- data/js/.npmignore +1 -0
- data/js/lib/gherkin/lexer/.npmignore +0 -0
- data/lib/gherkin.rb +2 -0
- data/lib/gherkin/c_lexer.rb +17 -0
- data/lib/gherkin/formatter/ansi_escapes.rb +97 -0
- data/lib/gherkin/formatter/argument.rb +16 -0
- data/lib/gherkin/formatter/escaping.rb +15 -0
- data/lib/gherkin/formatter/filter_formatter.rb +146 -0
- data/lib/gherkin/formatter/hashable.rb +19 -0
- data/lib/gherkin/formatter/json_formatter.rb +122 -0
- data/lib/gherkin/formatter/line_filter.rb +26 -0
- data/lib/gherkin/formatter/model.rb +281 -0
- data/lib/gherkin/formatter/pretty_formatter.rb +244 -0
- data/lib/gherkin/formatter/regexp_filter.rb +21 -0
- data/lib/gherkin/formatter/step_printer.rb +21 -0
- data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
- data/lib/gherkin/formatter/tag_filter.rb +19 -0
- data/lib/gherkin/i18n.rb +180 -0
- data/lib/gherkin/i18n.yml +613 -0
- data/lib/gherkin/js_lexer.rb +20 -0
- data/lib/gherkin/json_parser.rb +177 -0
- data/lib/gherkin/lexer/i18n_lexer.rb +46 -0
- data/lib/gherkin/listener/event.rb +45 -0
- data/lib/gherkin/listener/formatter_listener.rb +143 -0
- data/lib/gherkin/native.rb +7 -0
- data/lib/gherkin/native/java.rb +72 -0
- data/lib/gherkin/native/null.rb +5 -0
- data/lib/gherkin/native/therubyracer.rb +39 -0
- data/lib/gherkin/parser/meta.txt +5 -0
- data/lib/gherkin/parser/parser.rb +164 -0
- data/lib/gherkin/parser/root.txt +11 -0
- data/lib/gherkin/parser/steps.txt +4 -0
- data/lib/gherkin/rb_lexer.rb +8 -0
- data/lib/gherkin/rb_lexer/README.rdoc +8 -0
- data/lib/gherkin/rb_lexer/ar.rb +1165 -0
- data/lib/gherkin/rb_lexer/bg.rb +1377 -0
- data/lib/gherkin/rb_lexer/bm.rb +1081 -0
- data/lib/gherkin/rb_lexer/ca.rb +1305 -0
- data/lib/gherkin/rb_lexer/cs.rb +1157 -0
- data/lib/gherkin/rb_lexer/cy_gb.rb +1027 -0
- data/lib/gherkin/rb_lexer/da.rb +1043 -0
- data/lib/gherkin/rb_lexer/de.rb +1151 -0
- data/lib/gherkin/rb_lexer/en.rb +1151 -0
- data/lib/gherkin/rb_lexer/en_au.rb +971 -0
- data/lib/gherkin/rb_lexer/en_lol.rb +929 -0
- data/lib/gherkin/rb_lexer/en_pirate.rb +1205 -0
- data/lib/gherkin/rb_lexer/en_scouse.rb +1357 -0
- data/lib/gherkin/rb_lexer/en_tx.rb +1011 -0
- data/lib/gherkin/rb_lexer/eo.rb +990 -0
- data/lib/gherkin/rb_lexer/es.rb +1135 -0
- data/lib/gherkin/rb_lexer/et.rb +985 -0
- data/lib/gherkin/rb_lexer/fi.rb +964 -0
- data/lib/gherkin/rb_lexer/fr.rb +1223 -0
- data/lib/gherkin/rb_lexer/he.rb +1113 -0
- data/lib/gherkin/rb_lexer/hr.rb +1061 -0
- data/lib/gherkin/rb_lexer/hu.rb +1113 -0
- data/lib/gherkin/rb_lexer/id.rb +958 -0
- data/lib/gherkin/rb_lexer/is.rb +1115 -0
- data/lib/gherkin/rb_lexer/it.rb +1081 -0
- data/lib/gherkin/rb_lexer/ja.rb +1413 -0
- data/lib/gherkin/rb_lexer/ko.rb +1097 -0
- data/lib/gherkin/rb_lexer/lt.rb +1040 -0
- data/lib/gherkin/rb_lexer/lu.rb +1127 -0
- data/lib/gherkin/rb_lexer/lv.rb +1161 -0
- data/lib/gherkin/rb_lexer/nl.rb +1110 -0
- data/lib/gherkin/rb_lexer/no.rb +1055 -0
- data/lib/gherkin/rb_lexer/pl.rb +1452 -0
- data/lib/gherkin/rb_lexer/pt.rb +1425 -0
- data/lib/gherkin/rb_lexer/ro.rb +1159 -0
- data/lib/gherkin/rb_lexer/ru.rb +1749 -0
- data/lib/gherkin/rb_lexer/sk.rb +1041 -0
- data/lib/gherkin/rb_lexer/sr_cyrl.rb +1798 -0
- data/lib/gherkin/rb_lexer/sr_latn.rb +1289 -0
- data/lib/gherkin/rb_lexer/sv.rb +1065 -0
- data/lib/gherkin/rb_lexer/tr.rb +1087 -0
- data/lib/gherkin/rb_lexer/uk.rb +1641 -0
- data/lib/gherkin/rb_lexer/uz.rb +1371 -0
- data/lib/gherkin/rb_lexer/vi.rb +1193 -0
- data/lib/gherkin/rb_lexer/zh_cn.rb +1053 -0
- data/lib/gherkin/rb_lexer/zh_tw.rb +1047 -0
- data/lib/gherkin/rubify.rb +24 -0
- data/lib/gherkin/tag_expression.rb +62 -0
- data/ragel/lexer.c.rl.erb +454 -0
- data/ragel/lexer.java.rl.erb +219 -0
- data/ragel/lexer.js.rl.erb +227 -0
- data/ragel/lexer.rb.rl.erb +174 -0
- data/ragel/lexer_common.rl.erb +50 -0
- data/spec/gherkin/c_lexer_spec.rb +22 -0
- data/spec/gherkin/fixtures/1.feature +8 -0
- data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
- data/spec/gherkin/fixtures/complex.feature +45 -0
- data/spec/gherkin/fixtures/complex.json +139 -0
- data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
- data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
- data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
- data/spec/gherkin/fixtures/examples_with_only_header.feature +14 -0
- data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
- data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
- data/spec/gherkin/fixtures/i18n_fr2.feature +8 -0
- data/spec/gherkin/fixtures/i18n_no.feature +7 -0
- data/spec/gherkin/fixtures/i18n_pt1.feature +44 -0
- data/spec/gherkin/fixtures/i18n_pt2.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt3.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt4.feature +4 -0
- data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
- data/spec/gherkin/fixtures/issue_145.feature +22 -0
- data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
- data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
- data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
- data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
- data/spec/gherkin/fixtures/with_bom.feature +3 -0
- data/spec/gherkin/formatter/ansi_escapes_spec.rb +32 -0
- data/spec/gherkin/formatter/filter_formatter_spec.rb +204 -0
- data/spec/gherkin/formatter/json_formatter_spec.rb +92 -0
- data/spec/gherkin/formatter/model_spec.rb +28 -0
- data/spec/gherkin/formatter/pretty_formatter_spec.rb +177 -0
- data/spec/gherkin/formatter/spaces.feature +9 -0
- data/spec/gherkin/formatter/step_printer_spec.rb +55 -0
- data/spec/gherkin/formatter/tabs.feature +9 -0
- data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
- data/spec/gherkin/i18n_spec.rb +241 -0
- data/spec/gherkin/java_lexer_spec.rb +20 -0
- data/spec/gherkin/js_lexer_spec.rb +23 -0
- data/spec/gherkin/json_parser_spec.rb +176 -0
- data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
- data/spec/gherkin/output_stream_string_io.rb +20 -0
- data/spec/gherkin/parser/parser_spec.rb +16 -0
- data/spec/gherkin/rb_lexer_spec.rb +20 -0
- data/spec/gherkin/sexp_recorder.rb +59 -0
- data/spec/gherkin/shared/bom_group.rb +20 -0
- data/spec/gherkin/shared/doc_string_group.rb +163 -0
- data/spec/gherkin/shared/lexer_group.rb +591 -0
- data/spec/gherkin/shared/row_group.rb +125 -0
- data/spec/gherkin/shared/tags_group.rb +54 -0
- data/spec/gherkin/tag_expression_spec.rb +142 -0
- data/spec/spec_helper.rb +75 -0
- data/tasks/bench.rake +184 -0
- data/tasks/bench/feature_builder.rb +49 -0
- data/tasks/bench/null_listener.rb +4 -0
- data/tasks/compile.rake +120 -0
- data/tasks/cucumber.rake +22 -0
- data/tasks/gems.rake +31 -0
- data/tasks/ikvm.rake +124 -0
- data/tasks/ragel_task.rb +100 -0
- data/tasks/release.rake +49 -0
- data/tasks/rspec.rake +8 -0
- data/tasks/yard.rake +7 -0
- data/tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/tasks/yard/default/layout/html/bubble_48x48.png +0 -0
- data/tasks/yard/default/layout/html/footer.erb +5 -0
- data/tasks/yard/default/layout/html/index.erb +1 -0
- data/tasks/yard/default/layout/html/layout.erb +25 -0
- data/tasks/yard/default/layout/html/logo.erb +1 -0
- data/tasks/yard/default/layout/html/setup.rb +4 -0
- metadata +473 -0
@@ -0,0 +1,219 @@
|
|
1
|
+
package gherkin.lexer.i18n;
|
2
|
+
|
3
|
+
import java.io.UnsupportedEncodingException;
|
4
|
+
import java.util.List;
|
5
|
+
import java.util.ArrayList;
|
6
|
+
import java.util.regex.Pattern;
|
7
|
+
import gherkin.lexer.Lexer;
|
8
|
+
import gherkin.lexer.Listener;
|
9
|
+
import gherkin.lexer.LexingError;
|
10
|
+
|
11
|
+
public class <%= @i18n.underscored_iso_code.upcase %> implements Lexer {
|
12
|
+
%%{
|
13
|
+
machine lexer;
|
14
|
+
alphtype byte;
|
15
|
+
|
16
|
+
action begin_content {
|
17
|
+
contentStart = p;
|
18
|
+
currentLine = lineNumber;
|
19
|
+
if(keyword != null) {
|
20
|
+
startCol = p - lastNewline - (keyword.length() + 1);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
action start_docstring {
|
25
|
+
currentLine = lineNumber;
|
26
|
+
startCol = p - lastNewline;
|
27
|
+
}
|
28
|
+
|
29
|
+
action begin_docstring_content {
|
30
|
+
contentStart = p;
|
31
|
+
}
|
32
|
+
|
33
|
+
action start_docstring_content_type {
|
34
|
+
docstringContentTypeStart = p;
|
35
|
+
}
|
36
|
+
|
37
|
+
action end_docstring_content_type {
|
38
|
+
docstringContentTypeEnd = p;
|
39
|
+
}
|
40
|
+
|
41
|
+
action store_docstring_content {
|
42
|
+
String con = unindent(startCol, substring(data, contentStart, nextKeywordStart-1).replaceFirst("(\\r?\\n)?([\\t ])*\\Z", "").replaceAll("\\\\\"\\\\\"\\\\\"", "\"\"\""));
|
43
|
+
String conType = substring(data, docstringContentTypeStart, docstringContentTypeEnd).trim();
|
44
|
+
listener.docString(conType, con, currentLine);
|
45
|
+
}
|
46
|
+
|
47
|
+
action store_feature_content {
|
48
|
+
String[] nameDescription = nameAndUnindentedDescription(startCol, keywordContent(data, p, eof, nextKeywordStart, contentStart));
|
49
|
+
listener.feature(keyword, nameDescription[0], nameDescription[1], currentLine);
|
50
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
51
|
+
nextKeywordStart = -1;
|
52
|
+
}
|
53
|
+
|
54
|
+
action store_background_content {
|
55
|
+
String[] nameDescription = nameAndUnindentedDescription(startCol, keywordContent(data, p, eof, nextKeywordStart, contentStart));
|
56
|
+
listener.background(keyword, nameDescription[0], nameDescription[1], currentLine);
|
57
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
58
|
+
nextKeywordStart = -1;
|
59
|
+
}
|
60
|
+
|
61
|
+
action store_scenario_content {
|
62
|
+
String[] nameDescription = nameAndUnindentedDescription(startCol, keywordContent(data, p, eof, nextKeywordStart, contentStart));
|
63
|
+
listener.scenario(keyword, nameDescription[0], nameDescription[1], currentLine);
|
64
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
65
|
+
nextKeywordStart = -1;
|
66
|
+
}
|
67
|
+
|
68
|
+
action store_scenario_outline_content {
|
69
|
+
String[] nameDescription = nameAndUnindentedDescription(startCol, keywordContent(data, p, eof, nextKeywordStart, contentStart));
|
70
|
+
listener.scenarioOutline(keyword, nameDescription[0], nameDescription[1], currentLine);
|
71
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
72
|
+
nextKeywordStart = -1;
|
73
|
+
}
|
74
|
+
|
75
|
+
action store_examples_content {
|
76
|
+
String[] nameDescription = nameAndUnindentedDescription(startCol, keywordContent(data, p, eof, nextKeywordStart, contentStart));
|
77
|
+
listener.examples(keyword, nameDescription[0], nameDescription[1], currentLine);
|
78
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
79
|
+
nextKeywordStart = -1;
|
80
|
+
}
|
81
|
+
|
82
|
+
action store_step_content {
|
83
|
+
listener.step(keyword, substring(data, contentStart, p).trim(), currentLine);
|
84
|
+
}
|
85
|
+
|
86
|
+
action store_comment_content {
|
87
|
+
listener.comment(substring(data, contentStart, p).trim(), lineNumber);
|
88
|
+
keywordStart = -1;
|
89
|
+
}
|
90
|
+
|
91
|
+
action store_tag_content {
|
92
|
+
listener.tag(substring(data, contentStart, p).trim(), currentLine);
|
93
|
+
keywordStart = -1;
|
94
|
+
}
|
95
|
+
|
96
|
+
action inc_line_number {
|
97
|
+
lineNumber++;
|
98
|
+
}
|
99
|
+
|
100
|
+
action last_newline {
|
101
|
+
lastNewline = p + 1;
|
102
|
+
}
|
103
|
+
|
104
|
+
action start_keyword {
|
105
|
+
if(keywordStart == -1) keywordStart = p;
|
106
|
+
}
|
107
|
+
|
108
|
+
action end_keyword {
|
109
|
+
keyword = substring(data, keywordStart, p).replaceFirst(":$","");
|
110
|
+
keywordStart = -1;
|
111
|
+
}
|
112
|
+
|
113
|
+
action next_keyword_start {
|
114
|
+
nextKeywordStart = p;
|
115
|
+
}
|
116
|
+
|
117
|
+
action start_row {
|
118
|
+
p = p - 1;
|
119
|
+
currentRow = new ArrayList<String>();
|
120
|
+
currentLine = lineNumber;
|
121
|
+
}
|
122
|
+
|
123
|
+
action begin_cell_content {
|
124
|
+
contentStart = p;
|
125
|
+
}
|
126
|
+
|
127
|
+
action store_cell_content {
|
128
|
+
String con = substring(data, contentStart, p).trim();
|
129
|
+
currentRow.add(con
|
130
|
+
.replaceAll("\\\\\\|", "|")
|
131
|
+
.replaceAll("\\\\n", "\n")
|
132
|
+
.replaceAll("\\\\\\\\", "\\\\")
|
133
|
+
);
|
134
|
+
}
|
135
|
+
|
136
|
+
action store_row {
|
137
|
+
listener.row(currentRow, currentLine);
|
138
|
+
}
|
139
|
+
|
140
|
+
action end_feature {
|
141
|
+
if(cs < lexer_first_final) {
|
142
|
+
String content = currentLineContent(data, lastNewline);
|
143
|
+
throw new LexingError("Lexing error on line " + lineNumber + ": '" + content + "'. See http://wiki.github.com/cucumber/gherkin/lexingerror for more information.");
|
144
|
+
} else {
|
145
|
+
listener.eof();
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
include lexer_common "lexer_common.<%= @i18n.underscored_iso_code %>.rl";
|
150
|
+
}%%
|
151
|
+
|
152
|
+
private final Listener listener;
|
153
|
+
|
154
|
+
public <%= @i18n.underscored_iso_code.upcase %>(Listener listener) {
|
155
|
+
this.listener = listener;
|
156
|
+
}
|
157
|
+
|
158
|
+
%% write data noerror;
|
159
|
+
|
160
|
+
public void scan(String source) {
|
161
|
+
String input = source + "\n%_FEATURE_END_%";
|
162
|
+
byte[] data = null;
|
163
|
+
try {
|
164
|
+
data = input.getBytes("UTF-8");
|
165
|
+
} catch(UnsupportedEncodingException e) {
|
166
|
+
throw new RuntimeException(e);
|
167
|
+
}
|
168
|
+
int cs, p = 0, pe = data.length;
|
169
|
+
int eof = pe;
|
170
|
+
|
171
|
+
int lineNumber = 1;
|
172
|
+
int lastNewline = 0;
|
173
|
+
|
174
|
+
int contentStart = -1;
|
175
|
+
int currentLine = -1;
|
176
|
+
int docstringContentTypeStart = -1;
|
177
|
+
int docstringContentTypeEnd = -1;
|
178
|
+
int startCol = -1;
|
179
|
+
int nextKeywordStart = -1;
|
180
|
+
int keywordStart = -1;
|
181
|
+
String keyword = null;
|
182
|
+
List<String> currentRow = null;
|
183
|
+
|
184
|
+
%% write init;
|
185
|
+
%% write exec;
|
186
|
+
}
|
187
|
+
|
188
|
+
private String keywordContent(byte[] data, int p, int eof, int nextKeywordStart, int contentStart) {
|
189
|
+
int endPoint = (nextKeywordStart == -1 || (p == eof)) ? p : nextKeywordStart;
|
190
|
+
return substring(data, contentStart, endPoint);
|
191
|
+
}
|
192
|
+
|
193
|
+
private String[] nameAndUnindentedDescription(int startCol, String text) {
|
194
|
+
String[] lines = text.split("\n");
|
195
|
+
String name = lines.length > 0 ? lines[0].trim() : "";
|
196
|
+
StringBuffer description = new StringBuffer();
|
197
|
+
for(int i = 1; i < lines.length; i++) {
|
198
|
+
description.append(lines[i]);
|
199
|
+
description.append("\n");
|
200
|
+
}
|
201
|
+
return new String[]{name, unindent(startCol+2, description.toString()).replaceAll("\\s+$", "")};
|
202
|
+
}
|
203
|
+
|
204
|
+
private String unindent(int startCol, String text) {
|
205
|
+
return Pattern.compile("^[\t ]{0," + startCol + "}", Pattern.MULTILINE).matcher(text).replaceAll("");
|
206
|
+
}
|
207
|
+
|
208
|
+
private String currentLineContent(byte[] data, int lastNewline) {
|
209
|
+
return substring(data, lastNewline, data.length).trim();
|
210
|
+
}
|
211
|
+
|
212
|
+
private String substring(byte[] data, int start, int end) {
|
213
|
+
try {
|
214
|
+
return new String(data, start, end-start, "utf-8");
|
215
|
+
} catch(java.io.UnsupportedEncodingException e) {
|
216
|
+
throw new RuntimeException("Internal error", e);
|
217
|
+
}
|
218
|
+
}
|
219
|
+
}
|
@@ -0,0 +1,227 @@
|
|
1
|
+
;(function() {
|
2
|
+
|
3
|
+
%%{
|
4
|
+
machine lexer;
|
5
|
+
|
6
|
+
action begin_content {
|
7
|
+
this.content_start = p;
|
8
|
+
this.current_line = this.line_number;
|
9
|
+
this.start_col = p - this.last_newline - (this.keyword+':').length;
|
10
|
+
}
|
11
|
+
|
12
|
+
action start_docstring {
|
13
|
+
this.current_line = this.line_number;
|
14
|
+
this.start_col = p - this.last_newline;
|
15
|
+
}
|
16
|
+
|
17
|
+
action begin_docstring_content {
|
18
|
+
this.content_start = p;
|
19
|
+
}
|
20
|
+
|
21
|
+
action start_docstring_content_type {
|
22
|
+
this.docstring_content_type_start = p;
|
23
|
+
}
|
24
|
+
|
25
|
+
action end_docstring_content_type {
|
26
|
+
this.docstring_content_type_end = p;
|
27
|
+
}
|
28
|
+
|
29
|
+
action store_docstring_content {
|
30
|
+
var con = this.unindent(
|
31
|
+
this.start_col,
|
32
|
+
this.bytesToString(data.slice(this.content_start, this.next_keyword_start-1)).replace(/(\r?\n)?([\t ])*$/, '').replace(/ESCAPED_TRIPLE_QUOTE/mg, '"""')
|
33
|
+
);
|
34
|
+
var con_type = this.bytesToString(data.slice(this.docstring_content_type_start, this.docstring_content_type_end)).trim();
|
35
|
+
this.listener.doc_string(con_type, con, this.current_line);
|
36
|
+
}
|
37
|
+
|
38
|
+
action store_feature_content {
|
39
|
+
p = this.store_keyword_content('feature', data, p, eof);
|
40
|
+
}
|
41
|
+
|
42
|
+
action store_background_content {
|
43
|
+
p = this.store_keyword_content('background', data, p, eof);
|
44
|
+
}
|
45
|
+
|
46
|
+
action store_scenario_content {
|
47
|
+
p = this.store_keyword_content('scenario', data, p, eof);
|
48
|
+
}
|
49
|
+
|
50
|
+
action store_scenario_outline_content {
|
51
|
+
p = this.store_keyword_content('scenario_outline', data, p, eof);
|
52
|
+
}
|
53
|
+
|
54
|
+
action store_examples_content {
|
55
|
+
p = this.store_keyword_content('examples', data, p, eof);
|
56
|
+
}
|
57
|
+
|
58
|
+
action store_step_content {
|
59
|
+
var con = this.bytesToString(data.slice(this.content_start, p)).trim();
|
60
|
+
this.listener.step(this.keyword, con, this.current_line);
|
61
|
+
}
|
62
|
+
|
63
|
+
action store_comment_content {
|
64
|
+
var con = this.bytesToString(data.slice(this.content_start, p)).trim();
|
65
|
+
this.listener.comment(con, this.line_number);
|
66
|
+
this.keyword_start = null;
|
67
|
+
}
|
68
|
+
|
69
|
+
action store_tag_content {
|
70
|
+
var con = this.bytesToString(data.slice(this.content_start, p)).trim();
|
71
|
+
this.listener.tag(con, this.line_number);
|
72
|
+
this.keyword_start = null;
|
73
|
+
}
|
74
|
+
|
75
|
+
action inc_line_number {
|
76
|
+
this.line_number++;
|
77
|
+
}
|
78
|
+
|
79
|
+
action last_newline {
|
80
|
+
this.last_newline = p + 1;
|
81
|
+
}
|
82
|
+
|
83
|
+
action start_keyword {
|
84
|
+
this.keyword_start = this.keyword_start || p;
|
85
|
+
}
|
86
|
+
|
87
|
+
action end_keyword {
|
88
|
+
this.keyword = this.bytesToString(data.slice(this.keyword_start, p)).replace(/:$/, '');
|
89
|
+
this.keyword_start = null;
|
90
|
+
}
|
91
|
+
|
92
|
+
action next_keyword_start {
|
93
|
+
this.next_keyword_start = p;
|
94
|
+
}
|
95
|
+
|
96
|
+
action start_row {
|
97
|
+
p = p - 1;
|
98
|
+
current_row = [];
|
99
|
+
this.current_line = this.line_number;
|
100
|
+
}
|
101
|
+
|
102
|
+
action begin_cell_content {
|
103
|
+
this.content_start = p;
|
104
|
+
}
|
105
|
+
|
106
|
+
action store_cell_content {
|
107
|
+
var con = this.bytesToString(data.slice(this.content_start, p)).trim();
|
108
|
+
current_row.push(con.replace(/\\\|/, "|").replace(/\\n/, "\n").replace(/\\\\/, "\\"));
|
109
|
+
}
|
110
|
+
|
111
|
+
action store_row {
|
112
|
+
this.listener.row(current_row, this.current_line);
|
113
|
+
}
|
114
|
+
|
115
|
+
action end_feature {
|
116
|
+
if(this.cs < lexer_first_final) {
|
117
|
+
var content = this.current_line_content(data, p);
|
118
|
+
throw "Lexing error on line " + this.line_number + ": '" + content + "'. See http://wiki.github.com/cucumber/gherkin/lexingerror for more information.";
|
119
|
+
} else {
|
120
|
+
this.listener.eof();
|
121
|
+
}
|
122
|
+
|
123
|
+
}
|
124
|
+
|
125
|
+
include lexer_common "lexer_common.<%= @i18n.underscored_iso_code %>.rl";
|
126
|
+
}%%
|
127
|
+
|
128
|
+
%% write data;
|
129
|
+
%% access this.;
|
130
|
+
%% variable data data;
|
131
|
+
|
132
|
+
var Lexer = function(listener) {
|
133
|
+
// Check that listener has the required functions
|
134
|
+
var events = ['comment', 'tag', 'feature', 'background', 'scenario', 'scenario_outline', 'examples', 'step', 'doc_string', 'row', 'eof'];
|
135
|
+
for(e in events) {
|
136
|
+
var event = events[e];
|
137
|
+
if(typeof listener[event] != 'function') {
|
138
|
+
"Error. No " + event + " function exists on " + JSON.stringify(listener);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
this.listener = listener;
|
142
|
+
};
|
143
|
+
|
144
|
+
Lexer.prototype.scan = function(data) {
|
145
|
+
var ending = "\n%_FEATURE_END_%";
|
146
|
+
if(typeof data == 'string') {
|
147
|
+
data = this.stringToBytes(data + ending);
|
148
|
+
} else if(typeof Buffer != 'undefined' && Buffer.isBuffer(data)) {
|
149
|
+
// Node.js
|
150
|
+
var buf = new Buffer(data.length + ending.length);
|
151
|
+
data.copy(buf, 0, 0);
|
152
|
+
new Buffer(ending).copy(buf, data.length, 0);
|
153
|
+
data = buf;
|
154
|
+
}
|
155
|
+
var eof = pe = data.length;
|
156
|
+
var p = 0;
|
157
|
+
|
158
|
+
this.line_number = 1;
|
159
|
+
this.last_newline = 0;
|
160
|
+
|
161
|
+
%% write init;
|
162
|
+
%% write exec;
|
163
|
+
};
|
164
|
+
|
165
|
+
Lexer.prototype.bytesToString = function(bytes) {
|
166
|
+
if(typeof bytes.write == 'function') {
|
167
|
+
// Node.js
|
168
|
+
return bytes.toString('utf-8');
|
169
|
+
} else {
|
170
|
+
var result = "";
|
171
|
+
for(var b in bytes) {
|
172
|
+
result += String.fromCharCode(bytes[b]);
|
173
|
+
}
|
174
|
+
return result;
|
175
|
+
}
|
176
|
+
};
|
177
|
+
|
178
|
+
Lexer.prototype.stringToBytes = function(string) {
|
179
|
+
var bytes = [];
|
180
|
+
for(var i = 0; i < string.length; i++) {
|
181
|
+
bytes[i] = string.charCodeAt(i);
|
182
|
+
}
|
183
|
+
return bytes;
|
184
|
+
};
|
185
|
+
|
186
|
+
Lexer.prototype.unindent = function(startcol, text) {
|
187
|
+
startcol = startcol || 0;
|
188
|
+
return text.replace(new RegExp('^[\t ]{0,' + startcol + '}', 'gm'), '');
|
189
|
+
};
|
190
|
+
|
191
|
+
Lexer.prototype.store_keyword_content = function(event, data, p, eof) {
|
192
|
+
var end_point = (!this.next_keyword_start || (p == eof)) ? p : this.next_keyword_start;
|
193
|
+
var content = this.unindent(this.start_col + 2, this.bytesToString(data.slice(this.content_start, end_point))).replace(/\s+$/,"");
|
194
|
+
var content_lines = content.split("\n")
|
195
|
+
var name = content_lines.shift() || "";
|
196
|
+
name = name.trim();
|
197
|
+
var description = content_lines.join("\n");
|
198
|
+
this.listener[event](this.keyword, name, description, this.current_line);
|
199
|
+
var nks = this.next_keyword_start;
|
200
|
+
this.next_keyword_start = null;
|
201
|
+
return nks ? nks - 1 : p;
|
202
|
+
};
|
203
|
+
|
204
|
+
Lexer.prototype.current_line_content = function(data, p) {
|
205
|
+
var rest = data.slice(this.last_newline, -1);
|
206
|
+
var end = rest.indexOf(10) || -1;
|
207
|
+
return this.bytesToString(rest.slice(0, end)).trim();
|
208
|
+
};
|
209
|
+
|
210
|
+
// Node.js export
|
211
|
+
if(typeof exports !== 'undefined') {
|
212
|
+
exports.Lexer = Lexer;
|
213
|
+
}
|
214
|
+
// Require.js export
|
215
|
+
if (typeof define !== 'undefined') {
|
216
|
+
if(define.amd) {
|
217
|
+
define('gherkin/lexer/<%= @i18n.underscored_iso_code %>', [], function() {
|
218
|
+
return Lexer
|
219
|
+
});
|
220
|
+
} else {
|
221
|
+
define('gherkin/lexer/<%= @i18n.underscored_iso_code %>', function(require, exports, module) {
|
222
|
+
exports.Lexer = Lexer;
|
223
|
+
});
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
})();
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'gherkin/lexer/i18n_lexer'
|
2
|
+
|
3
|
+
module Gherkin
|
4
|
+
module RbLexer
|
5
|
+
class <%= @i18n.underscored_iso_code.capitalize %> #:nodoc:
|
6
|
+
%%{
|
7
|
+
machine lexer;
|
8
|
+
|
9
|
+
action begin_content {
|
10
|
+
@content_start = p
|
11
|
+
@current_line = @line_number
|
12
|
+
@start_col = p - @last_newline - "#{@keyword}:".length
|
13
|
+
}
|
14
|
+
|
15
|
+
action start_docstring {
|
16
|
+
@current_line = @line_number
|
17
|
+
@start_col = p - @last_newline
|
18
|
+
}
|
19
|
+
|
20
|
+
action begin_docstring_content {
|
21
|
+
@content_start = p
|
22
|
+
}
|
23
|
+
|
24
|
+
action start_docstring_content_type {
|
25
|
+
@docstring_content_type_start = p
|
26
|
+
}
|
27
|
+
action end_docstring_content_type {
|
28
|
+
@docstring_content_type_end = p
|
29
|
+
}
|
30
|
+
|
31
|
+
action store_docstring_content {
|
32
|
+
con = unindent(@start_col, utf8_pack(data[@content_start...@next_keyword_start-1]).sub(/(\r?\n)?([\t ])*\Z/, '').gsub(/\\"\\"\\"/, '"""'))
|
33
|
+
con_type = utf8_pack(data[@docstring_content_type_start...@docstring_content_type_end]).strip
|
34
|
+
@listener.doc_string(con_type, con, @current_line)
|
35
|
+
}
|
36
|
+
action store_feature_content {
|
37
|
+
p = store_keyword_content(:feature, data, p, eof)
|
38
|
+
}
|
39
|
+
|
40
|
+
action store_background_content {
|
41
|
+
p = store_keyword_content(:background, data, p, eof)
|
42
|
+
}
|
43
|
+
|
44
|
+
action store_scenario_content {
|
45
|
+
p = store_keyword_content(:scenario, data, p, eof)
|
46
|
+
}
|
47
|
+
|
48
|
+
action store_scenario_outline_content {
|
49
|
+
p = store_keyword_content(:scenario_outline, data, p, eof)
|
50
|
+
}
|
51
|
+
|
52
|
+
action store_examples_content {
|
53
|
+
p = store_keyword_content(:examples, data, p, eof)
|
54
|
+
}
|
55
|
+
|
56
|
+
action store_step_content {
|
57
|
+
con = utf8_pack(data[@content_start...p]).strip
|
58
|
+
@listener.step(@keyword, con, @current_line)
|
59
|
+
}
|
60
|
+
|
61
|
+
action store_comment_content {
|
62
|
+
con = utf8_pack(data[@content_start...p]).strip
|
63
|
+
@listener.comment(con, @line_number)
|
64
|
+
@keyword_start = nil
|
65
|
+
}
|
66
|
+
|
67
|
+
action store_tag_content {
|
68
|
+
con = utf8_pack(data[@content_start...p]).strip
|
69
|
+
@listener.tag(con, @current_line)
|
70
|
+
@keyword_start = nil
|
71
|
+
}
|
72
|
+
|
73
|
+
action inc_line_number {
|
74
|
+
@line_number += 1
|
75
|
+
}
|
76
|
+
|
77
|
+
action last_newline {
|
78
|
+
@last_newline = p + 1
|
79
|
+
}
|
80
|
+
|
81
|
+
action start_keyword {
|
82
|
+
@keyword_start ||= p
|
83
|
+
}
|
84
|
+
|
85
|
+
action end_keyword {
|
86
|
+
@keyword = utf8_pack(data[@keyword_start...p]).sub(/:$/,'')
|
87
|
+
@keyword_start = nil
|
88
|
+
}
|
89
|
+
|
90
|
+
action next_keyword_start {
|
91
|
+
@next_keyword_start = p
|
92
|
+
}
|
93
|
+
|
94
|
+
action start_row {
|
95
|
+
p = p - 1
|
96
|
+
current_row = []
|
97
|
+
@current_line = @line_number
|
98
|
+
}
|
99
|
+
|
100
|
+
action begin_cell_content {
|
101
|
+
@content_start = p
|
102
|
+
}
|
103
|
+
|
104
|
+
action store_cell_content {
|
105
|
+
con = utf8_pack(data[@content_start...p]).strip
|
106
|
+
current_row << con.gsub(/\\\|/, "|").gsub(/\\n/, "\n").gsub(/\\\\/, "\\")
|
107
|
+
}
|
108
|
+
|
109
|
+
action store_row {
|
110
|
+
@listener.row(current_row, @current_line)
|
111
|
+
}
|
112
|
+
|
113
|
+
action end_feature {
|
114
|
+
if cs < lexer_first_final
|
115
|
+
content = current_line_content(data, p)
|
116
|
+
raise Gherkin::Lexer::LexingError.new("Lexing error on line %d: '%s'. See http://wiki.github.com/cucumber/gherkin/lexingerror for more information." % [@line_number, content])
|
117
|
+
else
|
118
|
+
@listener.eof
|
119
|
+
end
|
120
|
+
}
|
121
|
+
|
122
|
+
include lexer_common "lexer_common.<%= @i18n.underscored_iso_code %>.rl";
|
123
|
+
}%%
|
124
|
+
|
125
|
+
def initialize(listener)
|
126
|
+
@listener = listener
|
127
|
+
%% write data;
|
128
|
+
end
|
129
|
+
|
130
|
+
def scan(data)
|
131
|
+
data = (data + "\n%_FEATURE_END_%").unpack("c*") # Explicit EOF simplifies things considerably
|
132
|
+
eof = pe = data.length
|
133
|
+
|
134
|
+
@line_number = 1
|
135
|
+
@last_newline = 0
|
136
|
+
|
137
|
+
%% write init;
|
138
|
+
%% write exec;
|
139
|
+
end
|
140
|
+
|
141
|
+
def unindent(startcol, text)
|
142
|
+
text.gsub(/^[\t ]{0,#{startcol}}/, "")
|
143
|
+
end
|
144
|
+
|
145
|
+
def store_keyword_content(event, data, p, eof)
|
146
|
+
end_point = (!@next_keyword_start or (p == eof)) ? p : @next_keyword_start
|
147
|
+
content = unindent(@start_col + 2, utf8_pack(data[@content_start...end_point])).rstrip
|
148
|
+
content_lines = content.split("\n")
|
149
|
+
name = content_lines.shift || ""
|
150
|
+
name.strip!
|
151
|
+
description = content_lines.join("\n")
|
152
|
+
@listener.__send__(event, @keyword, name, description, @current_line)
|
153
|
+
@next_keyword_start ? @next_keyword_start - 1 : p
|
154
|
+
ensure
|
155
|
+
@next_keyword_start = nil
|
156
|
+
end
|
157
|
+
|
158
|
+
def current_line_content(data, p)
|
159
|
+
rest = data[@last_newline..-1]
|
160
|
+
utf8_pack(rest[0..rest.index(10)||-1]).strip # 10 is \n
|
161
|
+
end
|
162
|
+
|
163
|
+
if (RUBY_VERSION =~ /^1\.9/)
|
164
|
+
def utf8_pack(array)
|
165
|
+
array.pack("c*").force_encoding("UTF-8")
|
166
|
+
end
|
167
|
+
else
|
168
|
+
def utf8_pack(array)
|
169
|
+
array.pack("c*")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|