gherkin 1.0.3-i386-mswin32 → 1.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.
Files changed (58) hide show
  1. data/History.txt +15 -6
  2. data/README.rdoc +15 -0
  3. data/Rakefile +1 -0
  4. data/VERSION.yml +1 -1
  5. data/features/step_definitions/gherkin_steps.rb +1 -1
  6. data/features/step_definitions/{pretty_printer_steps.rb → pretty_listener_step.rb} +2 -2
  7. data/gherkin.gemspec +24 -35
  8. data/java/Gherkin.iml +8 -14
  9. data/java/src/{gherkin → main/java/gherkin}/lexer/.gitignore +0 -0
  10. data/lib/gherkin.rb +1 -1
  11. data/lib/gherkin/c_lexer.rb +2 -2
  12. data/lib/gherkin/{format → formatter}/argument.rb +1 -1
  13. data/lib/gherkin/{tools → formatter}/colors.rb +1 -1
  14. data/lib/gherkin/{format → formatter}/monochrome_format.rb +1 -1
  15. data/lib/gherkin/{tools → formatter}/pretty_listener.rb +8 -9
  16. data/lib/gherkin/i18n.rb +27 -5
  17. data/lib/gherkin/i18n_lexer.rb +18 -44
  18. data/lib/gherkin/parser/filter_listener.rb +191 -0
  19. data/lib/gherkin/parser/parser.rb +142 -0
  20. data/lib/gherkin/parser/sexp.rb +45 -0
  21. data/lib/gherkin/parser/tag_expression.rb +46 -0
  22. data/lib/gherkin/rb_lexer.rb +2 -2
  23. data/ragel/lexer_common.rl.erb +1 -1
  24. data/spec/gherkin/{format → formatter}/argument_spec.rb +2 -2
  25. data/spec/gherkin/{tools → formatter}/colors_spec.rb +2 -2
  26. data/spec/gherkin/{tools → formatter}/pretty_listener_spec.rb +5 -5
  27. data/spec/gherkin/i18n_lexer_spec.rb +3 -3
  28. data/spec/gherkin/parser/filter_listener_spec.rb +363 -0
  29. data/spec/gherkin/parser/parser_spec.rb +35 -0
  30. data/spec/gherkin/parser/tag_expression_spec.rb +120 -0
  31. data/spec/gherkin/rb_lexer_spec.rb +0 -1
  32. data/spec/gherkin/sexp_recorder.rb +3 -3
  33. data/spec/gherkin/shared/lexer_spec.rb +19 -19
  34. data/spec/gherkin/shared/tags_spec.rb +4 -4
  35. data/tasks/bench.rake +2 -2
  36. data/tasks/compile.rake +1 -1
  37. data/tasks/ragel_task.rb +1 -1
  38. metadata +25 -36
  39. data/java/build.xml +0 -16
  40. data/java/src/gherkin/FixJava.java +0 -37
  41. data/java/src/gherkin/I18nLexer.java +0 -48
  42. data/java/src/gherkin/Lexer.java +0 -5
  43. data/java/src/gherkin/LexingError.java +0 -7
  44. data/java/src/gherkin/Listener.java +0 -29
  45. data/java/src/gherkin/Main.java +0 -17
  46. data/java/src/gherkin/ParseError.java +0 -22
  47. data/java/src/gherkin/Parser.java +0 -191
  48. data/java/src/gherkin/formatter/Argument.java +0 -39
  49. data/java/src/gherkin/formatter/ArgumentFormat.java +0 -17
  50. data/java/src/gherkin/formatter/Colors.java +0 -7
  51. data/java/src/gherkin/formatter/Formatter.java +0 -15
  52. data/java/src/gherkin/formatter/PrettyFormatter.java +0 -219
  53. data/java/src/gherkin/parser/StateMachineReader.java +0 -67
  54. data/java/test/gherkin/formatter/ArgumentTest.java +0 -17
  55. data/lib/gherkin/lexer.rb +0 -35
  56. data/lib/gherkin/parser.rb +0 -19
  57. data/lib/gherkin/rb_parser.rb +0 -125
  58. data/spec/gherkin/parser_spec.rb +0 -33
