diff --git a/.travis.yml b/.travis.yml index 6816451..52a3a96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,9 @@ go: - 1.6 - tip -script: - # pull all external dependencies - - go get gopkg.in/cucumber/gherkin-go.v3 - - go get github.com/shiena/ansicolor +install: go install github.com/DATA-DOG/godog/cmd/godog +script: # run standard go tests - go vet ./... - go fmt ./... @@ -17,4 +15,4 @@ script: - go test -race # run features - - go run cmd/godog/main.go --format=progress --concurrency=4 + - godog --format=progress --concurrency=4 diff --git a/Makefile b/Makefile index b833909..6fa7bd0 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,18 @@ -.PHONY: test deps +.PHONY: test gherkin test: @echo "running all tests" + @go install ./... @go fmt ./... - @golint ./... + @golint github.com/DATA-DOG/godog + @golint github.com/DATA-DOG/godog/cmd/godog go vet ./... go test - go run cmd/godog/main.go -f progress -c 4 - -deps: - @echo "updating all dependencies" - go get -u gopkg.in/cucumber/gherkin-go.v3 - go get -u github.com/shiena/ansicolor + godog -f progress -c 4 +gherkin: + @if [ -z "$(VERS)" ]; then echo "Provide gherkin version like: 'VERS=commit-hash'"; exit 1; fi + @rm -rf gherkin + @mkdir gherkin + @curl -s -L https://github.com/cucumber/gherkin-go/tarball/$(VERS) | tar -C gherkin -zx --strip-components 1 + @rm -rf gherkin/{.travis.yml,.gitignore,*_test.go,gherkin-generate*,*.razor,*.jq,Makefile,CONTRIBUTING.md} diff --git a/README.md b/README.md index 7a45b79..8fc0fb0 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,10 @@ used in tests. **Godog** uses standard **go** ast and build utils to generate test suite package and even builds it with **go test -c** command. It even passes all your environment exported vars. +**Godog** ships gherkin parser dependency as a subpackage. This will +ensure that it is always compatible with the installed version of godog. +So in general there are no vendor dependencies needed for installation. + ### Install go get github.com/DATA-DOG/godog/cmd/godog @@ -153,6 +157,10 @@ See implementation examples: ### Changes +**2016-05-26** +- pack gherkin dependency in a subpackage to prevent compatibility + conflicts. + **2016-05-25** - refactored test suite build tooling in order to use standard **go test** tool. Which allows to compile package with godog runner script in **go** diff --git a/cmd/godog/ansicolor.go b/cmd/godog/ansicolor.go new file mode 100644 index 0000000..af34f4c --- /dev/null +++ b/cmd/godog/ansicolor.go @@ -0,0 +1,41 @@ +// Copyright 2014 shiena Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package main + +import "io" + +type outputMode int + +// DiscardNonColorEscSeq supports the divided color escape sequence. +// But non-color escape sequence is not output. +// Please use the OutputNonColorEscSeq If you want to output a non-color +// escape sequences such as ncurses. However, it does not support the divided +// color escape sequence. +const ( + _ outputMode = iota + discardNonColorEscSeq + outputNonColorEscSeq +) + +// NewAnsiColorWriter creates and initializes a new ansiColorWriter +// using io.Writer w as its initial contents. +// In the console of Windows, which change the foreground and background +// colors of the text by the escape sequence. +// In the console of other systems, which writes to w all text. +func createAnsiColorWriter(w io.Writer) io.Writer { + return createModeAnsiColorWriter(w, discardNonColorEscSeq) +} + +// NewModeAnsiColorWriter create and initializes a new ansiColorWriter +// by specifying the outputMode. +func createModeAnsiColorWriter(w io.Writer, mode outputMode) io.Writer { + if _, ok := w.(*ansiColorWriter); !ok { + return &ansiColorWriter{ + w: w, + mode: mode, + } + } + return w +} diff --git a/cmd/godog/ansicolor_ansi.go b/cmd/godog/ansicolor_ansi.go new file mode 100644 index 0000000..b6858b6 --- /dev/null +++ b/cmd/godog/ansicolor_ansi.go @@ -0,0 +1,18 @@ +// Copyright 2014 shiena Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +// +build !windows + +package main + +import "io" + +type ansiColorWriter struct { + w io.Writer + mode outputMode +} + +func (cw *ansiColorWriter) Write(p []byte) (int, error) { + return cw.w.Write(p) +} diff --git a/cmd/godog/ansicolor_windows.go b/cmd/godog/ansicolor_windows.go new file mode 100644 index 0000000..1772929 --- /dev/null +++ b/cmd/godog/ansicolor_windows.go @@ -0,0 +1,417 @@ +// Copyright 2014 shiena Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +// +build windows + +package main + +import ( + "bytes" + "io" + "strings" + "syscall" + "unsafe" +) + +type csiState int + +const ( + outsideCsiCode csiState = iota + firstCsiCode + secondCsiCode +) + +type parseResult int + +const ( + noConsole parseResult = iota + changedColor + unknown +) + +type ansiColorWriter struct { + w io.Writer + mode outputMode + state csiState + paramStartBuf bytes.Buffer + paramBuf bytes.Buffer +} + +const ( + firstCsiChar byte = '\x1b' + secondeCsiChar byte = '[' + separatorChar byte = ';' + sgrCode byte = 'm' +) + +const ( + foregroundBlue = uint16(0x0001) + foregroundGreen = uint16(0x0002) + foregroundRed = uint16(0x0004) + foregroundIntensity = uint16(0x0008) + backgroundBlue = uint16(0x0010) + backgroundGreen = uint16(0x0020) + backgroundRed = uint16(0x0040) + backgroundIntensity = uint16(0x0080) + underscore = uint16(0x8000) + + foregroundMask = foregroundBlue | foregroundGreen | foregroundRed | foregroundIntensity + backgroundMask = backgroundBlue | backgroundGreen | backgroundRed | backgroundIntensity +) + +const ( + ansiReset = "0" + ansiIntensityOn = "1" + ansiIntensityOff = "21" + ansiUnderlineOn = "4" + ansiUnderlineOff = "24" + ansiBlinkOn = "5" + ansiBlinkOff = "25" + + ansiForegroundBlack = "30" + ansiForegroundRed = "31" + ansiForegroundGreen = "32" + ansiForegroundYellow = "33" + ansiForegroundBlue = "34" + ansiForegroundMagenta = "35" + ansiForegroundCyan = "36" + ansiForegroundWhite = "37" + ansiForegroundDefault = "39" + + ansiBackgroundBlack = "40" + ansiBackgroundRed = "41" + ansiBackgroundGreen = "42" + ansiBackgroundYellow = "43" + ansiBackgroundBlue = "44" + ansiBackgroundMagenta = "45" + ansiBackgroundCyan = "46" + ansiBackgroundWhite = "47" + ansiBackgroundDefault = "49" + + ansiLightForegroundGray = "90" + ansiLightForegroundRed = "91" + ansiLightForegroundGreen = "92" + ansiLightForegroundYellow = "93" + ansiLightForegroundBlue = "94" + ansiLightForegroundMagenta = "95" + ansiLightForegroundCyan = "96" + ansiLightForegroundWhite = "97" + + ansiLightBackgroundGray = "100" + ansiLightBackgroundRed = "101" + ansiLightBackgroundGreen = "102" + ansiLightBackgroundYellow = "103" + ansiLightBackgroundBlue = "104" + ansiLightBackgroundMagenta = "105" + ansiLightBackgroundCyan = "106" + ansiLightBackgroundWhite = "107" +) + +type drawType int + +const ( + foreground drawType = iota + background +) + +type winColor struct { + code uint16 + drawType drawType +} + +var colorMap = map[string]winColor{ + ansiForegroundBlack: {0, foreground}, + ansiForegroundRed: {foregroundRed, foreground}, + ansiForegroundGreen: {foregroundGreen, foreground}, + ansiForegroundYellow: {foregroundRed | foregroundGreen, foreground}, + ansiForegroundBlue: {foregroundBlue, foreground}, + ansiForegroundMagenta: {foregroundRed | foregroundBlue, foreground}, + ansiForegroundCyan: {foregroundGreen | foregroundBlue, foreground}, + ansiForegroundWhite: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, + ansiForegroundDefault: {foregroundRed | foregroundGreen | foregroundBlue, foreground}, + + ansiBackgroundBlack: {0, background}, + ansiBackgroundRed: {backgroundRed, background}, + ansiBackgroundGreen: {backgroundGreen, background}, + ansiBackgroundYellow: {backgroundRed | backgroundGreen, background}, + ansiBackgroundBlue: {backgroundBlue, background}, + ansiBackgroundMagenta: {backgroundRed | backgroundBlue, background}, + ansiBackgroundCyan: {backgroundGreen | backgroundBlue, background}, + ansiBackgroundWhite: {backgroundRed | backgroundGreen | backgroundBlue, background}, + ansiBackgroundDefault: {0, background}, + + ansiLightForegroundGray: {foregroundIntensity, foreground}, + ansiLightForegroundRed: {foregroundIntensity | foregroundRed, foreground}, + ansiLightForegroundGreen: {foregroundIntensity | foregroundGreen, foreground}, + ansiLightForegroundYellow: {foregroundIntensity | foregroundRed | foregroundGreen, foreground}, + ansiLightForegroundBlue: {foregroundIntensity | foregroundBlue, foreground}, + ansiLightForegroundMagenta: {foregroundIntensity | foregroundRed | foregroundBlue, foreground}, + ansiLightForegroundCyan: {foregroundIntensity | foregroundGreen | foregroundBlue, foreground}, + ansiLightForegroundWhite: {foregroundIntensity | foregroundRed | foregroundGreen | foregroundBlue, foreground}, + + ansiLightBackgroundGray: {backgroundIntensity, background}, + ansiLightBackgroundRed: {backgroundIntensity | backgroundRed, background}, + ansiLightBackgroundGreen: {backgroundIntensity | backgroundGreen, background}, + ansiLightBackgroundYellow: {backgroundIntensity | backgroundRed | backgroundGreen, background}, + ansiLightBackgroundBlue: {backgroundIntensity | backgroundBlue, background}, + ansiLightBackgroundMagenta: {backgroundIntensity | backgroundRed | backgroundBlue, background}, + ansiLightBackgroundCyan: {backgroundIntensity | backgroundGreen | backgroundBlue, background}, + ansiLightBackgroundWhite: {backgroundIntensity | backgroundRed | backgroundGreen | backgroundBlue, background}, +} + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + procSetConsoleTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") + procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") + defaultAttr *textAttributes +) + +func init() { + screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) + if screenInfo != nil { + colorMap[ansiForegroundDefault] = winColor{ + screenInfo.WAttributes & (foregroundRed | foregroundGreen | foregroundBlue), + foreground, + } + colorMap[ansiBackgroundDefault] = winColor{ + screenInfo.WAttributes & (backgroundRed | backgroundGreen | backgroundBlue), + background, + } + defaultAttr = convertTextAttr(screenInfo.WAttributes) + } +} + +type coord struct { + X, Y int16 +} + +type smallRect struct { + Left, Top, Right, Bottom int16 +} + +type consoleScreenBufferInfo struct { + DwSize coord + DwCursorPosition coord + WAttributes uint16 + SrWindow smallRect + DwMaximumWindowSize coord +} + +func getConsoleScreenBufferInfo(hConsoleOutput uintptr) *consoleScreenBufferInfo { + var csbi consoleScreenBufferInfo + ret, _, _ := procGetConsoleScreenBufferInfo.Call( + hConsoleOutput, + uintptr(unsafe.Pointer(&csbi))) + if ret == 0 { + return nil + } + return &csbi +} + +func setConsoleTextAttribute(hConsoleOutput uintptr, wAttributes uint16) bool { + ret, _, _ := procSetConsoleTextAttribute.Call( + hConsoleOutput, + uintptr(wAttributes)) + return ret != 0 +} + +type textAttributes struct { + foregroundColor uint16 + backgroundColor uint16 + foregroundIntensity uint16 + backgroundIntensity uint16 + underscore uint16 + otherAttributes uint16 +} + +func convertTextAttr(winAttr uint16) *textAttributes { + fgColor := winAttr & (foregroundRed | foregroundGreen | foregroundBlue) + bgColor := winAttr & (backgroundRed | backgroundGreen | backgroundBlue) + fgIntensity := winAttr & foregroundIntensity + bgIntensity := winAttr & backgroundIntensity + underline := winAttr & underscore + otherAttributes := winAttr &^ (foregroundMask | backgroundMask | underscore) + return &textAttributes{fgColor, bgColor, fgIntensity, bgIntensity, underline, otherAttributes} +} + +func convertWinAttr(textAttr *textAttributes) uint16 { + var winAttr uint16 + winAttr |= textAttr.foregroundColor + winAttr |= textAttr.backgroundColor + winAttr |= textAttr.foregroundIntensity + winAttr |= textAttr.backgroundIntensity + winAttr |= textAttr.underscore + winAttr |= textAttr.otherAttributes + return winAttr +} + +func changeColor(param []byte) parseResult { + screenInfo := getConsoleScreenBufferInfo(uintptr(syscall.Stdout)) + if screenInfo == nil { + return noConsole + } + + winAttr := convertTextAttr(screenInfo.WAttributes) + strParam := string(param) + if len(strParam) <= 0 { + strParam = "0" + } + csiParam := strings.Split(strParam, string(separatorChar)) + for _, p := range csiParam { + c, ok := colorMap[p] + switch { + case !ok: + switch p { + case ansiReset: + winAttr.foregroundColor = defaultAttr.foregroundColor + winAttr.backgroundColor = defaultAttr.backgroundColor + winAttr.foregroundIntensity = defaultAttr.foregroundIntensity + winAttr.backgroundIntensity = defaultAttr.backgroundIntensity + winAttr.underscore = 0 + winAttr.otherAttributes = 0 + case ansiIntensityOn: + winAttr.foregroundIntensity = foregroundIntensity + case ansiIntensityOff: + winAttr.foregroundIntensity = 0 + case ansiUnderlineOn: + winAttr.underscore = underscore + case ansiUnderlineOff: + winAttr.underscore = 0 + case ansiBlinkOn: + winAttr.backgroundIntensity = backgroundIntensity + case ansiBlinkOff: + winAttr.backgroundIntensity = 0 + default: + // unknown code + } + case c.drawType == foreground: + winAttr.foregroundColor = c.code + case c.drawType == background: + winAttr.backgroundColor = c.code + } + } + winTextAttribute := convertWinAttr(winAttr) + setConsoleTextAttribute(uintptr(syscall.Stdout), winTextAttribute) + + return changedColor +} + +func parseEscapeSequence(command byte, param []byte) parseResult { + if defaultAttr == nil { + return noConsole + } + + switch command { + case sgrCode: + return changeColor(param) + default: + return unknown + } +} + +func (cw *ansiColorWriter) flushBuffer() (int, error) { + return cw.flushTo(cw.w) +} + +func (cw *ansiColorWriter) resetBuffer() (int, error) { + return cw.flushTo(nil) +} + +func (cw *ansiColorWriter) flushTo(w io.Writer) (int, error) { + var n1, n2 int + var err error + + startBytes := cw.paramStartBuf.Bytes() + cw.paramStartBuf.Reset() + if w != nil { + n1, err = cw.w.Write(startBytes) + if err != nil { + return n1, err + } + } else { + n1 = len(startBytes) + } + paramBytes := cw.paramBuf.Bytes() + cw.paramBuf.Reset() + if w != nil { + n2, err = cw.w.Write(paramBytes) + if err != nil { + return n1 + n2, err + } + } else { + n2 = len(paramBytes) + } + return n1 + n2, nil +} + +func isParameterChar(b byte) bool { + return ('0' <= b && b <= '9') || b == separatorChar +} + +func (cw *ansiColorWriter) Write(p []byte) (int, error) { + r, nw, first, last := 0, 0, 0, 0 + if cw.mode != DiscardNonColorEscSeq { + cw.state = outsideCsiCode + cw.resetBuffer() + } + + var err error + for i, ch := range p { + switch cw.state { + case outsideCsiCode: + if ch == firstCsiChar { + cw.paramStartBuf.WriteByte(ch) + cw.state = firstCsiCode + } + case firstCsiCode: + switch ch { + case firstCsiChar: + cw.paramStartBuf.WriteByte(ch) + break + case secondeCsiChar: + cw.paramStartBuf.WriteByte(ch) + cw.state = secondCsiCode + last = i - 1 + default: + cw.resetBuffer() + cw.state = outsideCsiCode + } + case secondCsiCode: + if isParameterChar(ch) { + cw.paramBuf.WriteByte(ch) + } else { + nw, err = cw.w.Write(p[first:last]) + r += nw + if err != nil { + return r, err + } + first = i + 1 + result := parseEscapeSequence(ch, cw.paramBuf.Bytes()) + if result == noConsole || (cw.mode == OutputNonColorEscSeq && result == unknown) { + cw.paramBuf.WriteByte(ch) + nw, err := cw.flushBuffer() + if err != nil { + return r, err + } + r += nw + } else { + n, _ := cw.resetBuffer() + // Add one more to the size of the buffer for the last ch + r += n + 1 + } + + cw.state = outsideCsiCode + } + default: + cw.state = outsideCsiCode + } + } + + if cw.mode != DiscardNonColorEscSeq || cw.state == outsideCsiCode { + nw, err = cw.w.Write(p[first:len(p)]) + r += nw + } + + return r, err +} diff --git a/cmd/godog/main.go b/cmd/godog/main.go index d1ddc7f..3f37489 100644 --- a/cmd/godog/main.go +++ b/cmd/godog/main.go @@ -12,7 +12,6 @@ import ( "time" "github.com/DATA-DOG/godog" - "github.com/shiena/ansicolor" ) var statusMatch = regexp.MustCompile("^exit status (\\d+)") @@ -21,8 +20,8 @@ var parsedStatus int func buildAndRun() (int, error) { var status int // will support Ansi colors for windows - stdout := ansicolor.NewAnsiColorWriter(os.Stdout) - stderr := ansicolor.NewAnsiColorWriter(statusOutputFilter(os.Stderr)) + stdout := createAnsiColorWriter(os.Stdout) + stderr := createAnsiColorWriter(statusOutputFilter(os.Stderr)) dir := fmt.Sprintf(filepath.Join("%s", "godog-%d"), os.TempDir(), time.Now().UnixNano()) err := godog.Build(dir) diff --git a/fmt.go b/fmt.go index 3fba9cf..66aa3bc 100644 --- a/fmt.go +++ b/fmt.go @@ -10,7 +10,7 @@ import ( "time" "unicode" - "gopkg.in/cucumber/gherkin-go.v3" + "github.com/DATA-DOG/godog/gherkin" ) // some snippet formatting regexps diff --git a/fmt_junit.go b/fmt_junit.go index 464b30d..d0130dd 100644 --- a/fmt_junit.go +++ b/fmt_junit.go @@ -7,7 +7,7 @@ import ( "os" "time" - "gopkg.in/cucumber/gherkin-go.v3" + "github.com/DATA-DOG/godog/gherkin" ) func init() { diff --git a/fmt_pretty.go b/fmt_pretty.go index 0fc83e6..1357b06 100644 --- a/fmt_pretty.go +++ b/fmt_pretty.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "gopkg.in/cucumber/gherkin-go.v3" + "github.com/DATA-DOG/godog/gherkin" ) func init() { diff --git a/fmt_progress.go b/fmt_progress.go index 45ab28b..36c8b12 100644 --- a/fmt_progress.go +++ b/fmt_progress.go @@ -6,7 +6,7 @@ import ( "sync" "time" - "gopkg.in/cucumber/gherkin-go.v3" + "github.com/DATA-DOG/godog/gherkin" ) func init() { diff --git a/fmt_test.go b/fmt_test.go index ac40f8e..c8dc921 100644 --- a/fmt_test.go +++ b/fmt_test.go @@ -1,6 +1,6 @@ package godog -import "gopkg.in/cucumber/gherkin-go.v3" +import "github.com/DATA-DOG/godog/gherkin" type testFormatter struct { basefmt diff --git a/gherkin.go b/gherkin.go index ec45f1b..4280eae 100644 --- a/gherkin.go +++ b/gherkin.go @@ -1,6 +1,6 @@ package godog -import "gopkg.in/cucumber/gherkin-go.v3" +import "github.com/DATA-DOG/godog/gherkin" // examples is a helper func to cast gherkin.Examples // or gherkin.BaseExamples if its empty diff --git a/gherkin/LICENSE b/gherkin/LICENSE new file mode 100644 index 0000000..ea68549 --- /dev/null +++ b/gherkin/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016 Cucumber Ltd, Gaspar Nagy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/gherkin/README.md b/gherkin/README.md new file mode 100644 index 0000000..6b90df0 --- /dev/null +++ b/gherkin/README.md @@ -0,0 +1,3 @@ +[![Build Status](https://secure.travis-ci.org/cucumber/gherkin-go.svg)](http://travis-ci.org/cucumber/gherkin-go) + +Gherkin parser/compiler for Go. Please see [Gherkin](https://github.com/cucumber/gherkin) for details. diff --git a/gherkin/ast.go b/gherkin/ast.go new file mode 100644 index 0000000..d0909e6 --- /dev/null +++ b/gherkin/ast.go @@ -0,0 +1,97 @@ +package gherkin + +type Location struct { + Line int `json:"line"` + Column int `json:"column"` +} + +type Node struct { + Location *Location `json:"location,omitempty"` + Type string `json:"type"` +} + +type Feature struct { + Node + Tags []*Tag `json:"tags"` + Language string `json:"language,omitempty"` + Keyword string `json:"keyword"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Background *Background `json:"background,omitempty"` + ScenarioDefinitions []interface{} `json:"scenarioDefinitions"` + Comments []*Comment `json:"comments"` +} + +type Comment struct { + Node + Location *Location `json:"location,omitempty"` + Text string `json:"text"` +} + +type Tag struct { + Node + Location *Location `json:"location,omitempty"` + Name string `json:"name"` +} + +type Background struct { + ScenarioDefinition +} + +type Scenario struct { + ScenarioDefinition + Tags []*Tag `json:"tags"` +} + +type ScenarioOutline struct { + ScenarioDefinition + Tags []*Tag `json:"tags"` + Examples []*Examples `json:"examples,omitempty"` +} + +type Examples struct { + Node + Tags []*Tag `json:"tags"` + Keyword string `json:"keyword"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + TableHeader *TableRow `json:"tableHeader"` + TableBody []*TableRow `json:"tableBody"` +} + +type TableRow struct { + Node + Cells []*TableCell `json:"cells"` +} + +type TableCell struct { + Node + Value string `json:"value"` +} + +type ScenarioDefinition struct { + Node + Keyword string `json:"keyword"` + Name string `json:"name"` + Description string `json:"description,omitempty"` + Steps []*Step `json:"steps"` +} + +type Step struct { + Node + Keyword string `json:"keyword"` + Text string `json:"text"` + Argument interface{} `json:"argument,omitempty"` +} + +type DocString struct { + Node + ContentType string `json:"contentType,omitempty"` + Content string `json:"content"` + Delimitter string `json:"-"` +} + +type DataTable struct { + Node + Rows []*TableRow `json:"rows"` +} diff --git a/gherkin/astbuilder.go b/gherkin/astbuilder.go new file mode 100644 index 0000000..e92ea36 --- /dev/null +++ b/gherkin/astbuilder.go @@ -0,0 +1,378 @@ +package gherkin + +import ( + "strings" +) + +type AstBuilder interface { + Builder + GetFeature() *Feature +} + +type astBuilder struct { + stack []*astNode + comments []*Comment +} + +func (t *astBuilder) Reset() { + t.comments = []*Comment{} + t.stack = []*astNode{} + t.push(newAstNode(RuleType_None)) +} + +func (t *astBuilder) GetFeature() *Feature { + res := t.currentNode().getSingle(RuleType_Feature) + if val, ok := res.(*Feature); ok { + return val + } + return nil +} + +type astNode struct { + ruleType RuleType + subNodes map[RuleType][]interface{} +} + +func (a *astNode) add(rt RuleType, obj interface{}) { + a.subNodes[rt] = append(a.subNodes[rt], obj) +} + +func (a *astNode) getSingle(rt RuleType) interface{} { + if val, ok := a.subNodes[rt]; ok { + for i := range val { + return val[i] + } + } + return nil +} + +func (a *astNode) getItems(rt RuleType) []interface{} { + var res []interface{} + if val, ok := a.subNodes[rt]; ok { + for i := range val { + res = append(res, val[i]) + } + } + return res +} + +func (a *astNode) getToken(tt TokenType) *Token { + if val, ok := a.getSingle(tt.RuleType()).(*Token); ok { + return val + } + return nil +} + +func (a *astNode) getTokens(tt TokenType) []*Token { + var items = a.getItems(tt.RuleType()) + var tokens []*Token + for i := range items { + if val, ok := items[i].(*Token); ok { + tokens = append(tokens, val) + } + } + return tokens +} + +func (t *astBuilder) currentNode() *astNode { + if len(t.stack) > 0 { + return t.stack[len(t.stack)-1] + } + return nil +} + +func newAstNode(rt RuleType) *astNode { + return &astNode{ + ruleType: rt, + subNodes: make(map[RuleType][]interface{}), + } +} + +func NewAstBuilder() AstBuilder { + builder := new(astBuilder) + builder.comments = []*Comment{} + builder.push(newAstNode(RuleType_None)) + return builder +} + +func (t *astBuilder) push(n *astNode) { + t.stack = append(t.stack, n) +} + +func (t *astBuilder) pop() *astNode { + x := t.stack[len(t.stack)-1] + t.stack = t.stack[:len(t.stack)-1] + return x +} + +func (t *astBuilder) Build(tok *Token) (bool, error) { + if tok.Type == TokenType_Comment { + comment := new(Comment) + comment.Type = "Comment" + comment.Location = astLocation(tok) + comment.Text = tok.Text + t.comments = append(t.comments, comment) + } else { + t.currentNode().add(tok.Type.RuleType(), tok) + } + return true, nil +} +func (t *astBuilder) StartRule(r RuleType) (bool, error) { + t.push(newAstNode(r)) + return true, nil +} +func (t *astBuilder) EndRule(r RuleType) (bool, error) { + node := t.pop() + transformedNode, err := t.transformNode(node) + t.currentNode().add(node.ruleType, transformedNode) + return true, err +} + +func (t *astBuilder) transformNode(node *astNode) (interface{}, error) { + switch node.ruleType { + + case RuleType_Step: + stepLine := node.getToken(TokenType_StepLine) + step := new(Step) + step.Type = "Step" + step.Location = astLocation(stepLine) + step.Keyword = stepLine.Keyword + step.Text = stepLine.Text + step.Argument = node.getSingle(RuleType_DataTable) + if step.Argument == nil { + step.Argument = node.getSingle(RuleType_DocString) + } + return step, nil + + case RuleType_DocString: + separatorToken := node.getToken(TokenType_DocStringSeparator) + contentType := separatorToken.Text + lineTokens := node.getTokens(TokenType_Other) + var text string + for i := range lineTokens { + if i > 0 { + text += "\n" + } + text += lineTokens[i].Text + } + ds := new(DocString) + ds.Type = "DocString" + ds.Location = astLocation(separatorToken) + ds.ContentType = contentType + ds.Content = text + ds.Delimitter = DOCSTRING_SEPARATOR // TODO: remember separator + return ds, nil + + case RuleType_DataTable: + rows, err := astTableRows(node) + dt := new(DataTable) + dt.Type = "DataTable" + dt.Location = rows[0].Location + dt.Rows = rows + return dt, err + + case RuleType_Background: + backgroundLine := node.getToken(TokenType_BackgroundLine) + description, _ := node.getSingle(RuleType_Description).(string) + bg := new(Background) + bg.Type = "Background" + bg.Location = astLocation(backgroundLine) + bg.Keyword = backgroundLine.Keyword + bg.Name = backgroundLine.Text + bg.Description = description + bg.Steps = astSteps(node) + return bg, nil + + case RuleType_Scenario_Definition: + tags := astTags(node) + scenarioNode, _ := node.getSingle(RuleType_Scenario).(*astNode) + if scenarioNode != nil { + scenarioLine := scenarioNode.getToken(TokenType_ScenarioLine) + description, _ := scenarioNode.getSingle(RuleType_Description).(string) + sc := new(Scenario) + sc.Type = "Scenario" + sc.Tags = tags + sc.Location = astLocation(scenarioLine) + sc.Keyword = scenarioLine.Keyword + sc.Name = scenarioLine.Text + sc.Description = description + sc.Steps = astSteps(scenarioNode) + return sc, nil + } else { + scenarioOutlineNode, ok := node.getSingle(RuleType_ScenarioOutline).(*astNode) + if !ok { + panic("Internal grammar error") + } + scenarioOutlineLine := scenarioOutlineNode.getToken(TokenType_ScenarioOutlineLine) + description, _ := scenarioOutlineNode.getSingle(RuleType_Description).(string) + sc := new(ScenarioOutline) + sc.Type = "ScenarioOutline" + sc.Tags = tags + sc.Location = astLocation(scenarioOutlineLine) + sc.Keyword = scenarioOutlineLine.Keyword + sc.Name = scenarioOutlineLine.Text + sc.Description = description + sc.Steps = astSteps(scenarioOutlineNode) + sc.Examples = astExamples(scenarioOutlineNode) + return sc, nil + } + + case RuleType_Examples_Definition: + tags := astTags(node) + examplesNode, _ := node.getSingle(RuleType_Examples).(*astNode) + examplesLine := examplesNode.getToken(TokenType_ExamplesLine) + description, _ := examplesNode.getSingle(RuleType_Description).(string) + allRows, err := astTableRows(examplesNode) + ex := new(Examples) + ex.Type = "Examples" + ex.Tags = tags + ex.Location = astLocation(examplesLine) + ex.Keyword = examplesLine.Keyword + ex.Name = examplesLine.Text + ex.Description = description + ex.TableHeader = allRows[0] + ex.TableBody = allRows[1:] + return ex, err + + case RuleType_Description: + lineTokens := node.getTokens(TokenType_Other) + // Trim trailing empty lines + end := len(lineTokens) + for end > 0 && strings.TrimSpace(lineTokens[end-1].Text) == "" { + end-- + } + var desc []string + for i := range lineTokens[0:end] { + desc = append(desc, lineTokens[i].Text) + } + return strings.Join(desc, "\n"), nil + + case RuleType_Feature: + header, ok := node.getSingle(RuleType_Feature_Header).(*astNode) + if !ok { + return nil, nil + } + tags := astTags(header) + featureLine := header.getToken(TokenType_FeatureLine) + if featureLine == nil { + return nil, nil + } + background, _ := node.getSingle(RuleType_Background).(*Background) + scenarioDefinitions := node.getItems(RuleType_Scenario_Definition) + if scenarioDefinitions == nil { + scenarioDefinitions = []interface{}{} + } + description, _ := header.getSingle(RuleType_Description).(string) + + feat := new(Feature) + feat.Type = "Feature" + feat.Tags = tags + feat.Location = astLocation(featureLine) + feat.Language = featureLine.GherkinDialect + feat.Keyword = featureLine.Keyword + feat.Name = featureLine.Text + feat.Description = description + feat.Background = background + feat.ScenarioDefinitions = scenarioDefinitions + feat.Comments = t.comments + return feat, nil + } + return node, nil +} + +func astLocation(t *Token) *Location { + return &Location{ + Line: t.Location.Line, + Column: t.Location.Column, + } +} + +func astTableRows(t *astNode) (rows []*TableRow, err error) { + rows = []*TableRow{} + tokens := t.getTokens(TokenType_TableRow) + for i := range tokens { + row := new(TableRow) + row.Type = "TableRow" + row.Location = astLocation(tokens[i]) + row.Cells = astTableCells(tokens[i]) + rows = append(rows, row) + } + err = ensureCellCount(rows) + return +} + +func ensureCellCount(rows []*TableRow) error { + if len(rows) <= 1 { + return nil + } + cellCount := len(rows[0].Cells) + for i := range rows { + if cellCount != len(rows[i].Cells) { + return &parseError{"inconsistent cell count within the table", &Location{ + Line: rows[i].Location.Line, + Column: rows[i].Location.Column, + }} + } + } + return nil +} + +func astTableCells(t *Token) (cells []*TableCell) { + cells = []*TableCell{} + for i := range t.Items { + item := t.Items[i] + cell := new(TableCell) + cell.Type = "TableCell" + cell.Location = &Location{ + Line: t.Location.Line, + Column: item.Column, + } + cell.Value = item.Text + cells = append(cells, cell) + } + return +} + +func astSteps(t *astNode) (steps []*Step) { + steps = []*Step{} + tokens := t.getItems(RuleType_Step) + for i := range tokens { + step, _ := tokens[i].(*Step) + steps = append(steps, step) + } + return +} + +func astExamples(t *astNode) (examples []*Examples) { + examples = []*Examples{} + tokens := t.getItems(RuleType_Examples_Definition) + for i := range tokens { + example, _ := tokens[i].(*Examples) + examples = append(examples, example) + } + return +} + +func astTags(node *astNode) (tags []*Tag) { + tags = []*Tag{} + tagsNode, ok := node.getSingle(RuleType_Tags).(*astNode) + if !ok { + return + } + tokens := tagsNode.getTokens(TokenType_TagLine) + for i := range tokens { + token := tokens[i] + for k := range token.Items { + item := token.Items[k] + tag := new(Tag) + tag.Type = "Tag" + tag.Location = &Location{ + Line: token.Location.Line, + Column: item.Column, + } + tag.Name = item.Text + tags = append(tags, tag) + } + } + return +} diff --git a/gherkin/dialect.go b/gherkin/dialect.go new file mode 100644 index 0000000..e8af1e4 --- /dev/null +++ b/gherkin/dialect.go @@ -0,0 +1,47 @@ +package gherkin + +type GherkinDialect struct { + Language string + Name string + Native string + Keywords map[string][]string +} + +func (g *GherkinDialect) FeatureKeywords() []string { + return g.Keywords["feature"] +} + +func (g *GherkinDialect) ScenarioKeywords() []string { + return g.Keywords["scenario"] +} + +func (g *GherkinDialect) StepKeywords() []string { + result := g.Keywords["given"] + result = append(result, g.Keywords["when"]...) + result = append(result, g.Keywords["then"]...) + result = append(result, g.Keywords["and"]...) + result = append(result, g.Keywords["but"]...) + return result +} + +func (g *GherkinDialect) BackgroundKeywords() []string { + return g.Keywords["background"] +} + +func (g *GherkinDialect) ScenarioOutlineKeywords() []string { + return g.Keywords["scenarioOutline"] +} + +func (g *GherkinDialect) ExamplesKeywords() []string { + return g.Keywords["examples"] +} + +type GherkinDialectProvider interface { + GetDialect(language string) *GherkinDialect +} + +type gherkinDialectMap map[string]*GherkinDialect + +func (g gherkinDialectMap) GetDialect(language string) *GherkinDialect { + return g[language] +} diff --git a/gherkin/dialects_builtin.go b/gherkin/dialects_builtin.go new file mode 100644 index 0000000..1d74625 --- /dev/null +++ b/gherkin/dialects_builtin.go @@ -0,0 +1,2988 @@ +package gherkin + +// Builtin dialects for af (Afrikaans), am (Armenian), ar (Arabic), bg (Bulgarian), bm (Malay), bs (Bosnian), ca (Catalan), cs (Czech), cy-GB (Welsh), da (Danish), de (German), el (Greek), em (Emoji), en (English), en-Scouse (Scouse), en-au (Australian), en-lol (LOLCAT), en-old (Old English), en-pirate (Pirate), eo (Esperanto), es (Spanish), et (Estonian), fa (Persian), fi (Finnish), fr (French), ga (Irish), gj (Gujarati), gl (Galician), he (Hebrew), hi (Hindi), hr (Croatian), ht (Creole), hu (Hungarian), id (Indonesian), is (Icelandic), it (Italian), ja (Japanese), jv (Javanese), kn (Kannada), ko (Korean), lt (Lithuanian), lu (Luxemburgish), lv (Latvian), mn (Mongolian), nl (Dutch), no (Norwegian), pa (Panjabi), pl (Polish), pt (Portuguese), ro (Romanian), ru (Russian), sk (Slovak), sl (Slovenian), sr-Cyrl (Serbian), sr-Latn (Serbian (Latin)), sv (Swedish), ta (Tamil), th (Thai), tl (Telugu), tlh (Klingon), tr (Turkish), tt (Tatar), uk (Ukrainian), ur (Urdu), uz (Uzbek), vi (Vietnamese), zh-CN (Chinese simplified), zh-TW (Chinese traditional) +func GherkinDialectsBuildin() GherkinDialectProvider { + return buildinDialects +} + +const ( + feature = "feature" + background = "background" + scenario = "scenario" + scenarioOutline = "scenarioOutline" + examples = "examples" + given = "given" + when = "when" + then = "then" + and = "and" + but = "but" +) + +var buildinDialects = gherkinDialectMap{ + "af": &GherkinDialect{ + "af", "Afrikaans", "Afrikaans", map[string][]string{ + and: []string{ + "* ", + "En ", + }, + background: []string{ + "Agtergrond", + }, + but: []string{ + "* ", + "Maar ", + }, + examples: []string{ + "Voorbeelde", + }, + feature: []string{ + "Funksie", + "Besigheid Behoefte", + "Vermoë", + }, + given: []string{ + "* ", + "Gegewe ", + }, + scenario: []string{ + "Situasie", + }, + scenarioOutline: []string{ + "Situasie Uiteensetting", + }, + then: []string{ + "* ", + "Dan ", + }, + when: []string{ + "* ", + "Wanneer ", + }, + }, + }, + "am": &GherkinDialect{ + "am", "Armenian", "հայերեն", map[string][]string{ + and: []string{ + "* ", + "Եվ ", + }, + background: []string{ + "Կոնտեքստ", + }, + but: []string{ + "* ", + "Բայց ", + }, + examples: []string{ + "Օրինակներ", + }, + feature: []string{ + "Ֆունկցիոնալություն", + "Հատկություն", + }, + given: []string{ + "* ", + "Դիցուք ", + }, + scenario: []string{ + "Սցենար", + }, + scenarioOutline: []string{ + "Սցենարի կառուցվացքը", + }, + then: []string{ + "* ", + "Ապա ", + }, + when: []string{ + "* ", + "Եթե ", + "Երբ ", + }, + }, + }, + "ar": &GherkinDialect{ + "ar", "Arabic", "العربية", map[string][]string{ + and: []string{ + "* ", + "و ", + }, + background: []string{ + "الخلفية", + }, + but: []string{ + "* ", + "لكن ", + }, + examples: []string{ + "امثلة", + }, + feature: []string{ + "خاصية", + }, + given: []string{ + "* ", + "بفرض ", + }, + scenario: []string{ + "سيناريو", + }, + scenarioOutline: []string{ + "سيناريو مخطط", + }, + then: []string{ + "* ", + "اذاً ", + "ثم ", + }, + when: []string{ + "* ", + "متى ", + "عندما ", + }, + }, + }, + "bg": &GherkinDialect{ + "bg", "Bulgarian", "български", map[string][]string{ + and: []string{ + "* ", + "И ", + }, + background: []string{ + "Предистория", + }, + but: []string{ + "* ", + "Но ", + }, + examples: []string{ + "Примери", + }, + feature: []string{ + "Функционалност", + }, + given: []string{ + "* ", + "Дадено ", + }, + scenario: []string{ + "Сценарий", + }, + scenarioOutline: []string{ + "Рамка на сценарий", + }, + then: []string{ + "* ", + "То ", + }, + when: []string{ + "* ", + "Когато ", + }, + }, + }, + "bm": &GherkinDialect{ + "bm", "Malay", "Bahasa Melayu", map[string][]string{ + and: []string{ + "* ", + "Dan ", + }, + background: []string{ + "Latar Belakang", + }, + but: []string{ + "* ", + "Tetapi ", + "Tapi ", + }, + examples: []string{ + "Contoh", + }, + feature: []string{ + "Fungsi", + }, + given: []string{ + "* ", + "Diberi ", + "Bagi ", + }, + scenario: []string{ + "Senario", + "Situasi", + "Keadaan", + }, + scenarioOutline: []string{ + "Kerangka Senario", + "Kerangka Situasi", + "Kerangka Keadaan", + "Garis Panduan Senario", + }, + then: []string{ + "* ", + "Maka ", + "Kemudian ", + }, + when: []string{ + "* ", + "Apabila ", + }, + }, + }, + "bs": &GherkinDialect{ + "bs", "Bosnian", "Bosanski", map[string][]string{ + and: []string{ + "* ", + "I ", + "A ", + }, + background: []string{ + "Pozadina", + }, + but: []string{ + "* ", + "Ali ", + }, + examples: []string{ + "Primjeri", + }, + feature: []string{ + "Karakteristika", + }, + given: []string{ + "* ", + "Dato ", + }, + scenario: []string{ + "Scenariju", + "Scenario", + }, + scenarioOutline: []string{ + "Scenariju-obris", + "Scenario-outline", + }, + then: []string{ + "* ", + "Zatim ", + }, + when: []string{ + "* ", + "Kada ", + }, + }, + }, + "ca": &GherkinDialect{ + "ca", "Catalan", "català", map[string][]string{ + and: []string{ + "* ", + "I ", + }, + background: []string{ + "Rerefons", + "Antecedents", + }, + but: []string{ + "* ", + "Però ", + }, + examples: []string{ + "Exemples", + }, + feature: []string{ + "Característica", + "Funcionalitat", + }, + given: []string{ + "* ", + "Donat ", + "Donada ", + "Atès ", + "Atesa ", + }, + scenario: []string{ + "Escenari", + }, + scenarioOutline: []string{ + "Esquema de l'escenari", + }, + then: []string{ + "* ", + "Aleshores ", + "Cal ", + }, + when: []string{ + "* ", + "Quan ", + }, + }, + }, + "cs": &GherkinDialect{ + "cs", "Czech", "Česky", map[string][]string{ + and: []string{ + "* ", + "A také ", + "A ", + }, + background: []string{ + "Pozadí", + "Kontext", + }, + but: []string{ + "* ", + "Ale ", + }, + examples: []string{ + "Příklady", + }, + feature: []string{ + "Požadavek", + }, + given: []string{ + "* ", + "Pokud ", + "Za předpokladu ", + }, + scenario: []string{ + "Scénář", + }, + scenarioOutline: []string{ + "Náčrt Scénáře", + "Osnova scénáře", + }, + then: []string{ + "* ", + "Pak ", + }, + when: []string{ + "* ", + "Když ", + }, + }, + }, + "cy-GB": &GherkinDialect{ + "cy-GB", "Welsh", "Cymraeg", map[string][]string{ + and: []string{ + "* ", + "A ", + }, + background: []string{ + "Cefndir", + }, + but: []string{ + "* ", + "Ond ", + }, + examples: []string{ + "Enghreifftiau", + }, + feature: []string{ + "Arwedd", + }, + given: []string{ + "* ", + "Anrhegedig a ", + }, + scenario: []string{ + "Scenario", + }, + scenarioOutline: []string{ + "Scenario Amlinellol", + }, + then: []string{ + "* ", + "Yna ", + }, + when: []string{ + "* ", + "Pryd ", + }, + }, + }, + "da": &GherkinDialect{ + "da", "Danish", "dansk", map[string][]string{ + and: []string{ + "* ", + "Og ", + }, + background: []string{ + "Baggrund", + }, + but: []string{ + "* ", + "Men ", + }, + examples: []string{ + "Eksempler", + }, + feature: []string{ + "Egenskab", + }, + given: []string{ + "* ", + "Givet ", + }, + scenario: []string{ + "Scenarie", + }, + scenarioOutline: []string{ + "Abstrakt Scenario", + }, + then: []string{ + "* ", + "Så ", + }, + when: []string{ + "* ", + "Når ", + }, + }, + }, + "de": &GherkinDialect{ + "de", "German", "Deutsch", map[string][]string{ + and: []string{ + "* ", + "Und ", + }, + background: []string{ + "Grundlage", + }, + but: []string{ + "* ", + "Aber ", + }, + examples: []string{ + "Beispiele", + }, + feature: []string{ + "Funktionalität", + }, + given: []string{ + "* ", + "Angenommen ", + "Gegeben sei ", + "Gegeben seien ", + }, + scenario: []string{ + "Szenario", + }, + scenarioOutline: []string{ + "Szenariogrundriss", + }, + then: []string{ + "* ", + "Dann ", + }, + when: []string{ + "* ", + "Wenn ", + }, + }, + }, + "el": &GherkinDialect{ + "el", "Greek", "Ελληνικά", map[string][]string{ + and: []string{ + "* ", + "Και ", + }, + background: []string{ + "Υπόβαθρο", + }, + but: []string{ + "* ", + "Αλλά ", + }, + examples: []string{ + "Παραδείγματα", + "Σενάρια", + }, + feature: []string{ + "Δυνατότητα", + "Λειτουργία", + }, + given: []string{ + "* ", + "Δεδομένου ", + }, + scenario: []string{ + "Σενάριο", + }, + scenarioOutline: []string{ + "Περιγραφή Σεναρίου", + }, + then: []string{ + "* ", + "Τότε ", + }, + when: []string{ + "* ", + "Όταν ", + }, + }, + }, + "em": &GherkinDialect{ + "em", "Emoji", "😀", map[string][]string{ + and: []string{ + "* ", + "😂", + }, + background: []string{ + "💤", + }, + but: []string{ + "* ", + "😔", + }, + examples: []string{ + "📓", + }, + feature: []string{ + "📚", + }, + given: []string{ + "* ", + "😐", + }, + scenario: []string{ + "📕", + }, + scenarioOutline: []string{ + "📖", + }, + then: []string{ + "* ", + "🙏", + }, + when: []string{ + "* ", + "🎬", + }, + }, + }, + "en": &GherkinDialect{ + "en", "English", "English", map[string][]string{ + and: []string{ + "* ", + "And ", + }, + background: []string{ + "Background", + }, + but: []string{ + "* ", + "But ", + }, + examples: []string{ + "Examples", + "Scenarios", + }, + feature: []string{ + "Feature", + "Business Need", + "Ability", + }, + given: []string{ + "* ", + "Given ", + }, + scenario: []string{ + "Scenario", + }, + scenarioOutline: []string{ + "Scenario Outline", + "Scenario Template", + }, + then: []string{ + "* ", + "Then ", + }, + when: []string{ + "* ", + "When ", + }, + }, + }, + "en-Scouse": &GherkinDialect{ + "en-Scouse", "Scouse", "Scouse", map[string][]string{ + and: []string{ + "* ", + "An ", + }, + background: []string{ + "Dis is what went down", + }, + but: []string{ + "* ", + "Buh ", + }, + examples: []string{ + "Examples", + }, + feature: []string{ + "Feature", + }, + given: []string{ + "* ", + "Givun ", + "Youse know when youse got ", + }, + scenario: []string{ + "The thing of it is", + }, + scenarioOutline: []string{ + "Wharrimean is", + }, + then: []string{ + "* ", + "Dun ", + "Den youse gotta ", + }, + when: []string{ + "* ", + "Wun ", + "Youse know like when ", + }, + }, + }, + "en-au": &GherkinDialect{ + "en-au", "Australian", "Australian", map[string][]string{ + and: []string{ + "* ", + "Too right ", + }, + background: []string{ + "First off", + }, + but: []string{ + "* ", + "Yeah nah ", + }, + examples: []string{ + "You'll wanna", + }, + feature: []string{ + "Pretty much", + }, + given: []string{ + "* ", + "Y'know ", + }, + scenario: []string{ + "Awww, look mate", + }, + scenarioOutline: []string{ + "Reckon it's like", + }, + then: []string{ + "* ", + "But at the end of the day I reckon ", + }, + when: []string{ + "* ", + "It's just unbelievable ", + }, + }, + }, + "en-lol": &GherkinDialect{ + "en-lol", "LOLCAT", "LOLCAT", map[string][]string{ + and: []string{ + "* ", + "AN ", + }, + background: []string{ + "B4", + }, + but: []string{ + "* ", + "BUT ", + }, + examples: []string{ + "EXAMPLZ", + }, + feature: []string{ + "OH HAI", + }, + given: []string{ + "* ", + "I CAN HAZ ", + }, + scenario: []string{ + "MISHUN", + }, + scenarioOutline: []string{ + "MISHUN SRSLY", + }, + then: []string{ + "* ", + "DEN ", + }, + when: []string{ + "* ", + "WEN ", + }, + }, + }, + "en-old": &GherkinDialect{ + "en-old", "Old English", "Englisc", map[string][]string{ + and: []string{ + "* ", + "Ond ", + "7 ", + }, + background: []string{ + "Aer", + "Ær", + }, + but: []string{ + "* ", + "Ac ", + }, + examples: []string{ + "Se the", + "Se þe", + "Se ðe", + }, + feature: []string{ + "Hwaet", + "Hwæt", + }, + given: []string{ + "* ", + "Thurh ", + "Þurh ", + "Ðurh ", + }, + scenario: []string{ + "Swa", + }, + scenarioOutline: []string{ + "Swa hwaer swa", + "Swa hwær swa", + }, + then: []string{ + "* ", + "Tha ", + "Þa ", + "Ða ", + "Tha the ", + "Þa þe ", + "Ða ðe ", + }, + when: []string{ + "* ", + "Tha ", + "Þa ", + "Ða ", + }, + }, + }, + "en-pirate": &GherkinDialect{ + "en-pirate", "Pirate", "Pirate", map[string][]string{ + and: []string{ + "* ", + "Aye ", + }, + background: []string{ + "Yo-ho-ho", + }, + but: []string{ + "* ", + "Avast! ", + }, + examples: []string{ + "Dead men tell no tales", + }, + feature: []string{ + "Ahoy matey!", + }, + given: []string{ + "* ", + "Gangway! ", + }, + scenario: []string{ + "Heave to", + }, + scenarioOutline: []string{ + "Shiver me timbers", + }, + then: []string{ + "* ", + "Let go and haul ", + }, + when: []string{ + "* ", + "Blimey! ", + }, + }, + }, + "eo": &GherkinDialect{ + "eo", "Esperanto", "Esperanto", map[string][]string{ + and: []string{ + "* ", + "Kaj ", + }, + background: []string{ + "Fono", + }, + but: []string{ + "* ", + "Sed ", + }, + examples: []string{ + "Ekzemploj", + }, + feature: []string{ + "Trajto", + }, + given: []string{ + "* ", + "Donitaĵo ", + "Komence ", + }, + scenario: []string{ + "Scenaro", + "Kazo", + }, + scenarioOutline: []string{ + "Konturo de la scenaro", + "Skizo", + "Kazo-skizo", + }, + then: []string{ + "* ", + "Do ", + }, + when: []string{ + "* ", + "Se ", + }, + }, + }, + "es": &GherkinDialect{ + "es", "Spanish", "español", map[string][]string{ + and: []string{ + "* ", + "Y ", + "E ", + }, + background: []string{ + "Antecedentes", + }, + but: []string{ + "* ", + "Pero ", + }, + examples: []string{ + "Ejemplos", + }, + feature: []string{ + "Característica", + }, + given: []string{ + "* ", + "Dado ", + "Dada ", + "Dados ", + "Dadas ", + }, + scenario: []string{ + "Escenario", + }, + scenarioOutline: []string{ + "Esquema del escenario", + }, + then: []string{ + "* ", + "Entonces ", + }, + when: []string{ + "* ", + "Cuando ", + }, + }, + }, + "et": &GherkinDialect{ + "et", "Estonian", "eesti keel", map[string][]string{ + and: []string{ + "* ", + "Ja ", + }, + background: []string{ + "Taust", + }, + but: []string{ + "* ", + "Kuid ", + }, + examples: []string{ + "Juhtumid", + }, + feature: []string{ + "Omadus", + }, + given: []string{ + "* ", + "Eeldades ", + }, + scenario: []string{ + "Stsenaarium", + }, + scenarioOutline: []string{ + "Raamstsenaarium", + }, + then: []string{ + "* ", + "Siis ", + }, + when: []string{ + "* ", + "Kui ", + }, + }, + }, + "fa": &GherkinDialect{ + "fa", "Persian", "فارسی", map[string][]string{ + and: []string{ + "* ", + "و ", + }, + background: []string{ + "زمینه", + }, + but: []string{ + "* ", + "اما ", + }, + examples: []string{ + "نمونه ها", + }, + feature: []string{ + "وِیژگی", + }, + given: []string{ + "* ", + "با فرض ", + }, + scenario: []string{ + "سناریو", + }, + scenarioOutline: []string{ + "الگوی سناریو", + }, + then: []string{ + "* ", + "آنگاه ", + }, + when: []string{ + "* ", + "هنگامی ", + }, + }, + }, + "fi": &GherkinDialect{ + "fi", "Finnish", "suomi", map[string][]string{ + and: []string{ + "* ", + "Ja ", + }, + background: []string{ + "Tausta", + }, + but: []string{ + "* ", + "Mutta ", + }, + examples: []string{ + "Tapaukset", + }, + feature: []string{ + "Ominaisuus", + }, + given: []string{ + "* ", + "Oletetaan ", + }, + scenario: []string{ + "Tapaus", + }, + scenarioOutline: []string{ + "Tapausaihio", + }, + then: []string{ + "* ", + "Niin ", + }, + when: []string{ + "* ", + "Kun ", + }, + }, + }, + "fr": &GherkinDialect{ + "fr", "French", "français", map[string][]string{ + and: []string{ + "* ", + "Et que ", + "Et qu'", + "Et ", + }, + background: []string{ + "Contexte", + }, + but: []string{ + "* ", + "Mais que ", + "Mais qu'", + "Mais ", + }, + examples: []string{ + "Exemples", + }, + feature: []string{ + "Fonctionnalité", + }, + given: []string{ + "* ", + "Soit ", + "Etant donné que ", + "Etant donné qu'", + "Etant donné ", + "Etant donnée ", + "Etant donnés ", + "Etant données ", + "Étant donné que ", + "Étant donné qu'", + "Étant donné ", + "Étant donnée ", + "Étant donnés ", + "Étant données ", + }, + scenario: []string{ + "Scénario", + }, + scenarioOutline: []string{ + "Plan du scénario", + "Plan du Scénario", + }, + then: []string{ + "* ", + "Alors ", + }, + when: []string{ + "* ", + "Quand ", + "Lorsque ", + "Lorsqu'", + }, + }, + }, + "ga": &GherkinDialect{ + "ga", "Irish", "Gaeilge", map[string][]string{ + and: []string{ + "* ", + "Agus", + }, + background: []string{ + "Cúlra", + }, + but: []string{ + "* ", + "Ach", + }, + examples: []string{ + "Samplaí", + }, + feature: []string{ + "Gné", + }, + given: []string{ + "* ", + "Cuir i gcás go", + "Cuir i gcás nach", + "Cuir i gcás gur", + "Cuir i gcás nár", + }, + scenario: []string{ + "Cás", + }, + scenarioOutline: []string{ + "Cás Achomair", + }, + then: []string{ + "* ", + "Ansin", + }, + when: []string{ + "* ", + "Nuair a", + "Nuair nach", + "Nuair ba", + "Nuair nár", + }, + }, + }, + "gj": &GherkinDialect{ + "gj", "Gujarati", "ગુજરાતી", map[string][]string{ + and: []string{ + "* ", + "અને ", + }, + background: []string{ + "બેકગ્રાઉન્ડ", + }, + but: []string{ + "* ", + "પણ ", + }, + examples: []string{ + "ઉદાહરણો", + }, + feature: []string{ + "લક્ષણ", + "વ્યાપાર જરૂર", + "ક્ષમતા", + }, + given: []string{ + "* ", + "આપેલ છે ", + }, + scenario: []string{ + "સ્થિતિ", + }, + scenarioOutline: []string{ + "પરિદ્દશ્ય રૂપરેખા", + "પરિદ્દશ્ય ઢાંચો", + }, + then: []string{ + "* ", + "પછી ", + }, + when: []string{ + "* ", + "ક્યારે ", + }, + }, + }, + "gl": &GherkinDialect{ + "gl", "Galician", "galego", map[string][]string{ + and: []string{ + "* ", + "E ", + }, + background: []string{ + "Contexto", + }, + but: []string{ + "* ", + "Mais ", + "Pero ", + }, + examples: []string{ + "Exemplos", + }, + feature: []string{ + "Característica", + }, + given: []string{ + "* ", + "Dado ", + "Dada ", + "Dados ", + "Dadas ", + }, + scenario: []string{ + "Escenario", + }, + scenarioOutline: []string{ + "Esbozo do escenario", + }, + then: []string{ + "* ", + "Entón ", + "Logo ", + }, + when: []string{ + "* ", + "Cando ", + }, + }, + }, + "he": &GherkinDialect{ + "he", "Hebrew", "עברית", map[string][]string{ + and: []string{ + "* ", + "וגם ", + }, + background: []string{ + "רקע", + }, + but: []string{ + "* ", + "אבל ", + }, + examples: []string{ + "דוגמאות", + }, + feature: []string{ + "תכונה", + }, + given: []string{ + "* ", + "בהינתן ", + }, + scenario: []string{ + "תרחיש", + }, + scenarioOutline: []string{ + "תבנית תרחיש", + }, + then: []string{ + "* ", + "אז ", + "אזי ", + }, + when: []string{ + "* ", + "כאשר ", + }, + }, + }, + "hi": &GherkinDialect{ + "hi", "Hindi", "हिंदी", map[string][]string{ + and: []string{ + "* ", + "और ", + "तथा ", + }, + background: []string{ + "पृष्ठभूमि", + }, + but: []string{ + "* ", + "पर ", + "परन्तु ", + "किन्तु ", + }, + examples: []string{ + "उदाहरण", + }, + feature: []string{ + "रूप लेख", + }, + given: []string{ + "* ", + "अगर ", + "यदि ", + "चूंकि ", + }, + scenario: []string{ + "परिदृश्य", + }, + scenarioOutline: []string{ + "परिदृश्य रूपरेखा", + }, + then: []string{ + "* ", + "तब ", + "तदा ", + }, + when: []string{ + "* ", + "जब ", + "कदा ", + }, + }, + }, + "hr": &GherkinDialect{ + "hr", "Croatian", "hrvatski", map[string][]string{ + and: []string{ + "* ", + "I ", + }, + background: []string{ + "Pozadina", + }, + but: []string{ + "* ", + "Ali ", + }, + examples: []string{ + "Primjeri", + "Scenariji", + }, + feature: []string{ + "Osobina", + "Mogućnost", + "Mogucnost", + }, + given: []string{ + "* ", + "Zadan ", + "Zadani ", + "Zadano ", + }, + scenario: []string{ + "Scenarij", + }, + scenarioOutline: []string{ + "Skica", + "Koncept", + }, + then: []string{ + "* ", + "Onda ", + }, + when: []string{ + "* ", + "Kada ", + "Kad ", + }, + }, + }, + "ht": &GherkinDialect{ + "ht", "Creole", "kreyòl", map[string][]string{ + and: []string{ + "* ", + "Ak ", + "Epi ", + "E ", + }, + background: []string{ + "Kontèks", + "Istorik", + }, + but: []string{ + "* ", + "Men ", + }, + examples: []string{ + "Egzanp", + }, + feature: []string{ + "Karakteristik", + "Mak", + "Fonksyonalite", + }, + given: []string{ + "* ", + "Sipoze ", + "Sipoze ke ", + "Sipoze Ke ", + }, + scenario: []string{ + "Senaryo", + }, + scenarioOutline: []string{ + "Plan senaryo", + "Plan Senaryo", + "Senaryo deskripsyon", + "Senaryo Deskripsyon", + "Dyagram senaryo", + "Dyagram Senaryo", + }, + then: []string{ + "* ", + "Lè sa a ", + "Le sa a ", + }, + when: []string{ + "* ", + "Lè ", + "Le ", + }, + }, + }, + "hu": &GherkinDialect{ + "hu", "Hungarian", "magyar", map[string][]string{ + and: []string{ + "* ", + "És ", + }, + background: []string{ + "Háttér", + }, + but: []string{ + "* ", + "De ", + }, + examples: []string{ + "Példák", + }, + feature: []string{ + "Jellemző", + }, + given: []string{ + "* ", + "Amennyiben ", + "Adott ", + }, + scenario: []string{ + "Forgatókönyv", + }, + scenarioOutline: []string{ + "Forgatókönyv vázlat", + }, + then: []string{ + "* ", + "Akkor ", + }, + when: []string{ + "* ", + "Majd ", + "Ha ", + "Amikor ", + }, + }, + }, + "id": &GherkinDialect{ + "id", "Indonesian", "Bahasa Indonesia", map[string][]string{ + and: []string{ + "* ", + "Dan ", + }, + background: []string{ + "Dasar", + }, + but: []string{ + "* ", + "Tapi ", + }, + examples: []string{ + "Contoh", + }, + feature: []string{ + "Fitur", + }, + given: []string{ + "* ", + "Dengan ", + }, + scenario: []string{ + "Skenario", + }, + scenarioOutline: []string{ + "Skenario konsep", + }, + then: []string{ + "* ", + "Maka ", + }, + when: []string{ + "* ", + "Ketika ", + }, + }, + }, + "is": &GherkinDialect{ + "is", "Icelandic", "Íslenska", map[string][]string{ + and: []string{ + "* ", + "Og ", + }, + background: []string{ + "Bakgrunnur", + }, + but: []string{ + "* ", + "En ", + }, + examples: []string{ + "Dæmi", + "Atburðarásir", + }, + feature: []string{ + "Eiginleiki", + }, + given: []string{ + "* ", + "Ef ", + }, + scenario: []string{ + "Atburðarás", + }, + scenarioOutline: []string{ + "Lýsing Atburðarásar", + "Lýsing Dæma", + }, + then: []string{ + "* ", + "Þá ", + }, + when: []string{ + "* ", + "Þegar ", + }, + }, + }, + "it": &GherkinDialect{ + "it", "Italian", "italiano", map[string][]string{ + and: []string{ + "* ", + "E ", + }, + background: []string{ + "Contesto", + }, + but: []string{ + "* ", + "Ma ", + }, + examples: []string{ + "Esempi", + }, + feature: []string{ + "Funzionalità", + }, + given: []string{ + "* ", + "Dato ", + "Data ", + "Dati ", + "Date ", + }, + scenario: []string{ + "Scenario", + }, + scenarioOutline: []string{ + "Schema dello scenario", + }, + then: []string{ + "* ", + "Allora ", + }, + when: []string{ + "* ", + "Quando ", + }, + }, + }, + "ja": &GherkinDialect{ + "ja", "Japanese", "日本語", map[string][]string{ + and: []string{ + "* ", + "かつ", + }, + background: []string{ + "背景", + }, + but: []string{ + "* ", + "しかし", + "但し", + "ただし", + }, + examples: []string{ + "例", + "サンプル", + }, + feature: []string{ + "フィーチャ", + "機能", + }, + given: []string{ + "* ", + "前提", + }, + scenario: []string{ + "シナリオ", + }, + scenarioOutline: []string{ + "シナリオアウトライン", + "シナリオテンプレート", + "テンプレ", + "シナリオテンプレ", + }, + then: []string{ + "* ", + "ならば", + }, + when: []string{ + "* ", + "もし", + }, + }, + }, + "jv": &GherkinDialect{ + "jv", "Javanese", "Basa Jawa", map[string][]string{ + and: []string{ + "* ", + "Lan ", + }, + background: []string{ + "Dasar", + }, + but: []string{ + "* ", + "Tapi ", + "Nanging ", + "Ananging ", + }, + examples: []string{ + "Conto", + "Contone", + }, + feature: []string{ + "Fitur", + }, + given: []string{ + "* ", + "Nalika ", + "Nalikaning ", + }, + scenario: []string{ + "Skenario", + }, + scenarioOutline: []string{ + "Konsep skenario", + }, + then: []string{ + "* ", + "Njuk ", + "Banjur ", + }, + when: []string{ + "* ", + "Manawa ", + "Menawa ", + }, + }, + }, + "kn": &GherkinDialect{ + "kn", "Kannada", "ಕನ್ನಡ", map[string][]string{ + and: []string{ + "* ", + "ಮತ್ತು ", + }, + background: []string{ + "ಹಿನ್ನೆಲೆ", + }, + but: []string{ + "* ", + "ಆದರೆ ", + }, + examples: []string{ + "ಉದಾಹರಣೆಗಳು", + }, + feature: []string{ + "ಹೆಚ್ಚಳ", + }, + given: []string{ + "* ", + "ನೀಡಿದ ", + }, + scenario: []string{ + "ಕಥಾಸಾರಾಂಶ", + }, + scenarioOutline: []string{ + "ವಿವರಣೆ", + }, + then: []string{ + "* ", + "ನಂತರ ", + }, + when: []string{ + "* ", + "ಸ್ಥಿತಿಯನ್ನು ", + }, + }, + }, + "ko": &GherkinDialect{ + "ko", "Korean", "한국어", map[string][]string{ + and: []string{ + "* ", + "그리고", + }, + background: []string{ + "배경", + }, + but: []string{ + "* ", + "하지만", + "단", + }, + examples: []string{ + "예", + }, + feature: []string{ + "기능", + }, + given: []string{ + "* ", + "조건", + "먼저", + }, + scenario: []string{ + "시나리오", + }, + scenarioOutline: []string{ + "시나리오 개요", + }, + then: []string{ + "* ", + "그러면", + }, + when: []string{ + "* ", + "만일", + "만약", + }, + }, + }, + "lt": &GherkinDialect{ + "lt", "Lithuanian", "lietuvių kalba", map[string][]string{ + and: []string{ + "* ", + "Ir ", + }, + background: []string{ + "Kontekstas", + }, + but: []string{ + "* ", + "Bet ", + }, + examples: []string{ + "Pavyzdžiai", + "Scenarijai", + "Variantai", + }, + feature: []string{ + "Savybė", + }, + given: []string{ + "* ", + "Duota ", + }, + scenario: []string{ + "Scenarijus", + }, + scenarioOutline: []string{ + "Scenarijaus šablonas", + }, + then: []string{ + "* ", + "Tada ", + }, + when: []string{ + "* ", + "Kai ", + }, + }, + }, + "lu": &GherkinDialect{ + "lu", "Luxemburgish", "Lëtzebuergesch", map[string][]string{ + and: []string{ + "* ", + "an ", + "a ", + }, + background: []string{ + "Hannergrond", + }, + but: []string{ + "* ", + "awer ", + "mä ", + }, + examples: []string{ + "Beispiller", + }, + feature: []string{ + "Funktionalitéit", + }, + given: []string{ + "* ", + "ugeholl ", + }, + scenario: []string{ + "Szenario", + }, + scenarioOutline: []string{ + "Plang vum Szenario", + }, + then: []string{ + "* ", + "dann ", + }, + when: []string{ + "* ", + "wann ", + }, + }, + }, + "lv": &GherkinDialect{ + "lv", "Latvian", "latviešu", map[string][]string{ + and: []string{ + "* ", + "Un ", + }, + background: []string{ + "Konteksts", + "Situācija", + }, + but: []string{ + "* ", + "Bet ", + }, + examples: []string{ + "Piemēri", + "Paraugs", + }, + feature: []string{ + "Funkcionalitāte", + "Fīča", + }, + given: []string{ + "* ", + "Kad ", + }, + scenario: []string{ + "Scenārijs", + }, + scenarioOutline: []string{ + "Scenārijs pēc parauga", + }, + then: []string{ + "* ", + "Tad ", + }, + when: []string{ + "* ", + "Ja ", + }, + }, + }, + "mn": &GherkinDialect{ + "mn", "Mongolian", "монгол", map[string][]string{ + and: []string{ + "* ", + "Мөн ", + "Тэгээд ", + }, + background: []string{ + "Агуулга", + }, + but: []string{ + "* ", + "Гэхдээ ", + "Харин ", + }, + examples: []string{ + "Тухайлбал", + }, + feature: []string{ + "Функц", + "Функционал", + }, + given: []string{ + "* ", + "Өгөгдсөн нь ", + "Анх ", + }, + scenario: []string{ + "Сценар", + }, + scenarioOutline: []string{ + "Сценарын төлөвлөгөө", + }, + then: []string{ + "* ", + "Тэгэхэд ", + "Үүний дараа ", + }, + when: []string{ + "* ", + "Хэрэв ", + }, + }, + }, + "nl": &GherkinDialect{ + "nl", "Dutch", "Nederlands", map[string][]string{ + and: []string{ + "* ", + "En ", + }, + background: []string{ + "Achtergrond", + }, + but: []string{ + "* ", + "Maar ", + }, + examples: []string{ + "Voorbeelden", + }, + feature: []string{ + "Functionaliteit", + }, + given: []string{ + "* ", + "Gegeven ", + "Stel ", + }, + scenario: []string{ + "Scenario", + }, + scenarioOutline: []string{ + "Abstract Scenario", + }, + then: []string{ + "* ", + "Dan ", + }, + when: []string{ + "* ", + "Als ", + }, + }, + }, + "no": &GherkinDialect{ + "no", "Norwegian", "norsk", map[string][]string{ + and: []string{ + "* ", + "Og ", + }, + background: []string{ + "Bakgrunn", + }, + but: []string{ + "* ", + "Men ", + }, + examples: []string{ + "Eksempler", + }, + feature: []string{ + "Egenskap", + }, + given: []string{ + "* ", + "Gitt ", + }, + scenario: []string{ + "Scenario", + }, + scenarioOutline: []string{ + "Scenariomal", + "Abstrakt Scenario", + }, + then: []string{ + "* ", + "Så ", + }, + when: []string{ + "* ", + "Når ", + }, + }, + }, + "pa": &GherkinDialect{ + "pa", "Panjabi", "ਪੰਜਾਬੀ", map[string][]string{ + and: []string{ + "* ", + "ਅਤੇ ", + }, + background: []string{ + "ਪਿਛੋਕੜ", + }, + but: []string{ + "* ", + "ਪਰ ", + }, + examples: []string{ + "ਉਦਾਹਰਨਾਂ", + }, + feature: []string{ + "ਖਾਸੀਅਤ", + "ਮੁਹਾਂਦਰਾ", + "ਨਕਸ਼ ਨੁਹਾਰ", + }, + given: []string{ + "* ", + "ਜੇਕਰ ", + "ਜਿਵੇਂ ਕਿ ", + }, + scenario: []string{ + "ਪਟਕਥਾ", + }, + scenarioOutline: []string{ + "ਪਟਕਥਾ ਢਾਂਚਾ", + "ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ", + }, + then: []string{ + "* ", + "ਤਦ ", + }, + when: []string{ + "* ", + "ਜਦੋਂ ", + }, + }, + }, + "pl": &GherkinDialect{ + "pl", "Polish", "polski", map[string][]string{ + and: []string{ + "* ", + "Oraz ", + "I ", + }, + background: []string{ + "Założenia", + }, + but: []string{ + "* ", + "Ale ", + }, + examples: []string{ + "Przykłady", + }, + feature: []string{ + "Właściwość", + "Funkcja", + "Aspekt", + "Potrzeba biznesowa", + }, + given: []string{ + "* ", + "Zakładając ", + "Mając ", + "Zakładając, że ", + }, + scenario: []string{ + "Scenariusz", + }, + scenarioOutline: []string{ + "Szablon scenariusza", + }, + then: []string{ + "* ", + "Wtedy ", + }, + when: []string{ + "* ", + "Jeżeli ", + "Jeśli ", + "Gdy ", + "Kiedy ", + }, + }, + }, + "pt": &GherkinDialect{ + "pt", "Portuguese", "português", map[string][]string{ + and: []string{ + "* ", + "E ", + }, + background: []string{ + "Contexto", + "Cenário de Fundo", + "Cenario de Fundo", + "Fundo", + }, + but: []string{ + "* ", + "Mas ", + }, + examples: []string{ + "Exemplos", + "Cenários", + "Cenarios", + }, + feature: []string{ + "Funcionalidade", + "Característica", + "Caracteristica", + }, + given: []string{ + "* ", + "Dado ", + "Dada ", + "Dados ", + "Dadas ", + }, + scenario: []string{ + "Cenário", + "Cenario", + }, + scenarioOutline: []string{ + "Esquema do Cenário", + "Esquema do Cenario", + "Delineação do Cenário", + "Delineacao do Cenario", + }, + then: []string{ + "* ", + "Então ", + "Entao ", + }, + when: []string{ + "* ", + "Quando ", + }, + }, + }, + "ro": &GherkinDialect{ + "ro", "Romanian", "română", map[string][]string{ + and: []string{ + "* ", + "Si ", + "Și ", + "Şi ", + }, + background: []string{ + "Context", + }, + but: []string{ + "* ", + "Dar ", + }, + examples: []string{ + "Exemple", + }, + feature: []string{ + "Functionalitate", + "Funcționalitate", + "Funcţionalitate", + }, + given: []string{ + "* ", + "Date fiind ", + "Dat fiind ", + "Dati fiind ", + "Dați fiind ", + "Daţi fiind ", + }, + scenario: []string{ + "Scenariu", + }, + scenarioOutline: []string{ + "Structura scenariu", + "Structură scenariu", + }, + then: []string{ + "* ", + "Atunci ", + }, + when: []string{ + "* ", + "Cand ", + "Când ", + }, + }, + }, + "ru": &GherkinDialect{ + "ru", "Russian", "русский", map[string][]string{ + and: []string{ + "* ", + "И ", + "К тому же ", + "Также ", + }, + background: []string{ + "Предыстория", + "Контекст", + }, + but: []string{ + "* ", + "Но ", + "А ", + }, + examples: []string{ + "Примеры", + }, + feature: []string{ + "Функция", + "Функционал", + "Свойство", + }, + given: []string{ + "* ", + "Допустим ", + "Дано ", + "Пусть ", + }, + scenario: []string{ + "Сценарий", + }, + scenarioOutline: []string{ + "Структура сценария", + }, + then: []string{ + "* ", + "То ", + "Тогда ", + }, + when: []string{ + "* ", + "Если ", + "Когда ", + }, + }, + }, + "sk": &GherkinDialect{ + "sk", "Slovak", "Slovensky", map[string][]string{ + and: []string{ + "* ", + "A ", + "A tiež ", + "A taktiež ", + "A zároveň ", + }, + background: []string{ + "Pozadie", + }, + but: []string{ + "* ", + "Ale ", + }, + examples: []string{ + "Príklady", + }, + feature: []string{ + "Požiadavka", + "Funkcia", + "Vlastnosť", + }, + given: []string{ + "* ", + "Pokiaľ ", + "Za predpokladu ", + }, + scenario: []string{ + "Scenár", + }, + scenarioOutline: []string{ + "Náčrt Scenáru", + "Náčrt Scenára", + "Osnova Scenára", + }, + then: []string{ + "* ", + "Tak ", + "Potom ", + }, + when: []string{ + "* ", + "Keď ", + "Ak ", + }, + }, + }, + "sl": &GherkinDialect{ + "sl", "Slovenian", "Slovenski", map[string][]string{ + and: []string{ + "In ", + "Ter ", + }, + background: []string{ + "Kontekst", + "Osnova", + "Ozadje", + }, + but: []string{ + "Toda ", + "Ampak ", + "Vendar ", + }, + examples: []string{ + "Primeri", + "Scenariji", + }, + feature: []string{ + "Funkcionalnost", + "Funkcija", + "Možnosti", + "Moznosti", + "Lastnost", + "Značilnost", + }, + given: []string{ + "Dano ", + "Podano ", + "Zaradi ", + "Privzeto ", + }, + scenario: []string{ + "Scenarij", + "Primer", + }, + scenarioOutline: []string{ + "Struktura scenarija", + "Skica", + "Koncept", + "Oris scenarija", + "Osnutek", + }, + then: []string{ + "Nato ", + "Potem ", + "Takrat ", + }, + when: []string{ + "Ko ", + "Ce ", + "Če ", + "Kadar ", + }, + }, + }, + "sr-Cyrl": &GherkinDialect{ + "sr-Cyrl", "Serbian", "Српски", map[string][]string{ + and: []string{ + "* ", + "И ", + }, + background: []string{ + "Контекст", + "Основа", + "Позадина", + }, + but: []string{ + "* ", + "Али ", + }, + examples: []string{ + "Примери", + "Сценарији", + }, + feature: []string{ + "Функционалност", + "Могућност", + "Особина", + }, + given: []string{ + "* ", + "За дато ", + "За дате ", + "За дати ", + }, + scenario: []string{ + "Сценарио", + "Пример", + }, + scenarioOutline: []string{ + "Структура сценарија", + "Скица", + "Концепт", + }, + then: []string{ + "* ", + "Онда ", + }, + when: []string{ + "* ", + "Када ", + "Кад ", + }, + }, + }, + "sr-Latn": &GherkinDialect{ + "sr-Latn", "Serbian (Latin)", "Srpski (Latinica)", map[string][]string{ + and: []string{ + "* ", + "I ", + }, + background: []string{ + "Kontekst", + "Osnova", + "Pozadina", + }, + but: []string{ + "* ", + "Ali ", + }, + examples: []string{ + "Primeri", + "Scenariji", + }, + feature: []string{ + "Funkcionalnost", + "Mogućnost", + "Mogucnost", + "Osobina", + }, + given: []string{ + "* ", + "Za dato ", + "Za date ", + "Za dati ", + }, + scenario: []string{ + "Scenario", + "Primer", + }, + scenarioOutline: []string{ + "Struktura scenarija", + "Skica", + "Koncept", + }, + then: []string{ + "* ", + "Onda ", + }, + when: []string{ + "* ", + "Kada ", + "Kad ", + }, + }, + }, + "sv": &GherkinDialect{ + "sv", "Swedish", "Svenska", map[string][]string{ + and: []string{ + "* ", + "Och ", + }, + background: []string{ + "Bakgrund", + }, + but: []string{ + "* ", + "Men ", + }, + examples: []string{ + "Exempel", + }, + feature: []string{ + "Egenskap", + }, + given: []string{ + "* ", + "Givet ", + }, + scenario: []string{ + "Scenario", + }, + scenarioOutline: []string{ + "Abstrakt Scenario", + "Scenariomall", + }, + then: []string{ + "* ", + "Så ", + }, + when: []string{ + "* ", + "När ", + }, + }, + }, + "ta": &GherkinDialect{ + "ta", "Tamil", "தமிழ்", map[string][]string{ + and: []string{ + "* ", + "மேலும் ", + "மற்றும் ", + }, + background: []string{ + "பின்னணி", + }, + but: []string{ + "* ", + "ஆனால் ", + }, + examples: []string{ + "எடுத்துக்காட்டுகள்", + "காட்சிகள்", + " நிலைமைகளில்", + }, + feature: []string{ + "அம்சம்", + "வணிக தேவை", + "திறன்", + }, + given: []string{ + "* ", + "கொடுக்கப்பட்ட ", + }, + scenario: []string{ + "காட்சி", + }, + scenarioOutline: []string{ + "காட்சி சுருக்கம்", + "காட்சி வார்ப்புரு", + }, + then: []string{ + "* ", + "அப்பொழுது ", + }, + when: []string{ + "* ", + "எப்போது ", + }, + }, + }, + "th": &GherkinDialect{ + "th", "Thai", "ไทย", map[string][]string{ + and: []string{ + "* ", + "และ ", + }, + background: []string{ + "แนวคิด", + }, + but: []string{ + "* ", + "แต่ ", + }, + examples: []string{ + "ชุดของตัวอย่าง", + "ชุดของเหตุการณ์", + }, + feature: []string{ + "โครงหลัก", + "ความต้องการทางธุรกิจ", + "ความสามารถ", + }, + given: []string{ + "* ", + "กำหนดให้ ", + }, + scenario: []string{ + "เหตุการณ์", + }, + scenarioOutline: []string{ + "สรุปเหตุการณ์", + "โครงสร้างของเหตุการณ์", + }, + then: []string{ + "* ", + "ดังนั้น ", + }, + when: []string{ + "* ", + "เมื่อ ", + }, + }, + }, + "tl": &GherkinDialect{ + "tl", "Telugu", "తెలుగు", map[string][]string{ + and: []string{ + "* ", + "మరియు ", + }, + background: []string{ + "నేపథ్యం", + }, + but: []string{ + "* ", + "కాని ", + }, + examples: []string{ + "ఉదాహరణలు", + }, + feature: []string{ + "గుణము", + }, + given: []string{ + "* ", + "చెప్పబడినది ", + }, + scenario: []string{ + "సన్నివేశం", + }, + scenarioOutline: []string{ + "కథనం", + }, + then: []string{ + "* ", + "అప్పుడు ", + }, + when: []string{ + "* ", + "ఈ పరిస్థితిలో ", + }, + }, + }, + "tlh": &GherkinDialect{ + "tlh", "Klingon", "tlhIngan", map[string][]string{ + and: []string{ + "* ", + "'ej ", + "latlh ", + }, + background: []string{ + "mo'", + }, + but: []string{ + "* ", + "'ach ", + "'a ", + }, + examples: []string{ + "ghantoH", + "lutmey", + }, + feature: []string{ + "Qap", + "Qu'meH 'ut", + "perbogh", + "poQbogh malja'", + "laH", + }, + given: []string{ + "* ", + "ghu' noblu' ", + "DaH ghu' bejlu' ", + }, + scenario: []string{ + "lut", + }, + scenarioOutline: []string{ + "lut chovnatlh", + }, + then: []string{ + "* ", + "vaj ", + }, + when: []string{ + "* ", + "qaSDI' ", + }, + }, + }, + "tr": &GherkinDialect{ + "tr", "Turkish", "Türkçe", map[string][]string{ + and: []string{ + "* ", + "Ve ", + }, + background: []string{ + "Geçmiş", + }, + but: []string{ + "* ", + "Fakat ", + "Ama ", + }, + examples: []string{ + "Örnekler", + }, + feature: []string{ + "Özellik", + }, + given: []string{ + "* ", + "Diyelim ki ", + }, + scenario: []string{ + "Senaryo", + }, + scenarioOutline: []string{ + "Senaryo taslağı", + }, + then: []string{ + "* ", + "O zaman ", + }, + when: []string{ + "* ", + "Eğer ki ", + }, + }, + }, + "tt": &GherkinDialect{ + "tt", "Tatar", "Татарча", map[string][]string{ + and: []string{ + "* ", + "Һәм ", + "Вә ", + }, + background: []string{ + "Кереш", + }, + but: []string{ + "* ", + "Ләкин ", + "Әмма ", + }, + examples: []string{ + "Үрнәкләр", + "Мисаллар", + }, + feature: []string{ + "Мөмкинлек", + "Үзенчәлеклелек", + }, + given: []string{ + "* ", + "Әйтик ", + }, + scenario: []string{ + "Сценарий", + }, + scenarioOutline: []string{ + "Сценарийның төзелеше", + }, + then: []string{ + "* ", + "Нәтиҗәдә ", + }, + when: []string{ + "* ", + "Әгәр ", + }, + }, + }, + "uk": &GherkinDialect{ + "uk", "Ukrainian", "Українська", map[string][]string{ + and: []string{ + "* ", + "І ", + "А також ", + "Та ", + }, + background: []string{ + "Передумова", + }, + but: []string{ + "* ", + "Але ", + }, + examples: []string{ + "Приклади", + }, + feature: []string{ + "Функціонал", + }, + given: []string{ + "* ", + "Припустимо ", + "Припустимо, що ", + "Нехай ", + "Дано ", + }, + scenario: []string{ + "Сценарій", + }, + scenarioOutline: []string{ + "Структура сценарію", + }, + then: []string{ + "* ", + "То ", + "Тоді ", + }, + when: []string{ + "* ", + "Якщо ", + "Коли ", + }, + }, + }, + "ur": &GherkinDialect{ + "ur", "Urdu", "اردو", map[string][]string{ + and: []string{ + "* ", + "اور ", + }, + background: []string{ + "پس منظر", + }, + but: []string{ + "* ", + "لیکن ", + }, + examples: []string{ + "مثالیں", + }, + feature: []string{ + "صلاحیت", + "کاروبار کی ضرورت", + "خصوصیت", + }, + given: []string{ + "* ", + "اگر ", + "بالفرض ", + "فرض کیا ", + }, + scenario: []string{ + "منظرنامہ", + }, + scenarioOutline: []string{ + "منظر نامے کا خاکہ", + }, + then: []string{ + "* ", + "پھر ", + "تب ", + }, + when: []string{ + "* ", + "جب ", + }, + }, + }, + "uz": &GherkinDialect{ + "uz", "Uzbek", "Узбекча", map[string][]string{ + and: []string{ + "* ", + "Ва ", + }, + background: []string{ + "Тарих", + }, + but: []string{ + "* ", + "Лекин ", + "Бирок ", + "Аммо ", + }, + examples: []string{ + "Мисоллар", + }, + feature: []string{ + "Функционал", + }, + given: []string{ + "* ", + "Агар ", + }, + scenario: []string{ + "Сценарий", + }, + scenarioOutline: []string{ + "Сценарий структураси", + }, + then: []string{ + "* ", + "Унда ", + }, + when: []string{ + "* ", + "Агар ", + }, + }, + }, + "vi": &GherkinDialect{ + "vi", "Vietnamese", "Tiếng Việt", map[string][]string{ + and: []string{ + "* ", + "Và ", + }, + background: []string{ + "Bối cảnh", + }, + but: []string{ + "* ", + "Nhưng ", + }, + examples: []string{ + "Dữ liệu", + }, + feature: []string{ + "Tính năng", + }, + given: []string{ + "* ", + "Biết ", + "Cho ", + }, + scenario: []string{ + "Tình huống", + "Kịch bản", + }, + scenarioOutline: []string{ + "Khung tình huống", + "Khung kịch bản", + }, + then: []string{ + "* ", + "Thì ", + }, + when: []string{ + "* ", + "Khi ", + }, + }, + }, + "zh-CN": &GherkinDialect{ + "zh-CN", "Chinese simplified", "简体中文", map[string][]string{ + and: []string{ + "* ", + "而且", + "并且", + "同时", + }, + background: []string{ + "背景", + }, + but: []string{ + "* ", + "但是", + }, + examples: []string{ + "例子", + }, + feature: []string{ + "功能", + }, + given: []string{ + "* ", + "假如", + "假设", + "假定", + }, + scenario: []string{ + "场景", + "剧本", + }, + scenarioOutline: []string{ + "场景大纲", + "剧本大纲", + }, + then: []string{ + "* ", + "那么", + }, + when: []string{ + "* ", + "当", + }, + }, + }, + "zh-TW": &GherkinDialect{ + "zh-TW", "Chinese traditional", "繁體中文", map[string][]string{ + and: []string{ + "* ", + "而且", + "並且", + "同時", + }, + background: []string{ + "背景", + }, + but: []string{ + "* ", + "但是", + }, + examples: []string{ + "例子", + }, + feature: []string{ + "功能", + }, + given: []string{ + "* ", + "假如", + "假設", + "假定", + }, + scenario: []string{ + "場景", + "劇本", + }, + scenarioOutline: []string{ + "場景大綱", + "劇本大綱", + }, + then: []string{ + "* ", + "那麼", + }, + when: []string{ + "* ", + "當", + }, + }, + }, +} diff --git a/gherkin/gherkin.go b/gherkin/gherkin.go new file mode 100644 index 0000000..0dc469c --- /dev/null +++ b/gherkin/gherkin.go @@ -0,0 +1,137 @@ +package gherkin + +import ( + "bufio" + "fmt" + "io" + "strings" +) + +type Parser interface { + StopAtFirstError(b bool) + Parse(s Scanner, m Matcher) (err error) +} + +/* +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 (Abstract Syntax Tree). + +If the scanner sees a # language header, it will reconfigure itself dynamically to look for +Gherkin keywords for the associated language. The keywords are defined in gherkin-languages.json. +*/ +type Scanner interface { + Scan() (line *Line, atEof bool, err error) +} + +type Builder interface { + Build(*Token) (bool, error) + StartRule(RuleType) (bool, error) + EndRule(RuleType) (bool, error) + Reset() +} + +type Token struct { + Type TokenType + Keyword string + Text string + Items []*LineSpan + GherkinDialect string + Indent string + Location *Location +} + +func (t *Token) IsEOF() bool { + return t.Type == TokenType_EOF +} +func (t *Token) String() string { + return fmt.Sprintf("%s: %s/%s", t.Type.Name(), t.Keyword, t.Text) +} + +type LineSpan struct { + Column int + Text string +} + +func (l *LineSpan) String() string { + return fmt.Sprintf("%d:%s", l.Column, l.Text) +} + +type parser struct { + builder Builder + stopAtFirstError bool +} + +func NewParser(b Builder) Parser { + return &parser{ + builder: b, + } +} + +func (p *parser) StopAtFirstError(b bool) { + p.stopAtFirstError = b +} + +func NewScanner(r io.Reader) Scanner { + return &scanner{ + s: bufio.NewScanner(r), + line: 0, + } +} + +type scanner struct { + s *bufio.Scanner + line int +} + +func (t *scanner) Scan() (line *Line, atEof bool, err error) { + scanning := t.s.Scan() + if !scanning { + err = t.s.Err() + if err == nil { + atEof = true + } + } + if err == nil { + t.line += 1 + str := t.s.Text() + line = &Line{str, t.line, strings.TrimLeft(str, " \t"), atEof} + } + return +} + +type Line struct { + LineText string + LineNumber int + TrimmedLineText string + AtEof bool +} + +func (g *Line) Indent() int { + return len(g.LineText) - len(g.TrimmedLineText) +} + +func (g *Line) IsEmpty() bool { + return len(g.TrimmedLineText) == 0 +} + +func (g *Line) IsEof() bool { + return g.AtEof +} + +func (g *Line) StartsWith(prefix string) bool { + return strings.HasPrefix(g.TrimmedLineText, prefix) +} + +func ParseFeature(in io.Reader) (feature *Feature, err error) { + + builder := NewAstBuilder() + parser := NewParser(builder) + parser.StopAtFirstError(false) + matcher := NewMatcher(GherkinDialectsBuildin()) + + scanner := NewScanner(in) + + err = parser.Parse(scanner, matcher) + + return builder.GetFeature(), err +} diff --git a/gherkin/matcher.go b/gherkin/matcher.go new file mode 100644 index 0000000..d8c7efc --- /dev/null +++ b/gherkin/matcher.go @@ -0,0 +1,270 @@ +package gherkin + +import ( + "regexp" + "strings" + "unicode/utf8" +) + +const ( + DEFAULT_DIALECT = "en" + COMMENT_PREFIX = "#" + TAG_PREFIX = "@" + TITLE_KEYWORD_SEPARATOR = ":" + TABLE_CELL_SEPARATOR = '|' + ESCAPE_CHAR = '\\' + ESCAPED_NEWLINE = 'n' + DOCSTRING_SEPARATOR = "\"\"\"" + DOCSTRING_ALTERNATIVE_SEPARATOR = "```" +) + +type matcher struct { + gdp GherkinDialectProvider + default_lang string + lang string + dialect *GherkinDialect + activeDocStringSeparator string + indentToRemove int + languagePattern *regexp.Regexp +} + +func NewMatcher(gdp GherkinDialectProvider) Matcher { + return &matcher{ + gdp: gdp, + default_lang: DEFAULT_DIALECT, + lang: DEFAULT_DIALECT, + dialect: gdp.GetDialect(DEFAULT_DIALECT), + languagePattern: regexp.MustCompile("^\\s*#\\s*language\\s*:\\s*([a-zA-Z\\-_]+)\\s*$"), + } +} + +func NewLanguageMatcher(gdp GherkinDialectProvider, language string) Matcher { + return &matcher{ + gdp: gdp, + default_lang: language, + lang: language, + dialect: gdp.GetDialect(language), + languagePattern: regexp.MustCompile("^\\s*#\\s*language\\s*:\\s*([a-zA-Z\\-_]+)\\s*$"), + } +} + +func (m *matcher) Reset() { + m.indentToRemove = 0 + m.activeDocStringSeparator = "" + if m.lang != "en" { + m.dialect = m.gdp.GetDialect(m.default_lang) + m.lang = "en" + } +} + +func (m *matcher) newTokenAtLocation(line, index int) (token *Token) { + column := index + 1 + token = new(Token) + token.GherkinDialect = m.lang + token.Location = &Location{line, column} + return +} + +func (m *matcher) MatchEOF(line *Line) (ok bool, token *Token, err error) { + if line.IsEof() { + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_EOF + } + return +} + +func (m *matcher) MatchEmpty(line *Line) (ok bool, token *Token, err error) { + if line.IsEmpty() { + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_Empty + } + return +} + +func (m *matcher) MatchComment(line *Line) (ok bool, token *Token, err error) { + if line.StartsWith(COMMENT_PREFIX) { + token, ok = m.newTokenAtLocation(line.LineNumber, 0), true + token.Type = TokenType_Comment + token.Text = line.LineText + } + return +} + +func (m *matcher) MatchTagLine(line *Line) (ok bool, token *Token, err error) { + if line.StartsWith(TAG_PREFIX) { + var tags []*LineSpan + var column = line.Indent() + splits := strings.Split(line.TrimmedLineText, TAG_PREFIX) + for i := range splits { + txt := strings.Trim(splits[i], " ") + if txt != "" { + tags = append(tags, &LineSpan{column, TAG_PREFIX + txt}) + } + column = column + len(splits[i]) + 1 + } + + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_TagLine + token.Items = tags + } + return +} + +func (m *matcher) matchTitleLine(line *Line, tokenType TokenType, keywords []string) (ok bool, token *Token, err error) { + for i := range keywords { + keyword := keywords[i] + if line.StartsWith(keyword + TITLE_KEYWORD_SEPARATOR) { + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = tokenType + token.Keyword = keyword + token.Text = strings.Trim(line.TrimmedLineText[len(keyword)+1:], " ") + return + } + } + return +} + +func (m *matcher) MatchFeatureLine(line *Line) (ok bool, token *Token, err error) { + return m.matchTitleLine(line, TokenType_FeatureLine, m.dialect.FeatureKeywords()) +} +func (m *matcher) MatchBackgroundLine(line *Line) (ok bool, token *Token, err error) { + return m.matchTitleLine(line, TokenType_BackgroundLine, m.dialect.BackgroundKeywords()) +} +func (m *matcher) MatchScenarioLine(line *Line) (ok bool, token *Token, err error) { + return m.matchTitleLine(line, TokenType_ScenarioLine, m.dialect.ScenarioKeywords()) +} +func (m *matcher) MatchScenarioOutlineLine(line *Line) (ok bool, token *Token, err error) { + return m.matchTitleLine(line, TokenType_ScenarioOutlineLine, m.dialect.ScenarioOutlineKeywords()) +} +func (m *matcher) MatchExamplesLine(line *Line) (ok bool, token *Token, err error) { + return m.matchTitleLine(line, TokenType_ExamplesLine, m.dialect.ExamplesKeywords()) +} +func (m *matcher) MatchStepLine(line *Line) (ok bool, token *Token, err error) { + keywords := m.dialect.StepKeywords() + for i := range keywords { + keyword := keywords[i] + if line.StartsWith(keyword) { + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_StepLine + token.Keyword = keyword + token.Text = strings.Trim(line.TrimmedLineText[len(keyword):], " ") + return + } + } + return +} + +func (m *matcher) MatchDocStringSeparator(line *Line) (ok bool, token *Token, err error) { + if m.activeDocStringSeparator != "" { + if line.StartsWith(m.activeDocStringSeparator) { + // close + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_DocStringSeparator + + m.indentToRemove = 0 + m.activeDocStringSeparator = "" + } + return + } + if line.StartsWith(DOCSTRING_SEPARATOR) { + m.activeDocStringSeparator = DOCSTRING_SEPARATOR + } else if line.StartsWith(DOCSTRING_ALTERNATIVE_SEPARATOR) { + m.activeDocStringSeparator = DOCSTRING_ALTERNATIVE_SEPARATOR + } + if m.activeDocStringSeparator != "" { + // open + contentType := line.TrimmedLineText[len(m.activeDocStringSeparator):] + m.indentToRemove = line.Indent() + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_DocStringSeparator + token.Text = contentType + } + return +} + +func (m *matcher) MatchTableRow(line *Line) (ok bool, token *Token, err error) { + var firstChar, firstPos = utf8.DecodeRuneInString(line.TrimmedLineText) + if firstChar == TABLE_CELL_SEPARATOR { + var cells []*LineSpan + var cell []rune + var startCol = line.Indent() + 2 // column where the current cell started + // start after the first separator, it's not included in the cell + for i, w, col := firstPos, 0, startCol; i < len(line.TrimmedLineText); i += w { + var char rune + char, w = utf8.DecodeRuneInString(line.TrimmedLineText[i:]) + if char == TABLE_CELL_SEPARATOR { + // append current cell + txt := string(cell) + txtTrimmed := strings.TrimLeft(txt, " ") + ind := len(txt) - len(txtTrimmed) + cells = append(cells, &LineSpan{startCol + ind, strings.TrimRight(txtTrimmed, " ")}) + // start building next + cell = make([]rune, 0) + startCol = col + 1 + } else if char == ESCAPE_CHAR { + // skip this character but count the column + i += w + col++ + char, w = utf8.DecodeRuneInString(line.TrimmedLineText[i:]) + if char == ESCAPED_NEWLINE { + cell = append(cell, '\n') + } else { + if char != TABLE_CELL_SEPARATOR && char != ESCAPE_CHAR { + cell = append(cell, ESCAPE_CHAR) + } + cell = append(cell, char) + } + } else { + cell = append(cell, char) + } + col++ + } + + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_TableRow + token.Items = cells + } + return +} + +func (m *matcher) MatchLanguage(line *Line) (ok bool, token *Token, err error) { + matches := m.languagePattern.FindStringSubmatch(line.TrimmedLineText) + if len(matches) > 0 { + lang := matches[1] + token, ok = m.newTokenAtLocation(line.LineNumber, line.Indent()), true + token.Type = TokenType_Language + token.Text = lang + + dialect := m.gdp.GetDialect(lang) + if dialect == nil { + err = &parseError{"Language not supported: " + lang, token.Location} + } else { + m.lang = lang + m.dialect = dialect + } + } + return +} + +func (m *matcher) MatchOther(line *Line) (ok bool, token *Token, err error) { + token, ok = m.newTokenAtLocation(line.LineNumber, 0), true + token.Type = TokenType_Other + + element := line.LineText + txt := strings.TrimLeft(element, " ") + + if len(element)-len(txt) > m.indentToRemove { + token.Text = m.unescapeDocString(element[m.indentToRemove:]) + } else { + token.Text = m.unescapeDocString(txt) + } + return +} + +func (m *matcher) unescapeDocString(text string) string { + if m.activeDocStringSeparator != "" { + return strings.Replace(text, "\\\"\\\"\\\"", "\"\"\"", -1) + } else { + return text + } +} diff --git a/gherkin/parser.go b/gherkin/parser.go new file mode 100644 index 0000000..0e26200 --- /dev/null +++ b/gherkin/parser.go @@ -0,0 +1,2270 @@ +// +// This file is generated. Do not edit! Edit gherkin-golang.razor instead. + +// +package gherkin + +import ( + "fmt" + "strings" +) + +type TokenType int + +const ( + TokenType_None TokenType = iota + TokenType_EOF + TokenType_Empty + TokenType_Comment + TokenType_TagLine + TokenType_FeatureLine + TokenType_BackgroundLine + TokenType_ScenarioLine + TokenType_ScenarioOutlineLine + TokenType_ExamplesLine + TokenType_StepLine + TokenType_DocStringSeparator + TokenType_TableRow + TokenType_Language + TokenType_Other +) + +func tokenTypeForRule(rt RuleType) TokenType { + return TokenType_None +} + +func (t TokenType) Name() string { + switch t { + case TokenType_EOF: + return "EOF" + case TokenType_Empty: + return "Empty" + case TokenType_Comment: + return "Comment" + case TokenType_TagLine: + return "TagLine" + case TokenType_FeatureLine: + return "FeatureLine" + case TokenType_BackgroundLine: + return "BackgroundLine" + case TokenType_ScenarioLine: + return "ScenarioLine" + case TokenType_ScenarioOutlineLine: + return "ScenarioOutlineLine" + case TokenType_ExamplesLine: + return "ExamplesLine" + case TokenType_StepLine: + return "StepLine" + case TokenType_DocStringSeparator: + return "DocStringSeparator" + case TokenType_TableRow: + return "TableRow" + case TokenType_Language: + return "Language" + case TokenType_Other: + return "Other" + } + return "" +} + +func (t TokenType) RuleType() RuleType { + switch t { + case TokenType_EOF: + return RuleType__EOF + case TokenType_Empty: + return RuleType__Empty + case TokenType_Comment: + return RuleType__Comment + case TokenType_TagLine: + return RuleType__TagLine + case TokenType_FeatureLine: + return RuleType__FeatureLine + case TokenType_BackgroundLine: + return RuleType__BackgroundLine + case TokenType_ScenarioLine: + return RuleType__ScenarioLine + case TokenType_ScenarioOutlineLine: + return RuleType__ScenarioOutlineLine + case TokenType_ExamplesLine: + return RuleType__ExamplesLine + case TokenType_StepLine: + return RuleType__StepLine + case TokenType_DocStringSeparator: + return RuleType__DocStringSeparator + case TokenType_TableRow: + return RuleType__TableRow + case TokenType_Language: + return RuleType__Language + case TokenType_Other: + return RuleType__Other + } + return RuleType_None +} + +type RuleType int + +const ( + RuleType_None RuleType = iota + + RuleType__EOF + RuleType__Empty + RuleType__Comment + RuleType__TagLine + RuleType__FeatureLine + RuleType__BackgroundLine + RuleType__ScenarioLine + RuleType__ScenarioOutlineLine + RuleType__ExamplesLine + RuleType__StepLine + RuleType__DocStringSeparator + RuleType__TableRow + RuleType__Language + RuleType__Other + RuleType_Feature + RuleType_Feature_Header + RuleType_Background + RuleType_Scenario_Definition + RuleType_Scenario + RuleType_ScenarioOutline + RuleType_Examples_Definition + RuleType_Examples + RuleType_Scenario_Step + RuleType_ScenarioOutline_Step + RuleType_Step + RuleType_Step_Arg + RuleType_DataTable + RuleType_DocString + RuleType_Tags + RuleType_Feature_Description + RuleType_Background_Description + RuleType_Scenario_Description + RuleType_ScenarioOutline_Description + RuleType_Examples_Description + RuleType_Description_Helper + RuleType_Description +) + +func (t RuleType) IsEOF() bool { + return t == RuleType__EOF +} +func (t RuleType) Name() string { + switch t { + case RuleType__EOF: + return "#EOF" + case RuleType__Empty: + return "#Empty" + case RuleType__Comment: + return "#Comment" + case RuleType__TagLine: + return "#TagLine" + case RuleType__FeatureLine: + return "#FeatureLine" + case RuleType__BackgroundLine: + return "#BackgroundLine" + case RuleType__ScenarioLine: + return "#ScenarioLine" + case RuleType__ScenarioOutlineLine: + return "#ScenarioOutlineLine" + case RuleType__ExamplesLine: + return "#ExamplesLine" + case RuleType__StepLine: + return "#StepLine" + case RuleType__DocStringSeparator: + return "#DocStringSeparator" + case RuleType__TableRow: + return "#TableRow" + case RuleType__Language: + return "#Language" + case RuleType__Other: + return "#Other" + case RuleType_Feature: + return "Feature" + case RuleType_Feature_Header: + return "Feature_Header" + case RuleType_Background: + return "Background" + case RuleType_Scenario_Definition: + return "Scenario_Definition" + case RuleType_Scenario: + return "Scenario" + case RuleType_ScenarioOutline: + return "ScenarioOutline" + case RuleType_Examples_Definition: + return "Examples_Definition" + case RuleType_Examples: + return "Examples" + case RuleType_Scenario_Step: + return "Scenario_Step" + case RuleType_ScenarioOutline_Step: + return "ScenarioOutline_Step" + case RuleType_Step: + return "Step" + case RuleType_Step_Arg: + return "Step_Arg" + case RuleType_DataTable: + return "DataTable" + case RuleType_DocString: + return "DocString" + case RuleType_Tags: + return "Tags" + case RuleType_Feature_Description: + return "Feature_Description" + case RuleType_Background_Description: + return "Background_Description" + case RuleType_Scenario_Description: + return "Scenario_Description" + case RuleType_ScenarioOutline_Description: + return "ScenarioOutline_Description" + case RuleType_Examples_Description: + return "Examples_Description" + case RuleType_Description_Helper: + return "Description_Helper" + case RuleType_Description: + return "Description" + } + return "" +} + +type parseError struct { + msg string + loc *Location +} + +func (a *parseError) Error() string { + return fmt.Sprintf("(%d:%d): %s", a.loc.Line, a.loc.Column, a.msg) +} + +type parseErrors []error + +func (pe parseErrors) Error() string { + var ret = []string{"Parser errors:"} + for i := range pe { + ret = append(ret, pe[i].Error()) + } + return strings.Join(ret, "\n") +} + +func (p *parser) Parse(s Scanner, m Matcher) (err error) { + p.builder.Reset() + m.Reset() + ctxt := &parseContext{p, s, p.builder, m, nil, nil} + var state int + ctxt.startRule(RuleType_Feature) + for { + gl, eof, err := ctxt.scan() + if err != nil { + ctxt.addError(err) + if p.stopAtFirstError { + break + } + } + state, err = ctxt.match(state, gl) + if err != nil { + ctxt.addError(err) + if p.stopAtFirstError { + break + } + } + if eof { + // done! \o/ + break + } + } + ctxt.endRule(RuleType_Feature) + if len(ctxt.errors) > 0 { + return ctxt.errors + } + return +} + +type parseContext struct { + p *parser + s Scanner + b Builder + m Matcher + queue []*scanResult + errors parseErrors +} + +func (ctxt *parseContext) addError(e error) { + ctxt.errors = append(ctxt.errors, e) + // if (p.errors.length > 10) + // throw Errors.CompositeParserException.create(p.errors); +} + +type scanResult struct { + line *Line + atEof bool + err error +} + +func (ctxt *parseContext) scan() (*Line, bool, error) { + l := len(ctxt.queue) + if l > 0 { + x := ctxt.queue[0] + ctxt.queue = ctxt.queue[1:] + return x.line, x.atEof, x.err + } + return ctxt.s.Scan() +} + +func (ctxt *parseContext) startRule(r RuleType) (bool, error) { + ok, err := ctxt.b.StartRule(r) + if err != nil { + ctxt.addError(err) + } + return ok, err +} + +func (ctxt *parseContext) endRule(r RuleType) (bool, error) { + ok, err := ctxt.b.EndRule(r) + if err != nil { + ctxt.addError(err) + } + return ok, err +} + +func (ctxt *parseContext) build(t *Token) (bool, error) { + ok, err := ctxt.b.Build(t) + if err != nil { + ctxt.addError(err) + } + return ok, err +} + +func (ctxt *parseContext) match(state int, line *Line) (newState int, err error) { + switch state { + case 0: + return ctxt.matchAt_0(line) + case 1: + return ctxt.matchAt_1(line) + case 2: + return ctxt.matchAt_2(line) + case 3: + return ctxt.matchAt_3(line) + case 4: + return ctxt.matchAt_4(line) + case 5: + return ctxt.matchAt_5(line) + case 6: + return ctxt.matchAt_6(line) + case 7: + return ctxt.matchAt_7(line) + case 8: + return ctxt.matchAt_8(line) + case 9: + return ctxt.matchAt_9(line) + case 10: + return ctxt.matchAt_10(line) + case 11: + return ctxt.matchAt_11(line) + case 12: + return ctxt.matchAt_12(line) + case 13: + return ctxt.matchAt_13(line) + case 14: + return ctxt.matchAt_14(line) + case 15: + return ctxt.matchAt_15(line) + case 16: + return ctxt.matchAt_16(line) + case 17: + return ctxt.matchAt_17(line) + case 18: + return ctxt.matchAt_18(line) + case 19: + return ctxt.matchAt_19(line) + case 20: + return ctxt.matchAt_20(line) + case 21: + return ctxt.matchAt_21(line) + case 22: + return ctxt.matchAt_22(line) + case 23: + return ctxt.matchAt_23(line) + case 24: + return ctxt.matchAt_24(line) + case 25: + return ctxt.matchAt_25(line) + case 26: + return ctxt.matchAt_26(line) + case 27: + return ctxt.matchAt_27(line) + case 29: + return ctxt.matchAt_29(line) + case 30: + return ctxt.matchAt_30(line) + case 31: + return ctxt.matchAt_31(line) + case 32: + return ctxt.matchAt_32(line) + case 33: + return ctxt.matchAt_33(line) + case 34: + return ctxt.matchAt_34(line) + default: + return state, fmt.Errorf("Unknown state: %+v", state) + } +} + +// Start +func (ctxt *parseContext) matchAt_0(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_Language(line); ok { + ctxt.startRule(RuleType_Feature_Header) + ctxt.build(token) + return 1, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.startRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 2, err + } + if ok, token, err := ctxt.match_FeatureLine(line); ok { + ctxt.startRule(RuleType_Feature_Header) + ctxt.build(token) + return 3, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 0, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 0, err + } + + // var stateComment = "State: 0 - Start" + var expectedTokens = []string{"#Language", "#TagLine", "#FeatureLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 0, err +} + +// Feature:0>Feature_Header:0>#Language:0 +func (ctxt *parseContext) matchAt_1(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 2, err + } + if ok, token, err := ctxt.match_FeatureLine(line); ok { + ctxt.build(token) + return 3, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 1, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 1, err + } + + // var stateComment = "State: 1 - Feature:0>Feature_Header:0>#Language:0" + var expectedTokens = []string{"#TagLine", "#FeatureLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 1, err +} + +// Feature:0>Feature_Header:1>Tags:0>#TagLine:0 +func (ctxt *parseContext) matchAt_2(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.build(token) + return 2, err + } + if ok, token, err := ctxt.match_FeatureLine(line); ok { + ctxt.endRule(RuleType_Tags) + ctxt.build(token) + return 3, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 2, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 2, err + } + + // var stateComment = "State: 2 - Feature:0>Feature_Header:1>Tags:0>#TagLine:0" + var expectedTokens = []string{"#TagLine", "#FeatureLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 2, err +} + +// Feature:0>Feature_Header:2>#FeatureLine:0 +func (ctxt *parseContext) matchAt_3(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 3, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 5, err + } + if ok, token, err := ctxt.match_BackgroundLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Background) + ctxt.build(token) + return 6, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.startRule(RuleType_Description) + ctxt.build(token) + return 4, err + } + + // var stateComment = "State: 3 - Feature:0>Feature_Header:2>#FeatureLine:0" + var expectedTokens = []string{"#EOF", "#Empty", "#Comment", "#BackgroundLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 3, err +} + +// Feature:0>Feature_Header:3>Feature_Description:0>Description_Helper:1>Description:0>#Other:0 +func (ctxt *parseContext) matchAt_4(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Feature_Header) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.build(token) + return 5, err + } + if ok, token, err := ctxt.match_BackgroundLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Background) + ctxt.build(token) + return 6, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 4, err + } + + // var stateComment = "State: 4 - Feature:0>Feature_Header:3>Feature_Description:0>Description_Helper:1>Description:0>#Other:0" + var expectedTokens = []string{"#EOF", "#Comment", "#BackgroundLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 4, err +} + +// Feature:0>Feature_Header:3>Feature_Description:0>Description_Helper:2>#Comment:0 +func (ctxt *parseContext) matchAt_5(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 5, err + } + if ok, token, err := ctxt.match_BackgroundLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Background) + ctxt.build(token) + return 6, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Feature_Header) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 5, err + } + + // var stateComment = "State: 5 - Feature:0>Feature_Header:3>Feature_Description:0>Description_Helper:2>#Comment:0" + var expectedTokens = []string{"#EOF", "#Comment", "#BackgroundLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 5, err +} + +// Feature:1>Background:0>#BackgroundLine:0 +func (ctxt *parseContext) matchAt_6(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 6, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 8, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 9, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.startRule(RuleType_Description) + ctxt.build(token) + return 7, err + } + + // var stateComment = "State: 6 - Feature:1>Background:0>#BackgroundLine:0" + var expectedTokens = []string{"#EOF", "#Empty", "#Comment", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 6, err +} + +// Feature:1>Background:1>Background_Description:0>Description_Helper:1>Description:0>#Other:0 +func (ctxt *parseContext) matchAt_7(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Background) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.build(token) + return 8, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 9, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 7, err + } + + // var stateComment = "State: 7 - Feature:1>Background:1>Background_Description:0>Description_Helper:1>Description:0>#Other:0" + var expectedTokens = []string{"#EOF", "#Comment", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 7, err +} + +// Feature:1>Background:1>Background_Description:0>Description_Helper:2>#Comment:0 +func (ctxt *parseContext) matchAt_8(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 8, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 9, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 8, err + } + + // var stateComment = "State: 8 - Feature:1>Background:1>Background_Description:0>Description_Helper:2>#Comment:0" + var expectedTokens = []string{"#EOF", "#Comment", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 8, err +} + +// Feature:1>Background:2>Scenario_Step:0>Step:0>#StepLine:0 +func (ctxt *parseContext) matchAt_9(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.startRule(RuleType_DataTable) + ctxt.build(token) + return 10, err + } + if ok, token, err := ctxt.match_DocStringSeparator(line); ok { + ctxt.startRule(RuleType_DocString) + ctxt.build(token) + return 33, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 9, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 9, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 9, err + } + + // var stateComment = "State: 9 - Feature:1>Background:2>Scenario_Step:0>Step:0>#StepLine:0" + var expectedTokens = []string{"#EOF", "#TableRow", "#DocStringSeparator", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 9, err +} + +// Feature:1>Background:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:0>DataTable:0>#TableRow:0 +func (ctxt *parseContext) matchAt_10(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.build(token) + return 10, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 9, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 10, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 10, err + } + + // var stateComment = "State: 10 - Feature:1>Background:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:0>DataTable:0>#TableRow:0" + var expectedTokens = []string{"#EOF", "#TableRow", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 10, err +} + +// Feature:2>Scenario_Definition:0>Tags:0>#TagLine:0 +func (ctxt *parseContext) matchAt_11(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Tags) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Tags) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 11, err + } + + // var stateComment = "State: 11 - Feature:2>Scenario_Definition:0>Tags:0>#TagLine:0" + var expectedTokens = []string{"#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 11, err +} + +// Feature:2>Scenario_Definition:1>__alt0:0>Scenario:0>#ScenarioLine:0 +func (ctxt *parseContext) matchAt_12(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 14, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 15, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.startRule(RuleType_Description) + ctxt.build(token) + return 13, err + } + + // var stateComment = "State: 12 - Feature:2>Scenario_Definition:1>__alt0:0>Scenario:0>#ScenarioLine:0" + var expectedTokens = []string{"#EOF", "#Empty", "#Comment", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 12, err +} + +// Feature:2>Scenario_Definition:1>__alt0:0>Scenario:1>Scenario_Description:0>Description_Helper:1>Description:0>#Other:0 +func (ctxt *parseContext) matchAt_13(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.build(token) + return 14, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 15, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 13, err + } + + // var stateComment = "State: 13 - Feature:2>Scenario_Definition:1>__alt0:0>Scenario:1>Scenario_Description:0>Description_Helper:1>Description:0>#Other:0" + var expectedTokens = []string{"#EOF", "#Comment", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 13, err +} + +// Feature:2>Scenario_Definition:1>__alt0:0>Scenario:1>Scenario_Description:0>Description_Helper:2>#Comment:0 +func (ctxt *parseContext) matchAt_14(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 14, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 15, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 14, err + } + + // var stateComment = "State: 14 - Feature:2>Scenario_Definition:1>__alt0:0>Scenario:1>Scenario_Description:0>Description_Helper:2>#Comment:0" + var expectedTokens = []string{"#EOF", "#Comment", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 14, err +} + +// Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:0>#StepLine:0 +func (ctxt *parseContext) matchAt_15(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.startRule(RuleType_DataTable) + ctxt.build(token) + return 16, err + } + if ok, token, err := ctxt.match_DocStringSeparator(line); ok { + ctxt.startRule(RuleType_DocString) + ctxt.build(token) + return 31, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 15, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 15, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 15, err + } + + // var stateComment = "State: 15 - Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:0>#StepLine:0" + var expectedTokens = []string{"#EOF", "#TableRow", "#DocStringSeparator", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 15, err +} + +// Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:0>DataTable:0>#TableRow:0 +func (ctxt *parseContext) matchAt_16(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.build(token) + return 16, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 15, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 16, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 16, err + } + + // var stateComment = "State: 16 - Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:0>DataTable:0>#TableRow:0" + var expectedTokens = []string{"#EOF", "#TableRow", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 16, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:0>#ScenarioOutlineLine:0 +func (ctxt *parseContext) matchAt_17(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 19, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 20, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.startRule(RuleType_Description) + ctxt.build(token) + return 18, err + } + + // var stateComment = "State: 17 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:0>#ScenarioOutlineLine:0" + var expectedTokens = []string{"#Empty", "#Comment", "#StepLine", "#TagLine", "#ExamplesLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 17, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:1>ScenarioOutline_Description:0>Description_Helper:1>Description:0>#Other:0 +func (ctxt *parseContext) matchAt_18(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.build(token) + return 19, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 20, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 18, err + } + + // var stateComment = "State: 18 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:1>ScenarioOutline_Description:0>Description_Helper:1>Description:0>#Other:0" + var expectedTokens = []string{"#Comment", "#StepLine", "#TagLine", "#ExamplesLine", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 18, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:1>ScenarioOutline_Description:0>Description_Helper:2>#Comment:0 +func (ctxt *parseContext) matchAt_19(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 19, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 20, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 19, err + } + + // var stateComment = "State: 19 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:1>ScenarioOutline_Description:0>Description_Helper:2>#Comment:0" + var expectedTokens = []string{"#Comment", "#StepLine", "#TagLine", "#ExamplesLine", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 19, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:0>#StepLine:0 +func (ctxt *parseContext) matchAt_20(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.startRule(RuleType_DataTable) + ctxt.build(token) + return 21, err + } + if ok, token, err := ctxt.match_DocStringSeparator(line); ok { + ctxt.startRule(RuleType_DocString) + ctxt.build(token) + return 29, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 20, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 20, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 20, err + } + + // var stateComment = "State: 20 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:0>#StepLine:0" + var expectedTokens = []string{"#TableRow", "#DocStringSeparator", "#StepLine", "#TagLine", "#ExamplesLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 20, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:1>Step_Arg:0>__alt1:0>DataTable:0>#TableRow:0 +func (ctxt *parseContext) matchAt_21(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.build(token) + return 21, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 20, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.endRule(RuleType_DataTable) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 21, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 21, err + } + + // var stateComment = "State: 21 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:1>Step_Arg:0>__alt1:0>DataTable:0>#TableRow:0" + var expectedTokens = []string{"#TableRow", "#StepLine", "#TagLine", "#ExamplesLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 21, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:0>Tags:0>#TagLine:0 +func (ctxt *parseContext) matchAt_22(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.endRule(RuleType_Tags) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 22, err + } + + // var stateComment = "State: 22 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:0>Tags:0>#TagLine:0" + var expectedTokens = []string{"#TagLine", "#ExamplesLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 22, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:0>#ExamplesLine:0 +func (ctxt *parseContext) matchAt_23(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 25, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.build(token) + return 26, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.startRule(RuleType_Description) + ctxt.build(token) + return 24, err + } + + // var stateComment = "State: 23 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:0>#ExamplesLine:0" + var expectedTokens = []string{"#Empty", "#Comment", "#TableRow", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 23, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:1>Examples_Description:0>Description_Helper:1>Description:0>#Other:0 +func (ctxt *parseContext) matchAt_24(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.build(token) + return 25, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.endRule(RuleType_Description) + ctxt.build(token) + return 26, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 24, err + } + + // var stateComment = "State: 24 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:1>Examples_Description:0>Description_Helper:1>Description:0>#Other:0" + var expectedTokens = []string{"#Comment", "#TableRow", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 24, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:1>Examples_Description:0>Description_Helper:2>#Comment:0 +func (ctxt *parseContext) matchAt_25(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 25, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.build(token) + return 26, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 25, err + } + + // var stateComment = "State: 25 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:1>Examples_Description:0>Description_Helper:2>#Comment:0" + var expectedTokens = []string{"#Comment", "#TableRow", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 25, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:2>#TableRow:0 +func (ctxt *parseContext) matchAt_26(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.build(token) + return 27, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 26, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 26, err + } + + // var stateComment = "State: 26 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:2>#TableRow:0" + var expectedTokens = []string{"#TableRow", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 26, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:3>#TableRow:0 +func (ctxt *parseContext) matchAt_27(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_Examples) + ctxt.endRule(RuleType_Examples_Definition) + ctxt.endRule(RuleType_ScenarioOutline) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_TableRow(line); ok { + ctxt.build(token) + return 27, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + if ctxt.lookahead_0(line) { + ctxt.endRule(RuleType_Examples) + ctxt.endRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 22, err + } + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_Examples) + ctxt.endRule(RuleType_Examples_Definition) + ctxt.endRule(RuleType_ScenarioOutline) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.endRule(RuleType_Examples) + ctxt.endRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_Examples) + ctxt.endRule(RuleType_Examples_Definition) + ctxt.endRule(RuleType_ScenarioOutline) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_Examples) + ctxt.endRule(RuleType_Examples_Definition) + ctxt.endRule(RuleType_ScenarioOutline) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 27, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 27, err + } + + // var stateComment = "State: 27 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:3>Examples_Definition:1>Examples:3>#TableRow:0" + var expectedTokens = []string{"#EOF", "#TableRow", "#TagLine", "#ExamplesLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 27, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:0>#DocStringSeparator:0 +func (ctxt *parseContext) matchAt_29(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_DocStringSeparator(line); ok { + ctxt.build(token) + return 30, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 29, err + } + + // var stateComment = "State: 29 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:0>#DocStringSeparator:0" + var expectedTokens = []string{"#DocStringSeparator", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 29, err +} + +// Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:2>#DocStringSeparator:0 +func (ctxt *parseContext) matchAt_30(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 20, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 22, err + } + if ok, token, err := ctxt.match_ExamplesLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Examples_Definition) + ctxt.startRule(RuleType_Examples) + ctxt.build(token) + return 23, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 30, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 30, err + } + + // var stateComment = "State: 30 - Feature:2>Scenario_Definition:1>__alt0:1>ScenarioOutline:2>ScenarioOutline_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:2>#DocStringSeparator:0" + var expectedTokens = []string{"#StepLine", "#TagLine", "#ExamplesLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 30, err +} + +// Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:0>#DocStringSeparator:0 +func (ctxt *parseContext) matchAt_31(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_DocStringSeparator(line); ok { + ctxt.build(token) + return 32, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 31, err + } + + // var stateComment = "State: 31 - Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:0>#DocStringSeparator:0" + var expectedTokens = []string{"#DocStringSeparator", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 31, err +} + +// Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:2>#DocStringSeparator:0 +func (ctxt *parseContext) matchAt_32(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 15, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Scenario) + ctxt.endRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 32, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 32, err + } + + // var stateComment = "State: 32 - Feature:2>Scenario_Definition:1>__alt0:0>Scenario:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:2>#DocStringSeparator:0" + var expectedTokens = []string{"#EOF", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 32, err +} + +// Feature:1>Background:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:0>#DocStringSeparator:0 +func (ctxt *parseContext) matchAt_33(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_DocStringSeparator(line); ok { + ctxt.build(token) + return 34, err + } + if ok, token, err := ctxt.match_Other(line); ok { + ctxt.build(token) + return 33, err + } + + // var stateComment = "State: 33 - Feature:1>Background:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:0>#DocStringSeparator:0" + var expectedTokens = []string{"#DocStringSeparator", "#Other"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 33, err +} + +// Feature:1>Background:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:2>#DocStringSeparator:0 +func (ctxt *parseContext) matchAt_34(line *Line) (newState int, err error) { + if ok, token, err := ctxt.match_EOF(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.build(token) + return 28, err + } + if ok, token, err := ctxt.match_StepLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.startRule(RuleType_Step) + ctxt.build(token) + return 9, err + } + if ok, token, err := ctxt.match_TagLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Tags) + ctxt.build(token) + return 11, err + } + if ok, token, err := ctxt.match_ScenarioLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_Scenario) + ctxt.build(token) + return 12, err + } + if ok, token, err := ctxt.match_ScenarioOutlineLine(line); ok { + ctxt.endRule(RuleType_DocString) + ctxt.endRule(RuleType_Step) + ctxt.endRule(RuleType_Background) + ctxt.startRule(RuleType_Scenario_Definition) + ctxt.startRule(RuleType_ScenarioOutline) + ctxt.build(token) + return 17, err + } + if ok, token, err := ctxt.match_Comment(line); ok { + ctxt.build(token) + return 34, err + } + if ok, token, err := ctxt.match_Empty(line); ok { + ctxt.build(token) + return 34, err + } + + // var stateComment = "State: 34 - Feature:1>Background:2>Scenario_Step:0>Step:1>Step_Arg:0>__alt1:1>DocString:2>#DocStringSeparator:0" + var expectedTokens = []string{"#EOF", "#StepLine", "#TagLine", "#ScenarioLine", "#ScenarioOutlineLine", "#Comment", "#Empty"} + if line.IsEof() { + err = fmt.Errorf("(%d:0): unexpected end of file, expected: %s", line.LineNumber, strings.Join(expectedTokens, ", ")) + } else { + err = fmt.Errorf("(%d:%d): expected: %s, got '%s'", line.LineNumber, line.Indent()+1, strings.Join(expectedTokens, ", "), line.LineText) + } + // if (ctxt.p.stopAtFirstError) throw error; + //ctxt.addError(err) + return 34, err +} + +type Matcher interface { + MatchEOF(line *Line) (bool, *Token, error) + MatchEmpty(line *Line) (bool, *Token, error) + MatchComment(line *Line) (bool, *Token, error) + MatchTagLine(line *Line) (bool, *Token, error) + MatchFeatureLine(line *Line) (bool, *Token, error) + MatchBackgroundLine(line *Line) (bool, *Token, error) + MatchScenarioLine(line *Line) (bool, *Token, error) + MatchScenarioOutlineLine(line *Line) (bool, *Token, error) + MatchExamplesLine(line *Line) (bool, *Token, error) + MatchStepLine(line *Line) (bool, *Token, error) + MatchDocStringSeparator(line *Line) (bool, *Token, error) + MatchTableRow(line *Line) (bool, *Token, error) + MatchLanguage(line *Line) (bool, *Token, error) + MatchOther(line *Line) (bool, *Token, error) + Reset() +} + +func (ctxt *parseContext) isMatch_EOF(line *Line) bool { + ok, _, _ := ctxt.match_EOF(line) + return ok +} +func (ctxt *parseContext) match_EOF(line *Line) (bool, *Token, error) { + return ctxt.m.MatchEOF(line) +} + +func (ctxt *parseContext) isMatch_Empty(line *Line) bool { + ok, _, _ := ctxt.match_Empty(line) + return ok +} +func (ctxt *parseContext) match_Empty(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchEmpty(line) +} + +func (ctxt *parseContext) isMatch_Comment(line *Line) bool { + ok, _, _ := ctxt.match_Comment(line) + return ok +} +func (ctxt *parseContext) match_Comment(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchComment(line) +} + +func (ctxt *parseContext) isMatch_TagLine(line *Line) bool { + ok, _, _ := ctxt.match_TagLine(line) + return ok +} +func (ctxt *parseContext) match_TagLine(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchTagLine(line) +} + +func (ctxt *parseContext) isMatch_FeatureLine(line *Line) bool { + ok, _, _ := ctxt.match_FeatureLine(line) + return ok +} +func (ctxt *parseContext) match_FeatureLine(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchFeatureLine(line) +} + +func (ctxt *parseContext) isMatch_BackgroundLine(line *Line) bool { + ok, _, _ := ctxt.match_BackgroundLine(line) + return ok +} +func (ctxt *parseContext) match_BackgroundLine(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchBackgroundLine(line) +} + +func (ctxt *parseContext) isMatch_ScenarioLine(line *Line) bool { + ok, _, _ := ctxt.match_ScenarioLine(line) + return ok +} +func (ctxt *parseContext) match_ScenarioLine(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchScenarioLine(line) +} + +func (ctxt *parseContext) isMatch_ScenarioOutlineLine(line *Line) bool { + ok, _, _ := ctxt.match_ScenarioOutlineLine(line) + return ok +} +func (ctxt *parseContext) match_ScenarioOutlineLine(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchScenarioOutlineLine(line) +} + +func (ctxt *parseContext) isMatch_ExamplesLine(line *Line) bool { + ok, _, _ := ctxt.match_ExamplesLine(line) + return ok +} +func (ctxt *parseContext) match_ExamplesLine(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchExamplesLine(line) +} + +func (ctxt *parseContext) isMatch_StepLine(line *Line) bool { + ok, _, _ := ctxt.match_StepLine(line) + return ok +} +func (ctxt *parseContext) match_StepLine(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchStepLine(line) +} + +func (ctxt *parseContext) isMatch_DocStringSeparator(line *Line) bool { + ok, _, _ := ctxt.match_DocStringSeparator(line) + return ok +} +func (ctxt *parseContext) match_DocStringSeparator(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchDocStringSeparator(line) +} + +func (ctxt *parseContext) isMatch_TableRow(line *Line) bool { + ok, _, _ := ctxt.match_TableRow(line) + return ok +} +func (ctxt *parseContext) match_TableRow(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchTableRow(line) +} + +func (ctxt *parseContext) isMatch_Language(line *Line) bool { + ok, _, _ := ctxt.match_Language(line) + return ok +} +func (ctxt *parseContext) match_Language(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchLanguage(line) +} + +func (ctxt *parseContext) isMatch_Other(line *Line) bool { + ok, _, _ := ctxt.match_Other(line) + return ok +} +func (ctxt *parseContext) match_Other(line *Line) (bool, *Token, error) { + if line.IsEof() { + return false, nil, nil + } + return ctxt.m.MatchOther(line) +} + +func (ctxt *parseContext) lookahead_0(initialLine *Line) bool { + var queue []*scanResult + var match bool + + for { + line, atEof, err := ctxt.scan() + queue = append(queue, &scanResult{line, atEof, err}) + + if false || ctxt.isMatch_ExamplesLine(line) { + match = true + break + } + if !(false || ctxt.isMatch_Empty(line) || ctxt.isMatch_Comment(line) || ctxt.isMatch_TagLine(line)) { + break + } + if atEof { + break + } + } + + ctxt.queue = append(ctxt.queue, queue...) + + return match +} diff --git a/stepdef.go b/stepdef.go index a2ffff9..70bc2b3 100644 --- a/stepdef.go +++ b/stepdef.go @@ -7,7 +7,7 @@ import ( "runtime" "strconv" - "gopkg.in/cucumber/gherkin-go.v3" + "github.com/DATA-DOG/godog/gherkin" ) // StepDef is a registered step definition diff --git a/suite.go b/suite.go index b0b8e72..8aec11e 100644 --- a/suite.go +++ b/suite.go @@ -10,7 +10,7 @@ import ( "strconv" "strings" - "gopkg.in/cucumber/gherkin-go.v3" + "github.com/DATA-DOG/godog/gherkin" ) var errorInterface = reflect.TypeOf((*error)(nil)).Elem() diff --git a/suite_test.go b/suite_test.go index c8fb7d1..b28da9b 100644 --- a/suite_test.go +++ b/suite_test.go @@ -8,7 +8,7 @@ import ( "strings" "testing" - "gopkg.in/cucumber/gherkin-go.v3" + "github.com/DATA-DOG/godog/gherkin" ) func TestMain(m *testing.M) {