CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-cucumber--gherkin

Gherkin parser and compiler for Java providing complete parsing of Gherkin feature files into AST and executable Pickles for BDD testing frameworks

Pending
Overview
Eval results
Files

parsing.mddocs/

High-Level Parsing

The GherkinParser provides the main entry point for parsing Gherkin feature files into structured data formats. It supports multiple input sources and configurable output options through a builder pattern.

Capabilities

GherkinParser Creation

Create and configure a GherkinParser instance using the builder pattern.

/**
 * Create a new GherkinParser builder
 * @return Builder instance for configuration
 */
public static GherkinParser.Builder builder();

/**
 * Builder for configuring GherkinParser options
 */
public static final class Builder {
    /** 
     * Configure whether to include source information in output
     * @param includeSource true to include source data (default: true)
     * @return this builder for chaining
     */
    public Builder includeSource(boolean includeSource);
    
    /** 
     * Configure whether to include GherkinDocument AST in output
     * @param includeGherkinDocument true to include AST (default: true)
     * @return this builder for chaining
     */
    public Builder includeGherkinDocument(boolean includeGherkinDocument);
    
    /** 
     * Configure whether to include compiled Pickles in output  
     * @param includePickles true to include pickles (default: true)
     * @return this builder for chaining
     */
    public Builder includePickles(boolean includePickles);
    
    /** 
     * Set custom ID generator for element identification
     * @param idGenerator custom ID generator implementation
     * @return this builder for chaining
     */
    public Builder idGenerator(IdGenerator idGenerator);
    
    /**
     * Build the configured GherkinParser instance
     * @return configured parser ready for use
     */
    public GherkinParser build();
}

File Parsing

Parse Gherkin content from various sources including files, streams, and byte arrays.

/**
 * Parse a Gherkin feature file from filesystem path
 * @param source Path to the .feature file
 * @return Stream of Envelope messages containing parse results
 * @throws IOException if file cannot be read
 */
public Stream<Envelope> parse(Path source) throws IOException;

/**
 * Parse Gherkin content from InputStream
 * @param uri URI identifier for the source (used in messages)
 * @param source InputStream containing Gherkin content
 * @return Stream of Envelope messages containing parse results
 * @throws IOException if stream cannot be read
 */
public Stream<Envelope> parse(String uri, InputStream source) throws IOException;

/**
 * Parse Gherkin content from byte array
 * @param uri URI identifier for the source (used in messages)
 * @param source byte array containing Gherkin content
 * @return Stream of Envelope messages containing parse results
 */
public Stream<Envelope> parse(String uri, byte[] source);

/**
 * Parse Gherkin content from existing Envelope message
 * @param envelope Envelope containing Source message with Gherkin content
 * @return Stream of Envelope messages containing parse results
 */
public Stream<Envelope> parse(Envelope envelope);

Usage Examples:

// Parse from file path
GherkinParser parser = GherkinParser.builder().build();
Stream<Envelope> messages = parser.parse(Paths.get("features/login.feature"));

// Parse from string content
String gherkinContent = """
    Feature: User Login
    Scenario: Valid credentials
      Given a user exists
      When they enter valid credentials
      Then they should be logged in
    """;
Stream<Envelope> messages = parser.parse("test.feature", 
    gherkinContent.getBytes(StandardCharsets.UTF_8));

// Configure parser options
GherkinParser customParser = GherkinParser.builder()
    .includeSource(false)           // Skip source in output
    .includePickles(true)           // Include executable pickles
    .idGenerator(() -> "custom-id") // Use custom ID generation
    .build();

Message Processing

Process the stream of Envelope messages returned by parsing operations.

// Core message types returned in Envelope stream
interface Envelope {
    Optional<Source> getSource();           // Original source content
    Optional<GherkinDocument> getGherkinDocument(); // Parsed AST
    Optional<Pickle> getPickle();           // Executable scenario
    Optional<ParseError> getParseError();   // Parse error details
}

interface GherkinDocument {
    String getUri();
    Optional<Feature> getFeature();
    List<Comment> getComments();
}