@@ -1,48 +0,0 @@
1
- package gherkin;
2
-
3
- import java.util.regex.Matcher;
4
- import java.util.regex.Pattern;
5
-
6
- public class I18nLexer implements Lexer {
7
- private static final Pattern LANGUAGE_PATTERN = Pattern.compile("language\\s*:\\s*(.*)");
8
- private final Listener listener;
9
- private String i18nLanguage;
10
-
11
- public I18nLexer(Listener listener) {
12
- this.listener = listener;
13
- }
14
-
15
- /**
16
- * @return the i18n language code from the previous scanned source.
17
- */
18
- public String getI18nLanguage() {
19
- return i18nLanguage;
20
- }
21
-
22
- public void scan(CharSequence source) {
23
- createDelegate(source).scan(source);
24
- }
25
-
26
- private Lexer createDelegate(CharSequence source) {
27
- i18nLanguage = lang(source);
28
- String i18nLanguage = this.i18nLanguage.replaceAll("[\\s-]", "").toLowerCase();
29
- String i18nLexerClassName = i18nLanguage.substring(0,1).toUpperCase() + i18nLanguage.substring(1);
30
- String qualifiedI18nLexerClassName = "gherkin.lexer." + i18nLexerClassName;
31
- try {
32
- Class<?> delegateClass = Class.forName(qualifiedI18nLexerClassName);
33
- return (Lexer) delegateClass.getConstructor(Listener.class).newInstance(listener);
34
- } catch (Exception e) {
35
- throw new RuntimeException("Couldn't load lexer class: " + qualifiedI18nLexerClassName, e);
36
- }
37
- }
38
-
39
- private String lang(CharSequence source) {
40
- String lineOne = source.toString().split("\\n")[0];
41
- Matcher matcher = LANGUAGE_PATTERN.matcher(lineOne);
42
- if(matcher.find()) {
43
- return matcher.group(1);
44
- } else {
45
- return "en";
46
- }
47
- }
48
- }
@@ -1,5 +0,0 @@
1
- package gherkin;
2
-
3
- public interface Lexer {
4
- public void scan(CharSequence inputSequence);
5
- }
@@ -1,7 +0,0 @@
1
- package gherkin;
2
-
3
- public class LexingError extends RuntimeException {
4
- public LexingError(String message) {
5
- super(message);
6
- }
7
- }
@@ -1,29 +0,0 @@
1
- package gherkin;
2
-
3
- import java.util.List;
4
-
5
- public interface Listener {
6
- void tag(String name, int line);
7
-
8
- void comment(String content, int line);
9
-
10
- void feature(String keyword, String name, int line);
11
-
12
- void background(String keyword, String name, int line);
13
-
14
- void scenario(String keyword, String name, int line);
15
-
16
- void scenario_outline(String keyword, String name, int line);
17
-
18
- void examples(String keyword, String name, int line);
19
-
20
- void step(String keyword, String name, int line);
21
-
22
- void row(List<String> row, int line);
23
-
24
- void py_string(String string, int line);
25
-
26
- void eof();
27
-
28
- void syntax_error(String state, String event, List<String> legalEvents, int line);
29
- }
@@ -1,17 +0,0 @@
1
- package gherkin;
2
-
3
- import gherkin.formatter.PrettyFormatter;
4
-
5
- import java.io.FileReader;
6
- import java.io.IOException;
7
-
8
- public class Main {
9
- public static void main(String[] args) throws IOException {
10
- Parser p = new Parser(new PrettyFormatter(System.out, true));
11
- Lexer l = new I18nLexer(p);
12
-
13
- CharSequence input = FixJava.readReader(new FileReader(args[0]));
14
- l.scan(input);
15
- }
16
-
17
- }
@@ -1,22 +0,0 @@
1
- package gherkin;
2
-
3
- import java.util.List;
4
-
5
- public class ParseError extends RuntimeException {
6
- private final String state;
7
- private final List<String> expectedEvents;
8
-
9
- public ParseError(String state, String event, List<String> expectedEvents, int line) {
10
- super("Parse error on line " + line + ". Found " + event + " when expecting one of: " + FixJava.join(expectedEvents, ", ") + ". (Current state: " + state + ").");
11
- this.state = state;
12
- this.expectedEvents = expectedEvents;
13
- }
14
-
15
- public String state() {
16
- return state;
17
- }
18
-
19
- public List<String> expectedEvents() {
20
- return expectedEvents;
21
- }
22
- }
@@ -1,191 +0,0 @@
1
- package gherkin;
2
-
3
- import gherkin.parser.StateMachineReader;
4
-
5
- import java.util.*;
6
- import java.util.regex.Matcher;
7
- import java.util.regex.Pattern;
8
-
9
- public class Parser implements Listener {
10
- List<Machine> machines = new ArrayList<Machine>();
11
-
12
- private Listener listener;
13
- private boolean throwOnError;
14
-
15
- public Parser(Listener listener) {
16
- this(listener, true);
17
- }
18
-
19
- public Parser(Listener listener, boolean throwOnError) {
20
- this(listener, throwOnError, "root");
21
- }
22
-
23
- public Parser(Listener listener, boolean throwOnError, String machineName) {
24
- this.listener = listener;
25
- this.throwOnError = throwOnError;
26
- pushMachine(machineName);
27
- }
28
-
29
- private void pushMachine(String machineName) {
30
- machines.add(new Machine(this, machineName));
31
- }
32
-
33
- private void popMachine() {
34
- machines.remove(machines.size() - 1);
35
- }
36
-
37
- public void tag(String name, int line) {
38
- if (event("tag", line))
39
- listener.tag(name, line);
40
- }
41
-
42
- public void py_string(String string, int line) {
43
- if (event("py_string", line))
44
- listener.py_string(string, line);
45
- }
46
-
47
- public void feature(String keyword, String name, int line) {
48
- if (event("feature", line))
49
- listener.feature(keyword, name, line);
50
- }
51
-
52
- public void background(String keyword, String name, int line) {
53
- if (event("background", line))
54
- listener.background(keyword, name, line);
55
- }
56
-
57
- public void scenario(String keyword, String name, int line) {
58
- if (event("scenario", line))
59
- listener.scenario(keyword, name, line);
60
- }
61
-
62
- public void scenario_outline(String keyword, String name, int line) {
63
- if (event("scenario_outline", line))
64
- listener.scenario_outline(keyword, name, line);
65
- }
66
-
67
- public void examples(String keyword, String name, int line) {
68
- if (event("examples", line))
69
- listener.examples(keyword, name, line);
70
- }
71
-
72
- public void step(String keyword, String name, int line) {
73
- if (event("step", line))
74
- listener.step(keyword, name, line);
75
- }
76
-
77
- public void comment(String content, int line) {
78
- if (event("comment", line))
79
- listener.comment(content, line);
80
- }
81
-
82
- public void row(List<String> row, int line) {
83
- if (event("row", line))
84
- listener.row(row, line);
85
- }
86
-
87
- public void eof() {
88
- if (event("eof", 1))
89
- listener.eof();
90
- }
91
-
92
- public void syntax_error(String name, String event, List<String> strings, int line) {
93
- }
94
-
95
- private boolean event(String event, int line) {
96
- try {
97
- machine().event(event, line);
98
- return true;
99
- } catch (ParseError e) {
100
- if (throwOnError) {
101
- throw e;
102
- } else {
103
- listener.syntax_error(e.state(), event, e.expectedEvents(), line);
104
- return false;
105
- }
106
- }
107
- }
108
-
109
- private Machine machine() {
110
- return machines.get(machines.size() - 1);
111
- }
112
-
113
- private static class Machine {
114
- private static final Pattern PUSH = Pattern.compile("push\\((.+)\\)");
115
- private static final Map<String, Map<String, Map<String, String>>> TRANSITION_MAPS = new HashMap<String, Map<String, Map<String, String>>>();
116
-
117
- private final Parser parser;
118
- private final String name;
119
- private String state;
120
- private Map<String, Map<String, String>> transitionMap;
121
-
122
- public Machine(Parser parser, String name) {
123
- this.parser = parser;
124
- this.name = name;
125
- this.state = name;
126
- this.transitionMap = transitionMap(name);
127
- }
128
-
129
- public void event(String event, int line) {
130
- Map<String, String> states = transitionMap.get(state);
131
- if (states == null) {
132
- throw new RuntimeException("Unknown state: " + state + " for machine " + name);
133
- }
134
- String newState = states.get(event);
135
- if (newState == null) {
136
- throw new RuntimeException("Unknown transition: " + event + " among " + states + " for machine " + name + " in state " + state);
137
- }
138
- if ("E".equals(newState)) {
139
- throw new ParseError(state, event, expectedEvents(), line);
140
- } else {
141
- Matcher push = PUSH.matcher(newState);
142
- if (push.matches()) {
143
- parser.pushMachine(push.group(1));
144
- parser.event(event, line);
145
- } else if ("pop()".equals(newState)) {
146
- parser.popMachine();
147
- parser.event(event, line);
148
- } else {
149
- state = newState;
150
- }
151
- }
152
- }
153
-
154
- private List<String> expectedEvents() {
155
- List<String> result = new ArrayList<String>();
156
- for (String event : transitionMap.get(state).keySet()) {
157
- if (!transitionMap.get(state).get(event).equals("E")) {
158
- result.add(event);
159
- }
160
- }
161
- Collections.sort(result);
162
- result.remove("eof");
163
- return result;
164
- }
165
-
166
- private Map<String, Map<String, String>> transitionMap(String name) {
167
- Map<String, Map<String, String>> map = TRANSITION_MAPS.get(name);
168
- if(map == null) {
169
- map = buildTransitionMap(name);
170
- TRANSITION_MAPS.put(name, map);
171
- }
172
- return map;
173
- }
174
-
175
- private Map<String, Map<String, String>> buildTransitionMap(String name) {
176
- Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
177
- List<List<String>> transitionTable = new StateMachineReader(name).transitionTable();
178
- List<String> events = transitionTable.get(0).subList(1, transitionTable.get(0).size());
179
- for (List<String> actions : transitionTable.subList(1, transitionTable.size())) {
180
- Map<String, String> transitions = new HashMap<String, String>();
181
- int col = 1;
182
- for (String event : events) {
183
- transitions.put(event, actions.get(col++));
184
- }
185
- String state = actions.get(0);
186
- result.put(state, transitions);
187
- }
188
- return result;
189
- }
190
- }
191
- }
@@ -1,39 +0,0 @@
1
- package gherkin.formatter;
2
-
3
- import java.io.UnsupportedEncodingException;
4
- import java.util.List;
5
-
6
- public class Argument {
7
- private final int byteOffset;
8
- private final byte[] val;
9
-
10
- public Argument(int byteOffset, String val) throws UnsupportedEncodingException {
11
- this.byteOffset = byteOffset;
12
- this.val = val.getBytes("UTF-8");
13
- }
14
-
15
- public static String format(String string, ArgumentFormat format, List<Argument> arguments) throws UnsupportedEncodingException {
16
- return format(string, format, (Argument[]) arguments.toArray(new Argument[arguments.size()]));
17
- }
18
-
19
- public static String format(String string, ArgumentFormat format, Argument... arguments) throws UnsupportedEncodingException {
20
- byte[] result = string.getBytes("UTF-8");
21
- int offset = 0, pastOffset = 0;
22
- for (Argument argument : arguments) {
23
- if (argument.byteOffset != -1 && argument.byteOffset >= pastOffset) {
24
- byte[] replacement = format.formatArgument(argument.val);
25
- int delta = replacement.length - argument.val.length;
26
- byte[] newResult = new byte[result.length + delta];
27
-
28
- System.arraycopy(result, 0, newResult, 0, argument.byteOffset+offset);
29
- System.arraycopy(replacement, 0, newResult, argument.byteOffset+offset, replacement.length);
30
- int n = argument.byteOffset + argument.val.length + offset;
31
- System.arraycopy(result, n, newResult, argument.byteOffset + replacement.length, result.length - n);
32
-
33
- offset += delta;
34
- result = newResult;
35
- }
36
- }
37
- return new String(result, "UTF-8");
38
- }
39
- }
@@ -1,17 +0,0 @@
1
- package gherkin.formatter;
2
-
3
- import java.io.UnsupportedEncodingException;
4
-
5
- public class ArgumentFormat {
6
- private final String prefix;
7
- private final String suffix;
8
-
9
- public ArgumentFormat(String prefix, String suffix) {
10
- this.prefix = prefix;
11
- this.suffix = suffix;
12
- }
13
-
14
- public byte[] formatArgument(byte[] argument) throws UnsupportedEncodingException {
15
- return (prefix + new String(argument, "UTF-8") + suffix).getBytes("UTF-8");
16
- }
17
- }
@@ -1,7 +0,0 @@
1
- package gherkin.formatter;
2
-
3
- public class Colors {
4
- public static String comments(String s, boolean monochrome) {
5
- return s;
6
- }
7
- }
@@ -1,15 +0,0 @@
1
- package gherkin.formatter;
2
-
3
- import gherkin.Listener;
4
-
5
- import java.util.List;
6
-
7
- /**
8
- * This interface extends the Listener interface with extra methods for formatting
9
- * Gherkin features during execution.
10
- */
11
- public interface Formatter extends Listener {
12
- void scenario(String keyword, String name, int line, String location);
13
- void step(String keyword, String name, int line, String status, List<Argument> arguments, String location);
14
- void flushTable();
15
- }
@@ -1,219 +0,0 @@
1
- package gherkin.formatter;
2
-
3
- import java.io.OutputStream;
4
- import java.io.PrintWriter;
5
- import java.util.ArrayList;
6
- import java.util.Collections;
7
- import java.util.List;
8
- import java.util.regex.Pattern;
9
-
10
- import static gherkin.FixJava.join;
11
- import static gherkin.formatter.Colors.*;
12
-
13
- public class PrettyFormatter implements Formatter {
14
- private final PrintWriter out;
15
- private final boolean monochrome;
16
- private int maxStepLength = 0;
17
- private int[] stepLengths;
18
- private int stepIndex;
19
- private List<List<String>> rows;
20
- private List<String> comments;
21
- private List<String> tags;
22
-
23
- public PrettyFormatter(OutputStream out, boolean monochrome) {
24
- this.out = new PrintWriter(out);
25
- this.monochrome = monochrome;
26
- }
27
-
28
- public void tag(String name, int line) {
29
- if (tags == null) tags = new ArrayList<String>();
30
- tags.add('@' + name);
31
- }
32
-
33
- public void comment(String content, int line) {
34
- if (comments == null) comments = new ArrayList<String>();
35
- comments.add(content);
36
- }
37
-
38
- public void feature(String keyword, String name, int line) {
39
- printCommentsAndTags("");
40
- out.println(keyword + ": " + indent(name, " "));
41
- out.flush();
42
- }
43
-
44
- public void background(String keyword, String name, int line) {
45
- out.println();
46
- printCommentsAndTags(" ");
47
- out.println(" " + keyword + ": " + name);
48
- }
49
-
50
- public void scenario(String keyword, String name, int line) {
51
- scenario(keyword, name, line, null);
52
- }
53
-
54
- public void scenario(String keyword, String name, int line, String location) {
55
- flushTable();
56
- out.println();
57
- printCommentsAndTags(" ");
58
- out.println(" " + keyword + ": " + indent(name, " ") + indentedScenarioLocation(keyword, name, location));
59
- out.flush();
60
- }
61
-
62
- public void scenario_outline(String keyword, String name, int line) {
63
- flushTable();
64
- out.println();
65
- printCommentsAndTags(" ");
66
- out.println(" " + keyword + ": " + name);
67
- }
68
-
69
- public void examples(String keyword, String name, int line) {
70
- flushTable();
71
- out.println();
72
- printCommentsAndTags(" ");
73
- out.println(" " + keyword + ": " + name);
74
- }
75
-
76
- public void step(String keyword, String name, int line, String status, List<Argument> arguments, String location) {
77
- flushTable();
78
- out.println(" " + keyword + indent(name, " ") + indentedStepLocation(location));
79
- out.flush();
80
- }
81
-
82
- public void flushTable() {
83
- if (rows == null) return;
84
- int columnCount = rows.get(0).size();
85
- int[][] cellLengths = new int[rows.size()][columnCount];
86
- int[] maxLengths = new int[columnCount];
87
- for (int i = 0; i < rows.size(); i++) {
88
- for (int j = 0; j < columnCount; j++) {
89
- int length = rows.get(i).get(j).length();
90
- cellLengths[i][j] = length;
91
- maxLengths[j] = Math.max(maxLengths[j], length);
92
- }
93
- }
94
-
95
- for (int i = 0; i < rows.size(); i++) {
96
- out.write(" | ");
97
- for (int j = 0; j < columnCount; j++) {
98
- out.write(rows.get(i).get(j));
99
- padSpace(maxLengths[j] - cellLengths[i][j]);
100
- if (j < columnCount - 1) {
101
- out.write(" | ");
102
- } else {
103
- out.write(" |");
104
- }
105
- }
106
- out.println();
107
- }
108
- out.flush();
109
- rows = null;
110
- }
111
-
112
- public void step(String keyword, String name, int line) {
113
- step(keyword, name, line, null, Collections.<Argument>emptyList(), null);
114
- }
115
-
116
- public void row(List<String> row, int line) {
117
- if (rows == null) rows = new ArrayList<List<String>>();
118
- rows.add(row);
119
- }
120
-
121
- public void py_string(String string, int line) {
122
- out.println(" \"\"\"");
123
- out.print(Pattern.compile("^", Pattern.MULTILINE).matcher(string).replaceAll(" "));
124
- out.println("\n \"\"\"");
125
- }
126
-
127
- public void eof() {
128
- flushTable();
129
- out.flush();
130
- }
131
-
132
- public void syntax_error(String state, String event, List<String> legalEvents, int line) {
133
- out.println("Syntax error:" + state + ' ' + event);
134
- }
135
-
136
- public void steps(List<List<String>> steps) {
137
- stepLengths = new int[steps.size()];
138
- int i = 0;
139
- for (List<String> step : steps) {
140
- int stepLength = step.get(0).length() + step.get(1).length();
141
- stepLengths[i++] = stepLength;
142
- maxStepLength = Math.max(maxStepLength, stepLength);
143
- }
144
- stepIndex = -1;
145
- }
146
-
147
- private void padSpace(int indent, StringBuffer buffer) {
148
- for (int i = 0; i < indent; i++) {
149
- buffer.append(" ");
150
- }
151
- }
152
-
153
- private void padSpace(int indent) {
154
- for (int i = 0; i < indent; i++) {
155
- out.write(" ");
156
- }
157
- }
158
-
159
- private void printCommentsAndTags(String indent) {
160
- printComments(indent);
161
- printTags(indent);
162
- }
163
-
164
- private boolean printComments(String indent) {
165
- if (comments == null) return false;
166
- for (String comment : comments) {
167
- out.print(indent);
168
- out.println(comment);
169
- }
170
- out.flush();
171
- comments = null;
172
- return true;
173
- }
174
-
175
- private boolean printTags(String indent) {
176
- if (tags == null) return false;
177
- out.print(indent);
178
- out.println(join(tags, " "));
179
- out.flush();
180
- tags = null;
181
- return true;
182
- }
183
-
184
- private String indent(String name, String indentation) {
185
- String indent = "";
186
- StringBuilder sb = new StringBuilder();
187
- String[] lines = name.split("\\n");
188
- for (int i = 0; i < lines.length; i++) {
189
- sb.append(indent).append(lines[i]);
190
- if (i < lines.length - 1) {
191
- sb.append("\n");
192
- }
193
- indent = indentation;
194
- }
195
- return sb.toString();
196
- }
197
-
198
- private String indentedScenarioLocation(String keyword, String name, String location) {
199
- if (location == null || "".equals(location)) return "";
200
- int l = keyword.length() + name.length();
201
- maxStepLength = Math.max(maxStepLength, l);
202
- int indent = maxStepLength - l;
203
-
204
- StringBuffer buffer = new StringBuffer();
205
- padSpace(indent, buffer);
206
- buffer.append(" ").append(comments("# " + location, monochrome));
207
- return buffer.toString();
208
- }
209
-
210
- private String indentedStepLocation(String location) {
211
- if (location == null || "".equals(location)) return "";
212
- int indent = maxStepLength - stepLengths[stepIndex += 1];
213
-
214
- StringBuffer buffer = new StringBuffer();
215
- padSpace(indent, buffer);
216
- buffer.append(" ").append(comments("# " + location, monochrome));
217
- return buffer.toString();
218
- }
219
- }