Skip to content
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

Refresh README elements including broken links #240

Merged
merged 4 commits into from
Apr 1, 2024
Merged
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
125 changes: 71 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ Gherkin is a parser and compiler for the Gherkin language.

Gherkin is currently implemented for the following platforms (in order of birthday):

- [.NET](./dotnet) - Actively tested -> [workflow](./.github/workflows/test-dotnet.yml)
- [Java](./java) - Actively tested -> [workflow](./.github/workflows/test-java.yml)
- [JavaScript](./javascript) - Actively tested -> [workflow](./.github/workflows/test-javascript.yml)
- [Ruby](./ruby) - Actively tested -> [workflow](./.github/workflows/test-ruby.yml)
- [Go](./go) - Actively tested -> [workflow](./.github/workflows/test-go.yml)
- [Python](./python) - Actively tested -> [workflow](./.github/workflows/test-python.yml)
- [C](./c) - Actively tested -> [workflow](./.github/workflows/test-c.yml)
- [.NET](./dotnet) - [![test dotnet workflow](https://github.com/cucumber/gherkin/actions/workflows/test-dotnet.yml/badge.svg)](./.github/workflows/test-dotnet.yml)
- [Java](./java) - [![test java workflow](https://github.com/cucumber/gherkin/actions/workflows/test-java.yml/badge.svg)](./.github/workflows/test-java.yml)
- [JavaScript](./javascript) - [![test javascript workflow](https://github.com/cucumber/gherkin/actions/workflows/test-javascript.yml/badge.svg)](./.github/workflows/test-javascript.yml)
- [Ruby](./ruby) - [![test ruby workflow](https://github.com/cucumber/gherkin/actions/workflows/test-ruby.yml/badge.svg)](./.github/workflows/test-ruby.yml)
- [Go](./go) - [![test go workflow](https://github.com/cucumber/gherkin/actions/workflows/test-go.yml/badge.svg)](./.github/workflows/test-go.yml)
- [Python](./python) - [![test python workflow](https://github.com/cucumber/gherkin/actions/workflows/test-python.yml/badge.svg)](./.github/workflows/test-python.yml)
- [C](./c) - [![test c workflow](https://github.com/cucumber/gherkin/actions/workflows/test-c.yml/badge.svg)](./.github/workflows/test-c.yml)
- [Objective-C](./objective-c) - _Currently not actively tested, requires maintenance_
- [Perl](./perl) - Actively tested -> [workflow](./.github/workflows/test-perl.yml)
- [PHP](./php) - Actively tested -> [workflow](./.github/workflows/test-php.yml)
- [Dart](./dart) - Actively tested -> [workflow](./.github/workflows/test-dart.yml)
- [C++](./cpp) - Actively tested -> [workflow](./.github/workflows/test-cpp.yml)
- [Perl](./perl) - [![test perl workflow](https://github.com/cucumber/gherkin/actions/workflows/test-perl.yml/badge.svg)](./.github/workflows/test-perl.yml)
- [PHP](./php) - [![test php workflow](https://github.com/cucumber/gherkin/actions/workflows/test-php.yml/badge.svg)](./.github/workflows/test-php.yml)
- [Dart](./dart) - [![test dart workflow](https://github.com/cucumber/gherkin/actions/workflows/test-dart.yml/badge.svg)](./.github/workflows/test-dart.yml)
- [C++](./cpp) - [![test cpp workflow](https://github.com/cucumber/gherkin/actions/workflows/test-cpp.yml/badge.svg)](./.github/workflows/test-cpp.yml)

The CI will run using the linked workflow when that specific language implementation is changed

Expand Down Expand Up @@ -44,7 +44,7 @@ Gherkin can be used either through its command line interface (CLI) or as a
library.

It is designed to be used in conjunction with other tools such as Cucumber
which consumes the output from the CLI or library as [Cucumber Messages](../messages).
which consumes the output from the CLI or library as [Cucumber Messages](https://github.com/cucumber/messages).

### Library

Expand All @@ -58,21 +58,24 @@ that is easy to use. See the CLI implementations to get an idea of how to use it

Alternatively, you can use the lower level parser and compiler. Some usage examples are below:

#### Java

```java
// Java
Path path = Paths.get("../testdata/good/minimal.feature");
GherkinParser parser = GherkinParser.builder().build();
Stream<Envelope> pickles = parser.parse(envelope).filter(envelope -> envelope.getPickle().isPresent());
```

#### C#

```csharp
// C#
var parser = new Parser();
var gherkinDocument = parser.Parse(@"Drive:\PathToGherkinDocument\document.feature");
```

#### Ruby

```ruby
# Ruby
require 'gherkin/parser'
require 'gherkin/pickles/compiler'

Expand All @@ -88,22 +91,28 @@ id_generator = Cucumber::Messages::IdGenerator::UUID.new
pickles = Gherkin::Pickles::Compiler.new(id_generator).compile(gherkin_document, source)
```

```javascript
// JavaScript
var Gherkin = require('@cucumber/gherkin')
var Messages = require('@cucumber/messages')

var uuidFn = Messages.IdGenerator.uuid()
var builder = new Gherkin.AstBuilder(uuidFn)
var matcher = new Gherkin.GherkinClassicTokenMatcher() // or Gherkin.GherkinInMarkdownTokenMatcher()
#### JavaScript

var parser = new Gherkin.Parser(builder, matcher)
var gherkinDocument = parser.parse('Feature: ...')
var pickles = Gherkin.compile(gherkinDocument, 'uri_of_the_feature.feature', uuidFn)
```javascript
var Gherkin = require("@cucumber/gherkin");
var Messages = require("@cucumber/messages");

var uuidFn = Messages.IdGenerator.uuid();
var builder = new Gherkin.AstBuilder(uuidFn);
var matcher = new Gherkin.GherkinClassicTokenMatcher(); // or Gherkin.GherkinInMarkdownTokenMatcher()

var parser = new Gherkin.Parser(builder, matcher);
var gherkinDocument = parser.parse("Feature: ...");
var pickles = Gherkin.compile(
gherkinDocument,
"uri_of_the_feature.feature",
uuidFn
);
```

#### Go

```go
// Go
// Download the package via: `go get github.com/cucumber/gherkin/go/v27`
// && go get "github.com/cucumber/messages/go/v22"
import (
Expand All @@ -121,8 +130,9 @@ func main() {
}
```

#### Python

```python
# Python
from gherkin.parser import Parser
from gherkin.pickles.compiler import Compiler

Expand All @@ -132,8 +142,9 @@ gherkin_document["uri"] = "uri_of_the_feature.feature"
pickles = Compiler().compile(gherkin_document)
```

#### Objective-C

```Objective-C
// Objective-C
#import "GHParser+Extensions.h"

GHParser * parser = [[GHParser alloc] init];
Expand All @@ -145,8 +156,9 @@ if([content stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewline
GHGherkinDocument * result = [parser parseContent:content];
```

#### Perl

```perl
# Perl
use Gherkin::Parser;
use Gherkin::Pickles::Compiler;

Expand All @@ -155,8 +167,9 @@ my $gherkin_document = $parser->parse("Feature: ...");
my $pickles = Gherkin::Pickles::Compiler->compile($gherkin_document);
```

#### PHP

```php
# PHP
use Cucumber\Gherkin\GherkinParser;

$path = '/path/to/my.feature';
Expand All @@ -168,22 +181,26 @@ $pickles = $parser->parseString(uri: $path, data: file_get_contents($path));
### CLI

The Gherkin CLI `gherkin` reads Gherkin source files (`.feature` files) and outputs
[ASTs](#ast) and [Pickles](#pickles).
[ASTs](#abstract-syntax-tree-ast) and [Pickles](#pickles).

The `gherkin` program takes any number of files as arguments and prints the results
to `STDOUT` as [Newline Delimited JSON](http://ndjson.org/).
to `STDOUT` as [Newline Delimited JSON](https://jsonlines.org).

Each line is a JSON document that conforms to the [Cucumber Event Protocol](../messages).
Each line is a JSON document that conforms to the [Cucumber Event Protocol](https://github.com/cucumber/messages).

To try it out, just install Gherkin for your favourite language, and run it over the
files in this repository:

gherkin testdata/**/*.feature
```console
gherkin testdata/**/*.feature
```

Ndjson is easy to read for programs, but hard for people. To pretty print each JSON
document you can pipe it to the [jq](https://stedolan.github.io/jq/) program:

gherkin testdata/**/*.feature | jq
```console
gherkin testdata/**/*.feature | jq
```

## Table cell escaping

Expand All @@ -195,9 +212,11 @@ finally, if you need a `\`, you can escape that with `\\`.

The following diagram outlines the architecture:

╔════════════╗ β”Œβ”€β”€β”€β”€β”€β”€β”€β” ╔══════╗ β”Œβ”€β”€β”€β”€β”€β”€β” ╔═══╗
β•‘Feature file║──>β”‚Scanner│──>β•‘Tokens║──>β”‚Parser│──>β•‘ASTβ•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β• β””β”€β”€β”€β”€β”€β”€β”€β”˜ β•šβ•β•β•β•β•β•β• β””β”€β”€β”€β”€β”€β”€β”˜ β•šβ•β•β•β•
```mermaid
graph LR
A[Feature file] -->|Scanner| B[Tokens]
B -->|Parser| D[AST]
```

The _scanner_ reads a gherkin doc (typically read from a `.feature` file) and creates
a _token_ for each line. The tokens are passed to the _parser_, which outputs an _AST_
Expand All @@ -213,17 +232,12 @@ parser generator as part of the build process.
Berp takes a grammar file (`gherkin.berp`) and a template file (`gherkin-X.razor`) as input
and outputs a parser in language _X_:

╔════════════╗ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” ╔═══════════════╗
β•‘gherkin.berp║──>β”‚berp.exeβ”‚<──║gherkin-X.razorβ•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β• β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
β”‚
V
╔════════╗
β•‘Parser.xβ•‘
β•šβ•β•β•β•β•β•β•β•β•

Also see the [wiki](https://github.com/cucumber/gherkin/wiki) for some early
design docs (which might be a little outdated, but mostly OK).
```mermaid
graph TD
A[gherkin.berp] --> B[berp.exe]
C[gherkin-X.razor] --> B
B --> D[Parser.x]
```

### Abstract Syntax Tree (AST)

Expand Down Expand Up @@ -326,9 +340,10 @@ into a simpler form called _Pickles_.

The compiler compiles the AST produced by the parser into pickles:

╔═══╗ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β” ╔═══════╗
β•‘AST║──>β”‚Compiler│──>β•‘Picklesβ•‘
β•šβ•β•β•β• β””β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β•šβ•β•β•β•β•β•β•β•
```mermaid
graph LR
A[AST] -->|Compiler| B[Pickles]
```

The rationale is to decouple Gherkin from Cucumber so that Cucumber is open to
support alternative formats to Gherkin (for example Markdown).
Expand Down Expand Up @@ -373,7 +388,9 @@ Feature:

Using the [CLI](#cli) we can compile this into several pickle objects:

gherkin testdata/good/readme_example.feature --no-source --no-ast | jq
```console
gherkin testdata/good/readme_example.feature --no-source --no-ast | jq
```

Output:

Expand Down