[ 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+