Skip to content

[Java] Make CucumberExpressionParser.parse public #340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
[Java] Make CucumberExpressionParser.parse public ([#340](https://github.com/cucumber/cucumber-expressions/pull/340))

## [18.0.1] - 2024-10-28
### Fixed
Expand Down
57 changes: 33 additions & 24 deletions java/src/main/java/io/cucumber/cucumberexpressions/Ast.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@
import java.util.Objects;
import java.util.StringJoiner;

import static java.util.Arrays.asList;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;

final class Ast {
public final class Ast {

private static final char escapeCharacter = '\\';
private static final char alternationCharacter = '/';
private static final char beginParameterCharacter = '{';
private static final char endParameterCharacter = '}';
private static final char beginOptionalCharacter = '(';
private static final char endOptionalCharacter = ')';
public static final char escapeCharacter = '\\';
public static final char alternationCharacter = '/';
public static final char beginParameterCharacter = '{';
public static final char endParameterCharacter = '}';
public static final char beginOptionalCharacter = '(';
public static final char endOptionalCharacter = ')';

interface Located {
int start();
Expand All @@ -24,7 +23,7 @@ interface Located {

}

static final class Node implements Located {
public static final class Node implements Located {

private final Type type;
private final List<Node> nodes;
Expand All @@ -33,11 +32,11 @@ static final class Node implements Located {
private final int end;

Node(Type type, int start, int end, String token) {
this(type, start, end, null, token);
this(type, start, end, null, requireNonNull(token));
}

Node(Type type, int start, int end, List<Node> nodes) {
this(type, start, end, nodes, null);
this(type, start, end, requireNonNull(nodes), null);
}

private Node(Type type, int start, int end, List<Node> nodes, String token) {
Expand All @@ -48,7 +47,7 @@ private Node(Type type, int start, int end, List<Node> nodes, String token) {
this.end = end;
}

enum Type {
public enum Type {
TEXT_NODE,
OPTIONAL_NODE,
ALTERNATION_NODE,
Expand All @@ -65,14 +64,24 @@ public int end() {
return end;
}

List<Node> nodes() {
/**
* @return child nodes, {@code null} if a leaf-node
*/
public List<Node> nodes() {
return nodes;
}

Type type() {
public Type type() {
return type;
}

/**
* @return the text contained with in this node, {@code null} if not a leaf-node
*/
public String token() {
return token;
}

String text() {
if (nodes == null)
return token;
Expand Down Expand Up @@ -106,13 +115,13 @@ private StringBuilder toString(int depth) {
if (nodes != null) {
sb.append(", \"nodes\": ");
if (!nodes.isEmpty()) {
StringBuilder padding = new StringBuilder();
for (int i = 0; i < depth; i++) {
padding.append(" ");
}
sb.append(nodes.stream()
.map(node -> node.toString(depth + 1))
.collect(joining(",\n", "[\n", "\n" +padding + "]")));
StringBuilder padding = new StringBuilder();
for (int i = 0; i < depth; i++) {
padding.append(" ");
}
sb.append(nodes.stream()
.map(node -> node.toString(depth + 1))
.collect(joining(",\n", "[\n", "\n" + padding + "]")));

} else {
sb.append("[]");
Expand Down Expand Up @@ -224,10 +233,10 @@ public int hashCode() {

@Override
public String toString() {
return new StringJoiner(", ", "" + "{", "}")
return new StringJoiner(", ", "{", "}")
.add("\"type\": \"" + type + "\"")
.add("\"start\": " + start + "")
.add("\"end\": " + end + "")
.add("\"start\": " + start)
.add("\"end\": " + end)
.add("\"text\": \"" + text + "\"")
.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;

final class CucumberExpressionParser {
/**
* A parser for Cucumber expressions
*/
public final class CucumberExpressionParser {

/*
* text := whitespace | ')' | '}' | .
Expand Down Expand Up @@ -160,7 +163,13 @@ final class CucumberExpressionParser {
)
);

Node parse(String expression) {
/**
* Parses as Cucumber expression into an AST of {@link Node nodes}.
* @param expression the expression to parse
* @return an AST of nodes
* @throws CucumberExpressionException if the expression could not be parsed
*/
public Node parse(String expression) {
CucumberExpressionTokenizer tokenizer = new CucumberExpressionTokenizer();
List<Token> tokens = tokenizer.tokenize(expression);
Result result = cucumberExpressionParser.parse(expression, tokens, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ final class GroupBuilder {
private final List<GroupBuilder> groupBuilders = new ArrayList<>();
private boolean capturing = true;
private String source;
private int startIndex;
private final int startIndex;
private int endIndex;

GroupBuilder(int startIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public List<Argument<?>> match(String text, Type... typeHints) {

// When there is a conflict between the type hint from the regular expression and the method
// prefer the parameter type associated with the regular expression. This ensures we will
// use the internal/user registered parameter transformer rather then the default.
// use the internal/user registered parameter transformer rather than the default.
//
// Unless the parameter type indicates it is the stronger type hint.
if (parameterType != null && hasTypeHint && !parameterType.useRegexpMatchAsStrongTypeHint()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Group match(CharSequence s) {
return groupBuilder.build(matcher, IntStream.rangeClosed(0, matcher.groupCount()).iterator());
}

public GroupBuilder getGroupBuilder() {
GroupBuilder getGroupBuilder() {
return groupBuilder;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.file.DirectoryStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
Expand All @@ -38,7 +39,10 @@ class CucumberExpressionTest {

private static List<Path> acceptance_tests_pass() throws IOException {
List<Path> paths = new ArrayList<>();
newDirectoryStream(Paths.get("..", "testdata", "cucumber-expression", "matching")).forEach(paths::add);
Path path = Paths.get("..", "testdata", "cucumber-expression", "matching");
try (DirectoryStream<Path> directories = newDirectoryStream(path)){
directories.forEach(paths::add);
}
paths.sort(Comparator.naturalOrder());
return paths;
}
Expand Down
Loading