gherkin 1.0.2-i386-mingw32 → 1.0.3-i386-mingw32
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/.gitattributes +1 -0
- data/History.txt +18 -0
- data/README.rdoc +12 -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 +46 -18
- 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 +92 -31
- data/lib/gherkin/java_lexer.rb +0 -10
- data/spec/gherkin/shared/table_spec.rb +0 -97
@@ -0,0 +1,240 @@
|
|
1
|
+
namespace Gherkin.Lexer
|
2
|
+
{
|
3
|
+
using System.Text;
|
4
|
+
using System.Text.RegularExpressions;
|
5
|
+
using System.IO;
|
6
|
+
using System.Collections.Generic;
|
7
|
+
using System.Linq;
|
8
|
+
|
9
|
+
[Language("<%= @i18n.sanitized_key.downcase %>")]
|
10
|
+
public class <%= @i18n.sanitized_key.capitalize %> : ILexer {
|
11
|
+
%%{
|
12
|
+
machine lexer;
|
13
|
+
alphtype char;
|
14
|
+
|
15
|
+
action begin_content {
|
16
|
+
contentStart = p;
|
17
|
+
contentCol = p - lastNewline + 1;
|
18
|
+
contentNewline = lastNewline;
|
19
|
+
currentLine = lineNumber;
|
20
|
+
}
|
21
|
+
|
22
|
+
action start_pystring {
|
23
|
+
currentLine = lineNumber;
|
24
|
+
pystringStartCol = p - lastNewline;
|
25
|
+
pystringStartNewline = lastNewline;
|
26
|
+
}
|
27
|
+
|
28
|
+
action begin_pystring_content {
|
29
|
+
contentStart = p;
|
30
|
+
}
|
31
|
+
|
32
|
+
action store_pystring_content {
|
33
|
+
string con = Unindent(pystringStartCol, new Regex("(\\r?\\n)?( )*\\Z").Replace(Substring(data, contentStart, nextKeywordStart-1), "", 1));
|
34
|
+
listener.PythonString(new Token(con, GetCharacterPosition(data, pystringStartNewline, currentLine, pystringStartCol+1)));
|
35
|
+
}
|
36
|
+
|
37
|
+
action store_feature_content {
|
38
|
+
string con = MultilineStrip(KeywordContent(data, p, eof, nextKeywordStart, contentStart).Trim());
|
39
|
+
listener.Feature(new Token(keyword, GetCharacterPosition(data, keywordNewline, currentLine, keywordCol)), new Token(con, GetCharacterPosition(data, contentNewline, currentLine, contentCol)));
|
40
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
41
|
+
nextKeywordStart = -1;
|
42
|
+
}
|
43
|
+
|
44
|
+
action store_background_content {
|
45
|
+
string con = MultilineStrip(KeywordContent(data, p, eof, nextKeywordStart, contentStart));
|
46
|
+
listener.Background(new Token(keyword, GetCharacterPosition(data, keywordNewline, currentLine, keywordCol)), new Token(con, GetCharacterPosition(data, contentNewline, currentLine, contentCol)));
|
47
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
48
|
+
nextKeywordStart = -1;
|
49
|
+
}
|
50
|
+
|
51
|
+
action store_scenario_content {
|
52
|
+
string con = MultilineStrip(KeywordContent(data, p, eof, nextKeywordStart, contentStart));
|
53
|
+
listener.Scenario(new Token(keyword, GetCharacterPosition(data, keywordNewline, currentLine, keywordCol)), new Token(con, GetCharacterPosition(data, contentNewline, currentLine, contentCol)));
|
54
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
55
|
+
nextKeywordStart = -1;
|
56
|
+
}
|
57
|
+
|
58
|
+
action store_scenario_outline_content {
|
59
|
+
string con = MultilineStrip(KeywordContent(data, p, eof, nextKeywordStart, contentStart));
|
60
|
+
listener.ScenarioOutline(new Token(keyword, GetCharacterPosition(data, keywordNewline, currentLine, keywordCol)), new Token(con, GetCharacterPosition(data, contentNewline, currentLine, contentCol)));
|
61
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
62
|
+
nextKeywordStart = -1;
|
63
|
+
}
|
64
|
+
|
65
|
+
action store_examples_content {
|
66
|
+
string con = MultilineStrip(KeywordContent(data, p, eof, nextKeywordStart, contentStart));
|
67
|
+
listener.Examples(new Token(keyword, GetCharacterPosition(data, keywordNewline, currentLine, keywordCol)), new Token(con, GetCharacterPosition(data, contentNewline, currentLine, contentCol)));
|
68
|
+
if(nextKeywordStart != -1) p = nextKeywordStart - 1;
|
69
|
+
nextKeywordStart = -1;
|
70
|
+
}
|
71
|
+
|
72
|
+
action store_step_content {
|
73
|
+
listener.Step(
|
74
|
+
new Token(keyword, GetCharacterPosition(data, keywordNewline, currentLine, keywordCol)),
|
75
|
+
new Token(Substring(data, contentStart, p).Trim(), GetCharacterPosition(data, contentNewline, currentLine, contentCol)),
|
76
|
+
LookupStepKind(keyword));
|
77
|
+
}
|
78
|
+
|
79
|
+
action store_comment_content {
|
80
|
+
listener.Comment(new Token(Substring(data, contentStart, p).Trim(), GetCharacterPosition(data, contentNewline, currentLine, contentCol)));
|
81
|
+
keywordStart = -1;
|
82
|
+
}
|
83
|
+
|
84
|
+
action store_tag_content {
|
85
|
+
listener.Tag(new Token(Substring(data, contentStart, p).Trim(), GetCharacterPosition(data, contentNewline, currentLine, contentCol-1)));
|
86
|
+
keywordStart = -1;
|
87
|
+
}
|
88
|
+
|
89
|
+
action inc_line_number {
|
90
|
+
lineNumber++;
|
91
|
+
}
|
92
|
+
|
93
|
+
action last_newline {
|
94
|
+
lastNewline = p + 1;
|
95
|
+
}
|
96
|
+
|
97
|
+
action start_keyword {
|
98
|
+
if(keywordStart == -1) keywordStart = p;
|
99
|
+
if(nextKeywordStart == -1)
|
100
|
+
{
|
101
|
+
keywordCol = p - lastNewline + 1;
|
102
|
+
keywordNewline = lastNewline;
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
action end_keyword {
|
107
|
+
keyword = new Regex(":$").Replace(Substring(data, keywordStart, p), "", 1);
|
108
|
+
keywordStart = -1;
|
109
|
+
}
|
110
|
+
|
111
|
+
action next_keyword_start {
|
112
|
+
nextKeywordStart = p;
|
113
|
+
}
|
114
|
+
|
115
|
+
action start_row {
|
116
|
+
p = p - 1;
|
117
|
+
contentCol = p - lastNewline + 1;
|
118
|
+
currentRow = new List<Token>();
|
119
|
+
currentLine = lineNumber;
|
120
|
+
}
|
121
|
+
|
122
|
+
action begin_cell_content {
|
123
|
+
contentStart = p;
|
124
|
+
}
|
125
|
+
|
126
|
+
action store_cell_content {
|
127
|
+
currentRow.Add(new Token(Substring(data, contentStart, p).Trim(), GetCharacterPosition(data, lastNewline, lineNumber, contentStart - lastNewline + 1)));
|
128
|
+
}
|
129
|
+
|
130
|
+
action store_row {
|
131
|
+
listener.Row(currentRow, GetCharacterPosition(data, contentNewline, currentLine, contentCol));
|
132
|
+
}
|
133
|
+
|
134
|
+
action end_feature {
|
135
|
+
if(cs < lexer_first_final) {
|
136
|
+
string content = CurrentLineContent(data, lastNewline);
|
137
|
+
throw new LexingException("Lexing error on line " + lineNumber + ": '" + content + "'");
|
138
|
+
} else {
|
139
|
+
listener.Eof();
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
143
|
+
include lexer_common "lexer_common.<%= @i18n.sanitized_key %>.rl";
|
144
|
+
}%%
|
145
|
+
|
146
|
+
private readonly IListener listener;
|
147
|
+
|
148
|
+
private static readonly IDictionary<string, StepKind> stepKeywords = new Dictionary<string, StepKind>();
|
149
|
+
|
150
|
+
static <%= @i18n.sanitized_key.capitalize %>()
|
151
|
+
{
|
152
|
+
<% @i18n.keywords('given', true).reject{|kw| kw == '* '}.each do |keyword| %>
|
153
|
+
stepKeywords["<%=keyword%>"] = StepKind.Given;
|
154
|
+
<% end %>
|
155
|
+
<% @i18n.keywords('when', true).reject{|kw| kw == '* '}.each do |keyword| %>
|
156
|
+
stepKeywords["<%=keyword%>"] = StepKind.When;
|
157
|
+
<% end %>
|
158
|
+
<% @i18n.keywords('then', true).reject{|kw| kw == '* '}.each do |keyword| %>
|
159
|
+
stepKeywords["<%=keyword%>"] = StepKind.Then;
|
160
|
+
<% end %>
|
161
|
+
<% @i18n.keywords('and', true).reject{|kw| kw == '* '}.each do |keyword| %>
|
162
|
+
stepKeywords["<%=keyword%>"] = StepKind.And;
|
163
|
+
<% end %>
|
164
|
+
<% @i18n.keywords('but', true).reject{|kw| kw == '* '}.each do |keyword| %>
|
165
|
+
stepKeywords["<%=keyword%>"] = StepKind.But;
|
166
|
+
<% end %>
|
167
|
+
stepKeywords["* "] = StepKind.Any;
|
168
|
+
}
|
169
|
+
|
170
|
+
private static StepKind LookupStepKind(string keyword)
|
171
|
+
{
|
172
|
+
if (!stepKeywords.Keys.Contains(keyword))
|
173
|
+
return StepKind.Unknown;
|
174
|
+
return stepKeywords[keyword];
|
175
|
+
}
|
176
|
+
|
177
|
+
public <%= @i18n.sanitized_key.capitalize %>(IListener listener) {
|
178
|
+
this.listener = listener;
|
179
|
+
|
180
|
+
}
|
181
|
+
|
182
|
+
%% write data noerror;
|
183
|
+
|
184
|
+
public void Scan(TextReader inputSequence) {
|
185
|
+
string input = inputSequence.ReadToEnd() + "\n%_FEATURE_END_%";
|
186
|
+
char[] data = Encoding.GetEncoding("iso-8859-1").GetChars(Encoding.UTF8.GetBytes(input));
|
187
|
+
int cs, p = 0, pe = data.Length;
|
188
|
+
int eof = pe;
|
189
|
+
|
190
|
+
int lineNumber = 1;
|
191
|
+
int lastNewline = 0;
|
192
|
+
|
193
|
+
int keywordCol = -1;
|
194
|
+
int keywordNewline = 0;
|
195
|
+
int contentCol = -1;
|
196
|
+
int contentNewline = 0;
|
197
|
+
int contentStart = -1;
|
198
|
+
int currentLine = -1;
|
199
|
+
int pystringStartNewline = 0;
|
200
|
+
int pystringStartCol = -1;
|
201
|
+
int nextKeywordStart = -1;
|
202
|
+
int keywordStart = -1;
|
203
|
+
string keyword = null;
|
204
|
+
IList<Token> currentRow = null;
|
205
|
+
|
206
|
+
%% write init;
|
207
|
+
%% write exec;
|
208
|
+
}
|
209
|
+
|
210
|
+
private string KeywordContent(char[] data, int p, int eof, int nextKeywordStart, int contentStart) {
|
211
|
+
int endPoint = (nextKeywordStart == -1 || (p == eof)) ? p : nextKeywordStart;
|
212
|
+
return Substring(data, contentStart, endPoint);
|
213
|
+
}
|
214
|
+
|
215
|
+
private string MultilineStrip(string text) {
|
216
|
+
var result = new StringBuilder();
|
217
|
+
foreach (var s in text.Split(new [] {'\n'})) {
|
218
|
+
result.AppendLine(s.Trim());
|
219
|
+
}
|
220
|
+
return result.ToString().Trim();
|
221
|
+
}
|
222
|
+
|
223
|
+
private string Unindent(int startCol, string text) {
|
224
|
+
return new Regex("^ {0," + startCol + "}", RegexOptions.Multiline).Replace(text, "");
|
225
|
+
}
|
226
|
+
|
227
|
+
private string CurrentLineContent(char[] data, int lastNewline) {
|
228
|
+
return Substring(data, lastNewline, data.Length).Trim();
|
229
|
+
}
|
230
|
+
|
231
|
+
private string Substring(char[] data, int start, int end) {
|
232
|
+
return Encoding.UTF8.GetString(Encoding.GetEncoding("iso-8859-1").GetBytes(data, start, end-start));
|
233
|
+
}
|
234
|
+
|
235
|
+
private Position GetCharacterPosition(char[] data, int lineStart, int line, int bytecol) {
|
236
|
+
return new Position(line,
|
237
|
+
Encoding.UTF8.GetCharCount(Encoding.GetEncoding("iso-8859-1").GetBytes(data, lineStart, bytecol)));
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
data/ragel/lexer.java.rl.erb
CHANGED
@@ -3,6 +3,7 @@ package gherkin.lexer;
|
|
3
3
|
import java.util.List;
|
4
4
|
import java.util.ArrayList;
|
5
5
|
import java.util.regex.Pattern;
|
6
|
+
import java.util.regex.Matcher;
|
6
7
|
import gherkin.Lexer;
|
7
8
|
import gherkin.Listener;
|
8
9
|
import gherkin.LexingError;
|
@@ -93,7 +94,7 @@ public class <%= @i18n.sanitized_key.capitalize %> implements Lexer {
|
|
93
94
|
}
|
94
95
|
|
95
96
|
action end_keyword {
|
96
|
-
keyword = substring(data, keywordStart, p).replaceFirst(":$","")
|
97
|
+
keyword = substring(data, keywordStart, p).replaceFirst(":$","");
|
97
98
|
keywordStart = -1;
|
98
99
|
}
|
99
100
|
|
@@ -101,14 +102,10 @@ public class <%= @i18n.sanitized_key.capitalize %> implements Lexer {
|
|
101
102
|
nextKeywordStart = p;
|
102
103
|
}
|
103
104
|
|
104
|
-
action start_table {
|
105
|
-
p = p - 1;
|
106
|
-
rows = new ArrayList<List<String>>();
|
107
|
-
currentLine = lineNumber;
|
108
|
-
}
|
109
|
-
|
110
105
|
action start_row {
|
106
|
+
p = p - 1;
|
111
107
|
currentRow = new ArrayList<String>();
|
108
|
+
currentLine = lineNumber;
|
112
109
|
}
|
113
110
|
|
114
111
|
action begin_cell_content {
|
@@ -120,19 +117,15 @@ public class <%= @i18n.sanitized_key.capitalize %> implements Lexer {
|
|
120
117
|
}
|
121
118
|
|
122
119
|
action store_row {
|
123
|
-
|
124
|
-
}
|
125
|
-
|
126
|
-
action store_table {
|
127
|
-
if(!rows.isEmpty()) {
|
128
|
-
listener.table(rows, currentLine);
|
129
|
-
}
|
120
|
+
listener.row(currentRow, currentLine);
|
130
121
|
}
|
131
122
|
|
132
123
|
action end_feature {
|
133
124
|
if(cs < lexer_first_final) {
|
134
125
|
String content = currentLineContent(data, lastNewline);
|
135
|
-
throw new LexingError("Lexing error on line " + lineNumber);
|
126
|
+
throw new LexingError("Lexing error on line " + lineNumber + ": '" + content + "'");
|
127
|
+
} else {
|
128
|
+
listener.eof();
|
136
129
|
}
|
137
130
|
}
|
138
131
|
|
@@ -162,7 +155,6 @@ public class <%= @i18n.sanitized_key.capitalize %> implements Lexer {
|
|
162
155
|
int nextKeywordStart = -1;
|
163
156
|
int keywordStart = -1;
|
164
157
|
String keyword = null;
|
165
|
-
List<List<String>> rows = null;
|
166
158
|
List<String> currentRow = null;
|
167
159
|
|
168
160
|
%% write init;
|
@@ -174,14 +166,31 @@ public class <%= @i18n.sanitized_key.capitalize %> implements Lexer {
|
|
174
166
|
return substring(data, contentStart, endPoint);
|
175
167
|
}
|
176
168
|
|
169
|
+
private static final Pattern CRLF_RE = Pattern.compile("\r\n");
|
170
|
+
private static final Pattern LF_RE = Pattern.compile("[^\r]\n");
|
171
|
+
private static final String CRLF = "\r\n";
|
172
|
+
private static final String LF = "\n";
|
173
|
+
|
177
174
|
private String multilineStrip(String text) {
|
175
|
+
int crlfCount = matchCount(CRLF_RE.matcher(text));
|
176
|
+
int lfCount = matchCount(LF_RE.matcher(text));
|
177
|
+
String eol = crlfCount > lfCount ? CRLF : LF;
|
178
|
+
|
178
179
|
StringBuffer result = new StringBuffer();
|
179
|
-
for(String s : text.split("\n")) {
|
180
|
-
result.append(s.trim()).append(
|
180
|
+
for(String s : text.split("\r?\n")) {
|
181
|
+
result.append(s.trim()).append(eol);
|
181
182
|
}
|
182
183
|
return result.toString().trim();
|
183
184
|
}
|
184
185
|
|
186
|
+
private int matchCount(Matcher m) {
|
187
|
+
int count = 0;
|
188
|
+
while(m.find()) {
|
189
|
+
count++;
|
190
|
+
}
|
191
|
+
return count;
|
192
|
+
}
|
193
|
+
|
185
194
|
private String unindent(int startCol, String text) {
|
186
195
|
return Pattern.compile("^ {0," + startCol + "}", Pattern.MULTILINE).matcher(text).replaceAll("");
|
187
196
|
}
|
data/ragel/lexer.rb.rl.erb
CHANGED
@@ -85,7 +85,7 @@ module Gherkin
|
|
85
85
|
}
|
86
86
|
|
87
87
|
action end_keyword {
|
88
|
-
@keyword = data[@keyword_start...p].utf8_pack("c*").sub(/:$/,'')
|
88
|
+
@keyword = data[@keyword_start...p].utf8_pack("c*").sub(/:$/,'')
|
89
89
|
@keyword_start = nil
|
90
90
|
}
|
91
91
|
|
@@ -93,16 +93,12 @@ module Gherkin
|
|
93
93
|
@next_keyword_start = p
|
94
94
|
}
|
95
95
|
|
96
|
-
action
|
96
|
+
action start_row {
|
97
97
|
p = p - 1
|
98
|
-
|
98
|
+
current_row = []
|
99
99
|
@current_line = @line_number
|
100
100
|
}
|
101
101
|
|
102
|
-
action start_row {
|
103
|
-
current_row = []
|
104
|
-
}
|
105
|
-
|
106
102
|
action begin_cell_content {
|
107
103
|
@content_start = p
|
108
104
|
}
|
@@ -113,19 +109,15 @@ module Gherkin
|
|
113
109
|
}
|
114
110
|
|
115
111
|
action store_row {
|
116
|
-
@
|
112
|
+
@listener.row(current_row, @current_line)
|
117
113
|
}
|
118
114
|
|
119
|
-
action store_table {
|
120
|
-
if @rows.size != 0
|
121
|
-
@listener.table(@rows, @current_line)
|
122
|
-
end
|
123
|
-
}
|
124
|
-
|
125
115
|
action end_feature {
|
126
116
|
if cs < lexer_first_final
|
127
117
|
content = current_line_content(data, p)
|
128
|
-
raise
|
118
|
+
raise LexingError.new("Lexing error on line %d: '%s'." % [@line_number, content])
|
119
|
+
else
|
120
|
+
@listener.eof
|
129
121
|
end
|
130
122
|
}
|
131
123
|
|
@@ -147,9 +139,17 @@ module Gherkin
|
|
147
139
|
%% write init;
|
148
140
|
%% write exec;
|
149
141
|
end
|
150
|
-
|
142
|
+
|
143
|
+
CRLF_RE = /\r\n/
|
144
|
+
LF_RE = /[^\r]\n/
|
145
|
+
CRLF = "\r\n"
|
146
|
+
LF = "\n"
|
147
|
+
|
151
148
|
def multiline_strip(text)
|
152
|
-
text.
|
149
|
+
crlf_count = text.scan(CRLF_RE).size
|
150
|
+
lf_count = text.scan(LF_RE).size
|
151
|
+
eol = crlf_count > lf_count ? CRLF : LF
|
152
|
+
text.split(/\r?\n/).map{|s| s.strip}.join(eol).strip
|
153
153
|
end
|
154
154
|
|
155
155
|
def unindent(startcol, text)
|
data/ragel/lexer_common.rl.erb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
I18N_Examples = (<%= ragel_list(@i18n.examples_keywords) %> ':') >start_keyword %end_keyword;
|
11
11
|
|
12
12
|
EOF = '%_FEATURE_END_%'; # Explicit EOF added before scanning begins
|
13
|
-
EOL = ('\
|
13
|
+
EOL = ('\n' | '\r\n') @inc_line_number @last_newline;
|
14
14
|
|
15
15
|
FeatureHeadingEnd = EOL+ space* (I18N_Background | I18N_Scenario | I18N_ScenarioOutline | '@' | '#' | EOF) >next_keyword_start;
|
16
16
|
ScenarioHeadingEnd = EOL+ space* ( I18N_Scenario | I18N_ScenarioOutline | I18N_Step | '@' | '#' | EOF ) >next_keyword_start;
|
@@ -24,23 +24,23 @@
|
|
24
24
|
ScenarioOutlineHeading = space* I18N_ScenarioOutline %begin_content ^ScenarioOutlineHeadingEnd* :>> ScenarioOutlineHeadingEnd @store_scenario_outline_content;
|
25
25
|
ExamplesHeading = space* I18N_Examples %begin_content ^ExamplesHeadingEnd* :>> ExamplesHeadingEnd @store_examples_content;
|
26
26
|
|
27
|
-
Step = space* I18N_Step %begin_content ^EOL+ %store_step_content EOL+;
|
28
|
-
Comment = space* '#' >begin_content ^EOL* %store_comment_content EOL+;
|
27
|
+
Step = space* I18N_Step %begin_content ^EOL+ %store_step_content :> EOL+;
|
28
|
+
Comment = space* '#' >begin_content ^EOL* %store_comment_content :> EOL+;
|
29
29
|
|
30
30
|
Tag = ( '@' [^@\r\n\t ]+ >begin_content ) %store_tag_content;
|
31
31
|
Tags = space* (Tag space*)+ EOL+;
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
StartRow = space* '|' >start_row;
|
34
|
+
EndRow = EOL space* ^('|') >next_keyword_start;
|
35
35
|
Cell = '|' (any - '|')* >begin_cell_content %store_cell_content;
|
36
|
-
|
37
|
-
|
36
|
+
RowBody = space* Cell* '|' :>> (space* EOL+ space*) %store_row;
|
37
|
+
Row = StartRow :>> RowBody <: EndRow?;
|
38
38
|
|
39
39
|
StartPyString = '"""' >start_pystring space* :>> EOL;
|
40
40
|
EndPyString = (space* '"""') >next_keyword_start;
|
41
41
|
PyString = space* StartPyString %begin_pystring_content (^EOL | EOL)* :>> EndPyString %store_pystring_content space* EOL+;
|
42
42
|
|
43
|
-
Tokens = (space | EOL)* (Tags | Comment | FeatureHeading | BackgroundHeading | ScenarioHeading | ScenarioOutlineHeading | ExamplesHeading | Step |
|
43
|
+
Tokens = (space | EOL)* (Tags | Comment | FeatureHeading | BackgroundHeading | ScenarioHeading | ScenarioOutlineHeading | ExamplesHeading | Step | Row | PyString)* (space | EOL)* EOF;
|
44
44
|
|
45
45
|
main := Tokens %end_feature @!end_feature;
|
46
46
|
}%%
|
@@ -1,21 +1,21 @@
|
|
1
1
|
#encoding: utf-8
|
2
2
|
unless defined?(JRUBY_VERSION)
|
3
3
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
4
|
-
require '
|
4
|
+
require 'gherkin_lexer_en'
|
5
5
|
|
6
6
|
module Gherkin
|
7
7
|
module Lexer
|
8
8
|
describe "C Lexer" do
|
9
9
|
before do
|
10
10
|
@listener = Gherkin::SexpRecorder.new
|
11
|
-
@lexer = Gherkin::CLexer
|
11
|
+
@lexer = Gherkin::CLexer::En.new(@listener)
|
12
12
|
end
|
13
13
|
|
14
14
|
it_should_behave_like "a Gherkin lexer"
|
15
15
|
it_should_behave_like "a Gherkin lexer lexing tags"
|
16
16
|
it_should_behave_like "a Gherkin lexer lexing py_strings"
|
17
|
-
it_should_behave_like "a Gherkin lexer lexing
|
17
|
+
it_should_behave_like "a Gherkin lexer lexing rows"
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
end
|
21
|
+
end
|