interface Pickle {
    String getId();
    String getUri(); 
    String getName();
    String getLanguage();
    List<PickleStep> getSteps();
    List<PickleTag> getTags();
    List<String> getAstNodeIds();
}

Message Processing Examples:

// Process all message types
parser.parse(featureFile).forEach(envelope -> {
    // Handle source information
    envelope.getSource().ifPresent(source -> 
        System.out.println("Parsing: " + source.getUri()));
    
    // Handle parsed AST
    envelope.getGherkinDocument().ifPresent(doc -> {
        doc.getFeature().ifPresent(feature ->
            System.out.println("Feature: " + feature.getName()));
    });
    
    // Handle executable scenarios
    envelope.getPickle().ifPresent(pickle -> {
        System.out.println("Scenario: " + pickle.getName());
        pickle.getSteps().forEach(step ->
            System.out.println("  " + step.getText()));
    });
    
    // Handle parse errors
    envelope.getParseError().ifPresent(error ->
        System.err.println("Parse error: " + error.getMessage()));
});

// Collect only pickles for test execution
List<Pickle> scenarios = parser.parse(featureFile)
    .map(Envelope::getPickle)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .collect(Collectors.toList());

// Extract feature metadata
Optional<Feature> feature = parser.parse(featureFile)
    .map(Envelope::getGherkinDocument)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .map(GherkinDocument::getFeature)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .findFirst();

Error Handling

Handle parsing errors and exceptions during Gherkin processing.

// Exception types thrown by the parser (package-private but visible to users)
ParserException.NoSuchLanguageException    // Unsupported language code
ParserException.UnexpectedTokenException   // Syntax errors in Gherkin
ParserException.UnexpectedEOFException     // Premature end of file
ParserException.CompositeParserException   // Multiple parsing errors
ParserException.AstBuilderException        // AST construction failures
GherkinException                           // General processing errors

Error Handling Examples:

import io.cucumber.gherkin.ParserException;
import io.cucumber.gherkin.GherkinException;

try {
    Stream<Envelope> messages = parser.parse(featureFile);
    
    // Check for parse errors in the stream
    List<ParseError> errors = messages
        .map(Envelope::getParseError)
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());
        
    if (!errors.isEmpty()) {
        errors.forEach(error -> 
            System.err.println("Parse error at " + 
                error.getSource().getLocation().getLine() + ": " + 
                error.getMessage()));
    }
    
} catch (ParserException.NoSuchLanguageException e) {
    System.err.println("Unsupported language in feature file: " + e.getMessage());
    
} catch (ParserException.UnexpectedTokenException e) {
    System.err.println("Syntax error in Gherkin at line " + 
        e.location.getLine() + ": " + e.getMessage());
    System.err.println("Expected: " + String.join(", ", e.expectedTokenTypes));
    
} catch (ParserException.CompositeParserException e) {
    System.err.println("Multiple parsing errors found:");
    e.errors.forEach(error -> 
        System.err.println("  - " + error.getMessage()));
        
} catch (GherkinException e) {
    System.err.println("General parsing error: " + e.getMessage());
    if (e.getCause() != null) {
        System.err.println("Caused by: " + e.getCause().getMessage());
    }
    
} catch (IOException e) {
    System.err.println("Failed to read feature file: " + e.getMessage());
}

Language Error Example:

// This will throw NoSuchLanguageException
String invalidLanguageFeature = """
    # language: xyz-invalid
    Feature: Test
      Scenario: Example
        Given something
    """;
    
try {
    parser.parse("test.feature", invalidLanguageFeature.getBytes());
} catch (ParserException.NoSuchLanguageException e) {
    System.err.println("Language 'xyz-invalid' is not supported");
    
    // Show available languages
    GherkinDialectProvider provider = new GherkinDialectProvider();
    System.out.println("Available languages: " + provider.getLanguages());
}

Install with Tessl CLI

npx tessl i tessl/maven-io-cucumber--gherkin

docs

index.md

languages.md

parsing.md

tile.json