resources/gherkin.berp

[
	Tokens -> #Empty,#Comment,#TagLine,#FeatureLine,#RuleLine,#BackgroundLine,#ScenarioLine,#ExamplesLine,#StepLine,#DocStringSeparator,#TableRow,#Language
	IgnoredTokens -> #Comment,#Empty
	ClassName -> Parser
	Namespace -> Gherkin
]

GherkinDocument! := Feature?
Feature! := FeatureHeader Background? ScenarioDefinition* Rule*
FeatureHeader! := #Language? Tags? #FeatureLine DescriptionHelper

Rule! := RuleHeader Background? ScenarioDefinition*
RuleHeader! := #RuleLine DescriptionHelper

Background! := #BackgroundLine DescriptionHelper Step*

// we could avoid defining ScenarioDefinition, but that would require regular look-aheads, so worse performance
ScenarioDefinition! := Tags? Scenario

Scenario! := #ScenarioLine DescriptionHelper Step* ExamplesDefinition*
// after the first "Data" block, interpreting a tag line is ambiguous (tagline of next examples or of next scenario)
// because of this, we need a lookahead hint, that connects the tag line to the next examples, if there is an examples block ahead
ExamplesDefinition! [#Empty|#Comment|#TagLine->#ExamplesLine]:= Tags? Examples
Examples! := #ExamplesLine DescriptionHelper ExamplesTable?
ExamplesTable! := #TableRow #TableRow*

Step! := #StepLine StepArg?
StepArg := (DataTable | DocString)

DataTable! := #TableRow+
DocString! := #DocStringSeparator #Other* #DocStringSeparator

Tags! := #TagLine+

// we need to explicitly mention comment, to avoid merging it into the description line's #Other token
// we also eat the leading empty lines, the tailing lines are not removed by the parser to avoid lookahead, this has to be done by the AST builder
DescriptionHelper := #Empty* Description? #Comment*
Description! := #Other+