func (p *parser) parse(g *grammar) (val interface{}, err error) {
	if len(g.rules) == 0 {
		p.addErr(errNoRule)
		return nil, p.errs.err()
	}
	p.buildRulesTable(g)
	if p.recover {
		defer func() {
			if e := recover(); e != nil {
				if p.debug {
					defer p.out(p.in("panic handler"))
				}
				val = nil
				switch e := e.(type) {
				case error:
					p.addErr(e)
				default:
					p.addErr(fmt.Errorf("%v", e))
				}
				err = p.errs.err()
			}
		}()
	}
	startRule, ok := p.rules[p.entrypoint]
	if !ok {
		p.addErr(errInvalidEntrypoint)
		return nil, p.errs.err()
	}
	p.read()  
	val, ok = p.parseRule(startRule)
	if !ok {
		if len(*p.errs) == 0 {
			maxFailExpectedMap := make(map[string]struct{}, len(p.maxFailExpected))
			for _, v := range p.maxFailExpected {
				maxFailExpectedMap[v] = struct{}{}
			}
			expected := make([]string, 0, len(maxFailExpectedMap))
			eof := false
			if _, ok := maxFailExpectedMap["!."]; ok {
				delete(maxFailExpectedMap, "!.")
				eof = true
			}
			for k := range maxFailExpectedMap {
				expected = append(expected, k)
			}
			sort.Strings(expected)
			if eof {
				expected = append(expected, "EOF")
			}
			p.addErrAt(errors.New("no match found, expected: "+listJoin(expected, ", ", "or")), p.maxFailPos, expected)
		}
		return nil, p.errs.err()
	}
	return val, p.errs.err()
}
{{ if .Nolint }} nolint: gocyclo {{else}} ==template== {{ end }}
package builder
import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"math"
	"os"
	"sort"
	"strconv"
	"strings"
	"sync"
	"unicode"
	"unicode/utf8"
)
var (
	errNoRule = errors.New("grammar has no rule")
	errInvalidEntrypoint = errors.New("invalid entrypoint")
	errInvalidEncoding = errors.New("invalid encoding")
	errMaxExprCnt = errors.New("max number of expresssions parsed")
)
type Option func(*parser) Option
func MaxExpressions(maxExprCnt uint64) Option {
	return func(p *parser) Option {
		oldMaxExprCnt := p.maxExprCnt
		p.maxExprCnt = maxExprCnt
		return MaxExpressions(oldMaxExprCnt)
	}
}
func Entrypoint(ruleName string) Option {
	return func(p *parser) Option {
		oldEntrypoint := p.entrypoint
		p.entrypoint = ruleName
		if ruleName == "" {
			p.entrypoint = g.rules[0].name
		}
		return Entrypoint(oldEntrypoint)
	}
}
func Statistics(stats *Stats, choiceNoMatch string) Option {
	return func(p *parser) Option {
		oldStats := p.Stats
		p.Stats = stats
		oldChoiceNoMatch := p.choiceNoMatch
		p.choiceNoMatch = choiceNoMatch
		if p.Stats.ChoiceAltCnt == nil {
			p.Stats.ChoiceAltCnt = make(map[string]map[string]int)
		}
		return Statistics(oldStats, oldChoiceNoMatch)
	}
}
func Debug(b bool) Option {
	return func(p *parser) Option {
		old := p.debug
		p.debug = b
		return Debug(old)
	}
}
func Memoize(b bool) Option {
	return func(p *parser) Option {
		old := p.memoize
		p.memoize = b
		return Memoize(old)
	}
}
func AllowInvalidUTF8(b bool) Option {
	return func(p *parser) Option {
		old := p.allowInvalidUTF8
		p.allowInvalidUTF8 = b
		return AllowInvalidUTF8(old)
	}
}
func Recover(b bool) Option {
	return func(p *parser) Option {
		old := p.recover
		p.recover = b
		return Recover(old)
	}
}
func GlobalStore(key string, value interface{}) Option {
	return func(p *parser) Option {
		old := p.cur.globalStore[key]
		p.cur.globalStore[key] = value
		return GlobalStore(key, old)
	}
}
func InitState(key string, value interface{}) Option {
	return func(p *parser) Option {
		old := p.cur.state[key]
		p.cur.state[key] = value
		return InitState(key, old)
	}
}
func ParseFile(filename string, opts ...Option) (i interface{}, err error) {  
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer func() {
		if closeErr := f.Close(); closeErr != nil {
			err = closeErr
		}
	}()
	return ParseReader(filename, f, opts...)
}
func ParseReader(filename string, r io.Reader, opts ...Option) (interface{}, error) {  
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}
	return Parse(filename, b, opts...)
}
func Parse(filename string, b []byte, opts ...Option) (interface{}, error) {
	return newParser(filename, b, opts...).parse(g)
}
type position struct {
	line, col, offset int
}
func (p position) String() string {
	return strconv.Itoa(p.line) + ":" + strconv.Itoa(p.col) + " [" + strconv.Itoa(p.offset) + "]"
}
type savepoint struct {
	position
	rn rune
	w  int
}
type current struct {
	pos  position  
	text []byte    
	state storeDict
	globalStore storeDict
}
type storeDict map[string]interface{}
type grammar struct {
	pos   position
	rules []*rule
}
type rule struct {
	pos         position
	name        string
	displayName string
	expr        interface{}
}
type choiceExpr struct {
	pos          position
	alternatives []interface{}
}
type actionExpr struct {
	pos  position
	expr interface{}
	run  func(*parser) (interface{}, error)
}
type recoveryExpr struct {
	pos          position
	expr         interface{}
	recoverExpr  interface{}
	failureLabel []string
}
type seqExpr struct {
	pos   position
	exprs []interface{}
}
type throwExpr struct {
	pos   position
	label string
}
type labeledExpr struct {
	pos   position
	label string
	expr  interface{}
}
type expr struct {
	pos  position
	expr interface{}
}
type andExpr expr         
type notExpr expr         
type zeroOrOneExpr expr   
type zeroOrMoreExpr expr  
type oneOrMoreExpr expr   
type ruleRefExpr struct {
	pos  position
	name string
}
type stateCodeExpr struct {
	pos position
	run func(*parser) error
}
type andCodeExpr struct {
	pos position
	run func(*parser) (bool, error)
}
type notCodeExpr struct {
	pos position
	run func(*parser) (bool, error)
}
type litMatcher struct {
	pos        position
	val        string
	ignoreCase bool
	want       string
}
type charClassMatcher struct {
	pos             position
	val             string
	basicLatinChars [128]bool
	chars           []rune
	ranges          []rune
	classes         []*unicode.RangeTable
	ignoreCase      bool
	inverted        bool
}
type anyMatcher position  
type errList []error
func (e *errList) add(err error) {
	*e = append(*e, err)
}
func (e errList) err() error {
	if len(e) == 0 {
		return nil
	}
	e.dedupe()
	return e
}
func (e *errList) dedupe() {
	var cleaned []error
	set := make(map[string]bool)
	for _, err := range *e {
		if msg := err.Error(); !set[msg] {
			set[msg] = true
			cleaned = append(cleaned, err)
		}
	}
	*e = cleaned
}
func (e errList) Error() string {
	switch len(e) {
	case 0:
		return ""
	case 1:
		return e[0].Error()
	default:
		var buf bytes.Buffer
		for i, err := range e {
			if i > 0 {
				buf.WriteRune('\n')
			}
			buf.WriteString(err.Error())
		}
		return buf.String()
	}
}
type parserError struct {
	Inner    error
	pos      position
	prefix   string
	expected []string
}
func (p *parserError) Error() string {
	return p.prefix + ": " + p.Inner.Error()
}
func newParser(filename string, b []byte, opts ...Option) *parser {
	stats := Stats{
		ChoiceAltCnt: make(map[string]map[string]int),
	}
	p := &parser{
		filename: filename,
		errs:     new(errList),
		data:     b,
		pt:       savepoint{position: position{line: 1}},
		recover:  true,
		cur: current{
			state: make(storeDict),
			globalStore: make(storeDict),
		},
		maxFailPos:      position{col: 1, line: 1},
		maxFailExpected: make([]string, 0, 20),
		Stats:           &stats,
		entrypoint: g.rules[0].name,
	}
	p.setOptions(opts)
	if p.maxExprCnt == 0 {
		p.maxExprCnt = math.MaxUint64
	}
	return p
}
func (p *parser) setOptions(opts []Option) {
	for _, opt := range opts {
		opt(p)
	}
}
type resultTuple struct {
	v   interface{}
	b   bool
	end savepoint
}
const choiceNoMatch = -1
type Stats struct {
	ExprCnt uint64
	ChoiceAltCnt map[string]map[string]int
}
type parser struct {
	filename string
	pt       savepoint
	cur      current
	data []byte
	errs *errList
	depth   int
	recover bool
	debug bool
	memoize bool
	memo map[int]map[interface{}]resultTuple
	rules map[string]*rule
	vstack []map[string]interface{}
	rstack []*rule
	maxFailPos            position
	maxFailExpected       []string
	maxFailInvertExpected bool
	maxExprCnt uint64
	entrypoint string
	allowInvalidUTF8 bool
	*Stats
	choiceNoMatch string
	recoveryStack []map[string]interface{}
}
func (p *parser) pushV() {
	if cap(p.vstack) == len(p.vstack) {
		p.vstack = append(p.vstack, nil)
	} else {
		p.vstack = p.vstack[:len(p.vstack)+1]
	}
	m := p.vstack[len(p.vstack)-1]
	if m != nil && len(m) == 0 {
		return
	}
	m = make(map[string]interface{})
	p.vstack[len(p.vstack)-1] = m
}
func (p *parser) popV() {
	m := p.vstack[len(p.vstack)-1]
	if len(m) > 0 {
		p.vstack[len(p.vstack)-1] = nil
	}
	p.vstack = p.vstack[:len(p.vstack)-1]
}
func (p *parser) pushRecovery(labels []string, expr interface{}) {
	if cap(p.recoveryStack) == len(p.recoveryStack) {
		p.recoveryStack = append(p.recoveryStack, nil)
	} else {
		p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)+1]
	}
	m := make(map[string]interface{}, len(labels))
	for _, fl := range labels {
		m[fl] = expr
	}
	p.recoveryStack[len(p.recoveryStack)-1] = m
}
func (p *parser) popRecovery() {
	p.recoveryStack[len(p.recoveryStack)-1] = nil
	p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)-1]
}
func (p *parser) print(prefix, s string) string {
	if !p.debug {
		return s
	}
	fmt.Printf("%s %d:%d:%d: %s [%#U]\n",
		prefix, p.pt.line, p.pt.col, p.pt.offset, s, p.pt.rn)
	return s
}
func (p *parser) in(s string) string {
	p.depth++
	return p.print(strings.Repeat(" ", p.depth)+">", s)
}
func (p *parser) out(s string) string {
	p.depth--
	return p.print(strings.Repeat(" ", p.depth)+"<", s)
}
func (p *parser) addErr(err error) {
	p.addErrAt(err, p.pt.position, []string{})
}
func (p *parser) addErrAt(err error, pos position, expected []string) {
	var buf bytes.Buffer
	if p.filename != "" {
		buf.WriteString(p.filename)
	}
	if buf.Len() > 0 {
		buf.WriteString(":")
	}
	buf.WriteString(fmt.Sprintf("%d:%d (%d)", pos.line, pos.col, pos.offset))
	if len(p.rstack) > 0 {
		if buf.Len() > 0 {
			buf.WriteString(": ")
		}
		rule := p.rstack[len(p.rstack)-1]
		if rule.displayName != "" {
			buf.WriteString("rule " + rule.displayName)
		} else {
			buf.WriteString("rule " + rule.name)
		}
	}
	pe := &parserError{Inner: err, pos: pos, prefix: buf.String(), expected: expected}
	p.errs.add(pe)
}
func (p *parser) failAt(fail bool, pos position, want string) {
	if fail == p.maxFailInvertExpected {
		if pos.offset < p.maxFailPos.offset {
			return
		}
		if pos.offset > p.maxFailPos.offset {
			p.maxFailPos = pos
			p.maxFailExpected = p.maxFailExpected[:0]
		}
		if p.maxFailInvertExpected {
			want = "!" + want
		}
		p.maxFailExpected = append(p.maxFailExpected, want)
	}
}
func (p *parser) read() {
	p.pt.offset += p.pt.w
	rn, n := utf8.DecodeRune(p.data[p.pt.offset:])
	p.pt.rn = rn
	p.pt.w = n
	p.pt.col++
	if rn == '\n' {
		p.pt.line++
		p.pt.col = 0
	}
	if rn == utf8.RuneError && n == 1 {  
		if !p.allowInvalidUTF8 {
			p.addErr(errInvalidEncoding)
		}
	}
}
func (p *parser) restore(pt savepoint) {
	if p.debug {
		defer p.out(p.in("restore"))
	}
	if pt.offset == p.pt.offset {
		return
	}
	p.pt = pt
}
type Cloner interface {
	Clone() interface{}
}
var statePool = &sync.Pool{
	New: func() interface{} { return make(storeDict) },
}
func (sd storeDict) Discard() {
	for k := range sd {
		delete(sd, k)
	}
	statePool.Put(sd)
}
func (p *parser) cloneState() storeDict {
	if p.debug {
		defer p.out(p.in("cloneState"))
	}
	state := statePool.Get().(storeDict)
	for k, v := range p.cur.state {
		if c, ok := v.(Cloner); ok {
			state[k] = c.Clone()
		} else {
			state[k] = v
		}
	}
	return state
}
func (p *parser) restoreState(state storeDict) {
	if p.debug {
		defer p.out(p.in("restoreState"))
	}
	p.cur.state.Discard()
	p.cur.state = state
}
func (p *parser) sliceFrom(start savepoint) []byte {
	return p.data[start.position.offset:p.pt.position.offset]
}
func (p *parser) getMemoized(node interface{}) (resultTuple, bool) {
	if len(p.memo) == 0 {
		return resultTuple{}, false
	}
	m := p.memo[p.pt.offset]
	if len(m) == 0 {
		return resultTuple{}, false
	}
	res, ok := m[node]
	return res, ok
}
func (p *parser) setMemoized(pt savepoint, node interface{}, tuple resultTuple) {
	if p.memo == nil {
		p.memo = make(map[int]map[interface{}]resultTuple)
	}
	m := p.memo[pt.offset]
	if m == nil {
		m = make(map[interface{}]resultTuple)
		p.memo[pt.offset] = m
	}
	m[node] = tuple
}
func (p *parser) buildRulesTable(g *grammar) {
	p.rules = make(map[string]*rule, len(g.rules))
	for _, r := range g.rules {
		p.rules[r.name] = r
	}
}