package parser

import (
	"bytes"
	"fmt"
	"sort"
	"strings"

	"JSON/lexer"
	"JSON/parser/bsr"
	"JSON/parser/slot"
	"JSON/parser/symbols"
	"JSON/token"
)

type parser struct {
	cI int

	R *descriptors
	U *descriptors

	popped   map[poppedNode]bool
	crf      map[clusterNode][]*crfNode
	crfNodes map[crfNode]*crfNode

	lex         *lexer.Lexer
	parseErrors []*Error

	bsrSet *bsr.Set
}

func newParser(l *lexer.Lexer) *parser {
	return &parser{
		cI:     0,
		lex:    l,
		R:      &descriptors{},
		U:      &descriptors{},
		popped: make(map[poppedNode]bool),
		crf: map[clusterNode][]*crfNode{
			{symbols.NT_JSON, 0}: {},
		},
		crfNodes:    map[crfNode]*crfNode{},
		bsrSet:      bsr.New(symbols.NT_JSON, l),
		parseErrors: nil,
	}
}

func Parse(l *lexer.Lexer) (*bsr.Set, []*Error) {
	return newParser(l).parse()
}

func (p *parser) parse() (*bsr.Set, []*Error) {
	var L slot.Label
	m, cU := len(p.lex.Tokens)-1, 0
	p.ntAdd(symbols.NT_JSON, 0)

	for !p.R.empty() {
		L, cU, p.cI = p.R.remove()

		switch L {
		case slot.Array0R0: 

			p.call(slot.Array0R1, cU, p.cI)
		case slot.Array0R1: 

			if !p.testSelect(slot.Array0R1) {
				p.parseError(slot.Array0R1, p.cI, first[slot.Array0R1])
				break
			}

			p.call(slot.Array0R2, cU, p.cI)
		case slot.Array0R2: 

			if !p.testSelect(slot.Array0R2) {
				p.parseError(slot.Array0R2, p.cI, first[slot.Array0R2])
				break
			}

			p.call(slot.Array0R3, cU, p.cI)
		case slot.Array0R3: 

			if p.follow(symbols.NT_Array) {
				p.rtn(symbols.NT_Array, cU, p.cI)
			} else {
				p.parseError(slot.Array0R0, p.cI, followSets[symbols.NT_Array])
			}
		case slot.CHAR0R0: 

			p.bsrSet.Add(slot.CHAR0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_CHAR) {
				p.rtn(symbols.NT_CHAR, cU, p.cI)
			} else {
				p.parseError(slot.CHAR0R0, p.cI, followSets[symbols.NT_CHAR])
			}
		case slot.CHAR1R0: 

			p.bsrSet.Add(slot.CHAR1R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.CHAR1R1) {
				p.parseError(slot.CHAR1R1, p.cI, first[slot.CHAR1R1])
				break
			}

			p.call(slot.CHAR1R2, cU, p.cI)
		case slot.CHAR1R2: 

			if p.follow(symbols.NT_CHAR) {
				p.rtn(symbols.NT_CHAR, cU, p.cI)
			} else {
				p.parseError(slot.CHAR1R0, p.cI, followSets[symbols.NT_CHAR])
			}
		case slot.COLON0R0: 

			p.bsrSet.Add(slot.COLON0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.COLON0R1) {
				p.parseError(slot.COLON0R1, p.cI, first[slot.COLON0R1])
				break
			}

			p.call(slot.COLON0R2, cU, p.cI)
		case slot.COLON0R2: 

			if p.follow(symbols.NT_COLON) {
				p.rtn(symbols.NT_COLON, cU, p.cI)
			} else {
				p.parseError(slot.COLON0R0, p.cI, followSets[symbols.NT_COLON])
			}
		case slot.COMMA0R0: 

			p.bsrSet.Add(slot.COMMA0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.COMMA0R1) {
				p.parseError(slot.COMMA0R1, p.cI, first[slot.COMMA0R1])
				break
			}

			p.call(slot.COMMA0R2, cU, p.cI)
		case slot.COMMA0R2: 

			if p.follow(symbols.NT_COMMA) {
				p.rtn(symbols.NT_COMMA, cU, p.cI)
			} else {
				p.parseError(slot.COMMA0R0, p.cI, followSets[symbols.NT_COMMA])
			}
		case slot.CharCode0R0: 

			p.bsrSet.Add(slot.CharCode0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_CharCode) {
				p.rtn(symbols.NT_CharCode, cU, p.cI)
			} else {
				p.parseError(slot.CharCode0R0, p.cI, followSets[symbols.NT_CharCode])
			}
		case slot.CharCode1R0: 

			p.bsrSet.Add(slot.CharCode1R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.CharCode1R1) {
				p.parseError(slot.CharCode1R1, p.cI, first[slot.CharCode1R1])
				break
			}

			p.call(slot.CharCode1R2, cU, p.cI)
		case slot.CharCode1R2: 

			if !p.testSelect(slot.CharCode1R2) {
				p.parseError(slot.CharCode1R2, p.cI, first[slot.CharCode1R2])
				break
			}

			p.call(slot.CharCode1R3, cU, p.cI)
		case slot.CharCode1R3: 

			if !p.testSelect(slot.CharCode1R3) {
				p.parseError(slot.CharCode1R3, p.cI, first[slot.CharCode1R3])
				break
			}

			p.call(slot.CharCode1R4, cU, p.cI)
		case slot.CharCode1R4: 

			if !p.testSelect(slot.CharCode1R4) {
				p.parseError(slot.CharCode1R4, p.cI, first[slot.CharCode1R4])
				break
			}

			p.call(slot.CharCode1R5, cU, p.cI)
		case slot.CharCode1R5: 

			if p.follow(symbols.NT_CharCode) {
				p.rtn(symbols.NT_CharCode, cU, p.cI)
			} else {
				p.parseError(slot.CharCode1R0, p.cI, followSets[symbols.NT_CharCode])
			}
		case slot.Close0R0: 

			p.bsrSet.Add(slot.Close0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_Close) {
				p.rtn(symbols.NT_Close, cU, p.cI)
			} else {
				p.parseError(slot.Close0R0, p.cI, followSets[symbols.NT_Close])
			}
		case slot.Close1R0: 

			p.call(slot.Close1R1, cU, p.cI)
		case slot.Close1R1: 

			if !p.testSelect(slot.Close1R1) {
				p.parseError(slot.Close1R1, p.cI, first[slot.Close1R1])
				break
			}

			p.call(slot.Close1R2, cU, p.cI)
		case slot.Close1R2: 

			if p.follow(symbols.NT_Close) {
				p.rtn(symbols.NT_Close, cU, p.cI)
			} else {
				p.parseError(slot.Close1R0, p.cI, followSets[symbols.NT_Close])
			}
		case slot.ComPair0x0R0: 

			p.call(slot.ComPair0x0R1, cU, p.cI)
		case slot.ComPair0x0R1: 

			if !p.testSelect(slot.ComPair0x0R1) {
				p.parseError(slot.ComPair0x0R1, p.cI, first[slot.ComPair0x0R1])
				break
			}

			p.call(slot.ComPair0x0R2, cU, p.cI)
		case slot.ComPair0x0R2: 

			if !p.testSelect(slot.ComPair0x0R2) {
				p.parseError(slot.ComPair0x0R2, p.cI, first[slot.ComPair0x0R2])
				break
			}

			p.call(slot.ComPair0x0R3, cU, p.cI)
		case slot.ComPair0x0R3: 

			if p.follow(symbols.NT_ComPair0x) {
				p.rtn(symbols.NT_ComPair0x, cU, p.cI)
			} else {
				p.parseError(slot.ComPair0x0R0, p.cI, followSets[symbols.NT_ComPair0x])
			}
		case slot.ComPair0x1R0: 
			p.bsrSet.AddEmpty(slot.ComPair0x1R0, p.cI)

			if p.follow(symbols.NT_ComPair0x) {
				p.rtn(symbols.NT_ComPair0x, cU, p.cI)
			} else {
				p.parseError(slot.ComPair0x1R0, p.cI, followSets[symbols.NT_ComPair0x])
			}
		case slot.ComVal0x0R0: 

			p.call(slot.ComVal0x0R1, cU, p.cI)
		case slot.ComVal0x0R1: 

			if !p.testSelect(slot.ComVal0x0R1) {
				p.parseError(slot.ComVal0x0R1, p.cI, first[slot.ComVal0x0R1])
				break
			}

			p.call(slot.ComVal0x0R2, cU, p.cI)
		case slot.ComVal0x0R2: 

			if !p.testSelect(slot.ComVal0x0R2) {
				p.parseError(slot.ComVal0x0R2, p.cI, first[slot.ComVal0x0R2])
				break
			}

			p.call(slot.ComVal0x0R3, cU, p.cI)
		case slot.ComVal0x0R3: 

			if p.follow(symbols.NT_ComVal0x) {
				p.rtn(symbols.NT_ComVal0x, cU, p.cI)
			} else {
				p.parseError(slot.ComVal0x0R0, p.cI, followSets[symbols.NT_ComVal0x])
			}
		case slot.ComVal0x1R0: 
			p.bsrSet.AddEmpty(slot.ComVal0x1R0, p.cI)

			if p.follow(symbols.NT_ComVal0x) {
				p.rtn(symbols.NT_ComVal0x, cU, p.cI)
			} else {
				p.parseError(slot.ComVal0x1R0, p.cI, followSets[symbols.NT_ComVal0x])
			}
		case slot.Elements0R0: 

			p.call(slot.Elements0R1, cU, p.cI)
		case slot.Elements0R1: 

			if !p.testSelect(slot.Elements0R1) {
				p.parseError(slot.Elements0R1, p.cI, first[slot.Elements0R1])
				break
			}

			p.call(slot.Elements0R2, cU, p.cI)
		case slot.Elements0R2: 

			if p.follow(symbols.NT_Elements) {
				p.rtn(symbols.NT_Elements, cU, p.cI)
			} else {
				p.parseError(slot.Elements0R0, p.cI, followSets[symbols.NT_Elements])
			}
		case slot.EscOrComment0R0: 

			p.bsrSet.Add(slot.EscOrComment0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_EscOrComment) {
				p.rtn(symbols.NT_EscOrComment, cU, p.cI)
			} else {
				p.parseError(slot.EscOrComment0R0, p.cI, followSets[symbols.NT_EscOrComment])
			}
		case slot.EscOrComment1R0: 

			p.call(slot.EscOrComment1R1, cU, p.cI)
		case slot.EscOrComment1R1: 

			if p.follow(symbols.NT_EscOrComment) {
				p.rtn(symbols.NT_EscOrComment, cU, p.cI)
			} else {
				p.parseError(slot.EscOrComment1R0, p.cI, followSets[symbols.NT_EscOrComment])
			}
		case slot.FALSE0R0: 

			p.bsrSet.Add(slot.FALSE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.FALSE0R1) {
				p.parseError(slot.FALSE0R1, p.cI, first[slot.FALSE0R1])
				break
			}

			p.call(slot.FALSE0R2, cU, p.cI)
		case slot.FALSE0R2: 

			if p.follow(symbols.NT_FALSE) {
				p.rtn(symbols.NT_FALSE, cU, p.cI)
			} else {
				p.parseError(slot.FALSE0R0, p.cI, followSets[symbols.NT_FALSE])
			}
		case slot.HEX0R0: 

			p.call(slot.HEX0R1, cU, p.cI)
		case slot.HEX0R1: 

			if !p.testSelect(slot.HEX0R1) {
				p.parseError(slot.HEX0R1, p.cI, first[slot.HEX0R1])
				break
			}

			p.bsrSet.Add(slot.HEX0R2, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_HEX) {
				p.rtn(symbols.NT_HEX, cU, p.cI)
			} else {
				p.parseError(slot.HEX0R0, p.cI, followSets[symbols.NT_HEX])
			}
		case slot.HEX1R0: 
			p.bsrSet.AddEmpty(slot.HEX1R0, p.cI)

			if p.follow(symbols.NT_HEX) {
				p.rtn(symbols.NT_HEX, cU, p.cI)
			} else {
				p.parseError(slot.HEX1R0, p.cI, followSets[symbols.NT_HEX])
			}
		case slot.INT0R0: 

			p.bsrSet.Add(slot.INT0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.INT0R1) {
				p.parseError(slot.INT0R1, p.cI, first[slot.INT0R1])
				break
			}

			p.call(slot.INT0R2, cU, p.cI)
		case slot.INT0R2: 

			if p.follow(symbols.NT_INT) {
				p.rtn(symbols.NT_INT, cU, p.cI)
			} else {
				p.parseError(slot.INT0R0, p.cI, followSets[symbols.NT_INT])
			}
		case slot.Integers0R0: 

			p.bsrSet.Add(slot.Integers0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_Integers) {
				p.rtn(symbols.NT_Integers, cU, p.cI)
			} else {
				p.parseError(slot.Integers0R0, p.cI, followSets[symbols.NT_Integers])
			}
		case slot.Integers1R0: 

			p.bsrSet.Add(slot.Integers1R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_Integers) {
				p.rtn(symbols.NT_Integers, cU, p.cI)
			} else {
				p.parseError(slot.Integers1R0, p.cI, followSets[symbols.NT_Integers])
			}
		case slot.JSON0R0: 

			p.call(slot.JSON0R1, cU, p.cI)
		case slot.JSON0R1: 

			if !p.testSelect(slot.JSON0R1) {
				p.parseError(slot.JSON0R1, p.cI, first[slot.JSON0R1])
				break
			}

			p.call(slot.JSON0R2, cU, p.cI)
		case slot.JSON0R2: 

			if p.follow(symbols.NT_JSON) {
				p.rtn(symbols.NT_JSON, cU, p.cI)
			} else {
				p.parseError(slot.JSON0R0, p.cI, followSets[symbols.NT_JSON])
			}
		case slot.LBRACE0R0: 

			p.bsrSet.Add(slot.LBRACE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.LBRACE0R1) {
				p.parseError(slot.LBRACE0R1, p.cI, first[slot.LBRACE0R1])
				break
			}

			p.call(slot.LBRACE0R2, cU, p.cI)
		case slot.LBRACE0R2: 

			if p.follow(symbols.NT_LBRACE) {
				p.rtn(symbols.NT_LBRACE, cU, p.cI)
			} else {
				p.parseError(slot.LBRACE0R0, p.cI, followSets[symbols.NT_LBRACE])
			}
		case slot.LBRACKET0R0: 

			p.bsrSet.Add(slot.LBRACKET0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.LBRACKET0R1) {
				p.parseError(slot.LBRACKET0R1, p.cI, first[slot.LBRACKET0R1])
				break
			}

			p.call(slot.LBRACKET0R2, cU, p.cI)
		case slot.LBRACKET0R2: 

			if p.follow(symbols.NT_LBRACKET) {
				p.rtn(symbols.NT_LBRACKET, cU, p.cI)
			} else {
				p.parseError(slot.LBRACKET0R0, p.cI, followSets[symbols.NT_LBRACKET])
			}
		case slot.LineOrBlock0R0: 

			p.bsrSet.Add(slot.LineOrBlock0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_LineOrBlock) {
				p.rtn(symbols.NT_LineOrBlock, cU, p.cI)
			} else {
				p.parseError(slot.LineOrBlock0R0, p.cI, followSets[symbols.NT_LineOrBlock])
			}
		case slot.LineOrBlock1R0: 

			p.bsrSet.Add(slot.LineOrBlock1R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_LineOrBlock) {
				p.rtn(symbols.NT_LineOrBlock, cU, p.cI)
			} else {
				p.parseError(slot.LineOrBlock1R0, p.cI, followSets[symbols.NT_LineOrBlock])
			}
		case slot.Members0R0: 

			p.call(slot.Members0R1, cU, p.cI)
		case slot.Members0R1: 

			if !p.testSelect(slot.Members0R1) {
				p.parseError(slot.Members0R1, p.cI, first[slot.Members0R1])
				break
			}

			p.call(slot.Members0R2, cU, p.cI)
		case slot.Members0R2: 

			if p.follow(symbols.NT_Members) {
				p.rtn(symbols.NT_Members, cU, p.cI)
			} else {
				p.parseError(slot.Members0R0, p.cI, followSets[symbols.NT_Members])
			}
		case slot.Mems0x0R0: 

			p.call(slot.Mems0x0R1, cU, p.cI)
		case slot.Mems0x0R1: 

			if !p.testSelect(slot.Mems0x0R1) {
				p.parseError(slot.Mems0x0R1, p.cI, first[slot.Mems0x0R1])
				break
			}

			p.call(slot.Mems0x0R2, cU, p.cI)
		case slot.Mems0x0R2: 

			if p.follow(symbols.NT_Mems0x) {
				p.rtn(symbols.NT_Mems0x, cU, p.cI)
			} else {
				p.parseError(slot.Mems0x0R0, p.cI, followSets[symbols.NT_Mems0x])
			}
		case slot.Mems0x1R0: 
			p.bsrSet.AddEmpty(slot.Mems0x1R0, p.cI)

			if p.follow(symbols.NT_Mems0x) {
				p.rtn(symbols.NT_Mems0x, cU, p.cI)
			} else {
				p.parseError(slot.Mems0x1R0, p.cI, followSets[symbols.NT_Mems0x])
			}
		case slot.NUL0R0: 

			p.bsrSet.Add(slot.NUL0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.NUL0R1) {
				p.parseError(slot.NUL0R1, p.cI, first[slot.NUL0R1])
				break
			}

			p.call(slot.NUL0R2, cU, p.cI)
		case slot.NUL0R2: 

			if p.follow(symbols.NT_NUL) {
				p.rtn(symbols.NT_NUL, cU, p.cI)
			} else {
				p.parseError(slot.NUL0R0, p.cI, followSets[symbols.NT_NUL])
			}
		case slot.Number0R0: 

			p.call(slot.Number0R1, cU, p.cI)
		case slot.Number0R1: 

			if !p.testSelect(slot.Number0R1) {
				p.parseError(slot.Number0R1, p.cI, first[slot.Number0R1])
				break
			}

			p.call(slot.Number0R2, cU, p.cI)
		case slot.Number0R2: 

			if !p.testSelect(slot.Number0R2) {
				p.parseError(slot.Number0R2, p.cI, first[slot.Number0R2])
				break
			}

			p.call(slot.Number0R3, cU, p.cI)
		case slot.Number0R3: 

			if !p.testSelect(slot.Number0R3) {
				p.parseError(slot.Number0R3, p.cI, first[slot.Number0R3])
				break
			}

			p.call(slot.Number0R4, cU, p.cI)
		case slot.Number0R4: 

			if p.follow(symbols.NT_Number) {
				p.rtn(symbols.NT_Number, cU, p.cI)
			} else {
				p.parseError(slot.Number0R0, p.cI, followSets[symbols.NT_Number])
			}
		case slot.Object0R0: 

			p.call(slot.Object0R1, cU, p.cI)
		case slot.Object0R1: 

			if !p.testSelect(slot.Object0R1) {
				p.parseError(slot.Object0R1, p.cI, first[slot.Object0R1])
				break
			}

			p.call(slot.Object0R2, cU, p.cI)
		case slot.Object0R2: 

			if !p.testSelect(slot.Object0R2) {
				p.parseError(slot.Object0R2, p.cI, first[slot.Object0R2])
				break
			}

			p.call(slot.Object0R3, cU, p.cI)
		case slot.Object0R3: 

			if !p.testSelect(slot.Object0R3) {
				p.parseError(slot.Object0R3, p.cI, first[slot.Object0R3])
				break
			}

			p.call(slot.Object0R4, cU, p.cI)
		case slot.Object0R4: 

			if p.follow(symbols.NT_Object) {
				p.rtn(symbols.NT_Object, cU, p.cI)
			} else {
				p.parseError(slot.Object0R0, p.cI, followSets[symbols.NT_Object])
			}
		case slot.OptElem0R0: 

			p.call(slot.OptElem0R1, cU, p.cI)
		case slot.OptElem0R1: 

			if p.follow(symbols.NT_OptElem) {
				p.rtn(symbols.NT_OptElem, cU, p.cI)
			} else {
				p.parseError(slot.OptElem0R0, p.cI, followSets[symbols.NT_OptElem])
			}
		case slot.OptElem1R0: 
			p.bsrSet.AddEmpty(slot.OptElem1R0, p.cI)

			if p.follow(symbols.NT_OptElem) {
				p.rtn(symbols.NT_OptElem, cU, p.cI)
			} else {
				p.parseError(slot.OptElem1R0, p.cI, followSets[symbols.NT_OptElem])
			}
		case slot.OptExp0R0: 

			p.bsrSet.Add(slot.OptExp0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_OptExp) {
				p.rtn(symbols.NT_OptExp, cU, p.cI)
			} else {
				p.parseError(slot.OptExp0R0, p.cI, followSets[symbols.NT_OptExp])
			}
		case slot.OptExp1R0: 
			p.bsrSet.AddEmpty(slot.OptExp1R0, p.cI)

			if p.follow(symbols.NT_OptExp) {
				p.rtn(symbols.NT_OptExp, cU, p.cI)
			} else {
				p.parseError(slot.OptExp1R0, p.cI, followSets[symbols.NT_OptExp])
			}
		case slot.OptFrac0R0: 

			p.bsrSet.Add(slot.OptFrac0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_OptFrac) {
				p.rtn(symbols.NT_OptFrac, cU, p.cI)
			} else {
				p.parseError(slot.OptFrac0R0, p.cI, followSets[symbols.NT_OptFrac])
			}
		case slot.OptFrac1R0: 
			p.bsrSet.AddEmpty(slot.OptFrac1R0, p.cI)

			if p.follow(symbols.NT_OptFrac) {
				p.rtn(symbols.NT_OptFrac, cU, p.cI)
			} else {
				p.parseError(slot.OptFrac1R0, p.cI, followSets[symbols.NT_OptFrac])
			}
		case slot.Pair0R0: 

			p.call(slot.Pair0R1, cU, p.cI)
		case slot.Pair0R1: 

			if !p.testSelect(slot.Pair0R1) {
				p.parseError(slot.Pair0R1, p.cI, first[slot.Pair0R1])
				break
			}

			p.call(slot.Pair0R2, cU, p.cI)
		case slot.Pair0R2: 

			if !p.testSelect(slot.Pair0R2) {
				p.parseError(slot.Pair0R2, p.cI, first[slot.Pair0R2])
				break
			}

			p.call(slot.Pair0R3, cU, p.cI)
		case slot.Pair0R3: 

			if p.follow(symbols.NT_Pair) {
				p.rtn(symbols.NT_Pair, cU, p.cI)
			} else {
				p.parseError(slot.Pair0R0, p.cI, followSets[symbols.NT_Pair])
			}
		case slot.RBRACE0R0: 

			p.bsrSet.Add(slot.RBRACE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.RBRACE0R1) {
				p.parseError(slot.RBRACE0R1, p.cI, first[slot.RBRACE0R1])
				break
			}

			p.call(slot.RBRACE0R2, cU, p.cI)
		case slot.RBRACE0R2: 

			if p.follow(symbols.NT_RBRACE) {
				p.rtn(symbols.NT_RBRACE, cU, p.cI)
			} else {
				p.parseError(slot.RBRACE0R0, p.cI, followSets[symbols.NT_RBRACE])
			}
		case slot.RBRACKET0R0: 

			p.bsrSet.Add(slot.RBRACKET0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.RBRACKET0R1) {
				p.parseError(slot.RBRACKET0R1, p.cI, first[slot.RBRACKET0R1])
				break
			}

			p.call(slot.RBRACKET0R2, cU, p.cI)
		case slot.RBRACKET0R2: 

			if p.follow(symbols.NT_RBRACKET) {
				p.rtn(symbols.NT_RBRACKET, cU, p.cI)
			} else {
				p.parseError(slot.RBRACKET0R0, p.cI, followSets[symbols.NT_RBRACKET])
			}
		case slot.String0R0: 

			p.bsrSet.Add(slot.String0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.String0R1) {
				p.parseError(slot.String0R1, p.cI, first[slot.String0R1])
				break
			}

			p.call(slot.String0R2, cU, p.cI)
		case slot.String0R2: 

			if !p.testSelect(slot.String0R2) {
				p.parseError(slot.String0R2, p.cI, first[slot.String0R2])
				break
			}

			p.call(slot.String0R3, cU, p.cI)
		case slot.String0R3: 

			if p.follow(symbols.NT_String) {
				p.rtn(symbols.NT_String, cU, p.cI)
			} else {
				p.parseError(slot.String0R0, p.cI, followSets[symbols.NT_String])
			}
		case slot.TRUE0R0: 

			p.bsrSet.Add(slot.TRUE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.TRUE0R1) {
				p.parseError(slot.TRUE0R1, p.cI, first[slot.TRUE0R1])
				break
			}

			p.call(slot.TRUE0R2, cU, p.cI)
		case slot.TRUE0R2: 

			if p.follow(symbols.NT_TRUE) {
				p.rtn(symbols.NT_TRUE, cU, p.cI)
			} else {
				p.parseError(slot.TRUE0R0, p.cI, followSets[symbols.NT_TRUE])
			}
		case slot.Value0R0: 

			p.call(slot.Value0R1, cU, p.cI)
		case slot.Value0R1: 

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value0R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value1R0: 

			p.call(slot.Value1R1, cU, p.cI)
		case slot.Value1R1: 

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value1R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value2R0: 

			p.call(slot.Value2R1, cU, p.cI)
		case slot.Value2R1: 

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value2R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value3R0: 

			p.call(slot.Value3R1, cU, p.cI)
		case slot.Value3R1: 

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value3R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value4R0: 

			p.call(slot.Value4R1, cU, p.cI)
		case slot.Value4R1: 

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value4R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value5R0: 

			p.call(slot.Value5R1, cU, p.cI)
		case slot.Value5R1: 

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value5R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value6R0: 

			p.call(slot.Value6R1, cU, p.cI)
		case slot.Value6R1: 

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value6R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.WS0R0: 

			p.call(slot.WS0R1, cU, p.cI)
		case slot.WS0R1: 

			if !p.testSelect(slot.WS0R1) {
				p.parseError(slot.WS0R1, p.cI, first[slot.WS0R1])
				break
			}

			p.call(slot.WS0R2, cU, p.cI)
		case slot.WS0R2: 

			if p.follow(symbols.NT_WS) {
				p.rtn(symbols.NT_WS, cU, p.cI)
			} else {
				p.parseError(slot.WS0R0, p.cI, followSets[symbols.NT_WS])
			}
		case slot.WS1R0: 
			p.bsrSet.AddEmpty(slot.WS1R0, p.cI)

			if p.follow(symbols.NT_WS) {
				p.rtn(symbols.NT_WS, cU, p.cI)
			} else {
				p.parseError(slot.WS1R0, p.cI, followSets[symbols.NT_WS])
			}

		default:
			panic("This must not happen")
		}
	}
	if !p.bsrSet.Contain(symbols.NT_JSON, 0, m) {
		p.sortParseErrors()
		return nil, p.parseErrors
	}
	return p.bsrSet, nil
}

func (p *parser) ntAdd(nt symbols.NT, j int) {

	failed := true
	expected := map[token.Type]string{}
	for _, l := range slot.GetAlternates(nt) {
		if p.testSelect(l) {
			p.dscAdd(l, j, j)
			failed = false
		} else {
			for k, v := range first[l] {
				expected[k] = v
			}
		}
	}
	if failed {
		for _, l := range slot.GetAlternates(nt) {
			p.parseError(l, j, expected)
		}
	}
}

type poppedNode struct {
	X    symbols.NT
	k, j int
}

type clusterNode struct {
	X symbols.NT
	k int
}

type crfNode struct {
	L slot.Label
	i int
}

func (p *parser) call(L slot.Label, i, j int) {

	u, exist := p.crfNodes[crfNode{L, i}]

	if !exist {
		u = &crfNode{L, i}
		p.crfNodes[*u] = u
	}
	X := L.Symbols()[L.Pos()-1].(symbols.NT)
	ndV := clusterNode{X, j}
	v, exist := p.crf[ndV]
	if !exist {

		p.crf[ndV] = []*crfNode{u}
		p.ntAdd(X, j)
	} else {

		if !existEdge(v, u) {

			p.crf[ndV] = append(v, u)

			for pnd := range p.popped {
				if pnd.X == X && pnd.k == j {
					p.dscAdd(L, i, pnd.j)
					p.bsrSet.Add(L, i, j, pnd.j)
				}
			}
		}
	}
}

func existEdge(nds []*crfNode, nd *crfNode) bool {
	for _, nd1 := range nds {
		if nd1 == nd {
			return true
		}
	}
	return false
}

func (p *parser) rtn(X symbols.NT, k, j int) {

	pn := poppedNode{X, k, j}
	if _, exist := p.popped[pn]; !exist {
		p.popped[pn] = true
		for _, nd := range p.crf[clusterNode{X, k}] {
			p.dscAdd(nd.L, nd.i, j)
			p.bsrSet.Add(nd.L, nd.i, k, j)
		}
	}
}

func (cn clusterNode) String() string {
	return fmt.Sprintf("(%s,%d)", cn.X, cn.k)
}

func (n crfNode) String() string {
	return fmt.Sprintf("(%s,%d)", n.L.String(), n.i)
}

type descriptors struct {
	set []*descriptor
}

func (ds *descriptors) contain(d *descriptor) bool {
	for _, d1 := range ds.set {
		if d1 == d {
			return true
		}
	}
	return false
}

func (ds *descriptors) empty() bool {
	return len(ds.set) == 0
}

func (ds *descriptors) String() string {
	buf := new(bytes.Buffer)
	buf.WriteString("{")
	for i, d := range ds.set {
		if i > 0 {
			buf.WriteString("; ")
		}
		fmt.Fprintf(buf, "%s", d)
	}
	buf.WriteString("}")
	return buf.String()
}

type descriptor struct {
	L slot.Label
	k int
	i int
}

func (d *descriptor) String() string {
	return fmt.Sprintf("%s,%d,%d", d.L, d.k, d.i)
}

func (p *parser) dscAdd(L slot.Label, k, i int) {

	d := &descriptor{L, k, i}
	if !p.U.contain(d) {
		p.R.set = append(p.R.set, d)
		p.U.set = append(p.U.set, d)
	}
}

func (ds *descriptors) remove() (L slot.Label, k, i int) {
	d := ds.set[len(ds.set)-1]
	ds.set = ds.set[:len(ds.set)-1]

	return d.L, d.k, d.i
}

func (p *parser) DumpDescriptors() {
	p.DumpR()
	p.DumpU()
}

func (p *parser) DumpR() {
	fmt.Println("R:")
	for _, d := range p.R.set {
		fmt.Printf(" %s\n", d)
	}
}

func (p *parser) DumpU() {
	fmt.Println("U:")
	for _, d := range p.U.set {
		fmt.Printf(" %s\n", d)
	}
}

func (p *parser) follow(nt symbols.NT) bool {
	_, exist := followSets[nt][p.lex.Tokens[p.cI].Type()]
	return exist
}

func (p *parser) testSelect(l slot.Label) bool {
	_, exist := first[l][p.lex.Tokens[p.cI].Type()]

	return exist
}

var first = []map[token.Type]string{

	{
		token.T_2: "[",
	},

	{
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_7: "carrotSlash",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_5: "bSlash",
	},

	{
		token.T_9:  "esc",
		token.T_21: "u",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_1: ":",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_0: ",",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_9: "esc",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_21: "u",
	},

	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},

	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},

	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},

	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_0: ",",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0: ",",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_0: ",",
		token.T_3: "]",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_0: ",",
		token.T_3: "]",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_10: "escChar",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.T_6:  "block_comment",
		token.T_16: "line_comment",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.T_13: "false",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_19: "optNeg",
	},

	{
		token.T_4: "aA_fF",
	},

	{
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
		token.T_19: "optNeg",
	},

	{
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
		token.T_19: "optNeg",
	},

	{
		token.T_19: "optNeg",
	},

	{
		token.T_15: "integer",
		token.T_22: "zero",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_15: "integer",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_22: "zero",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_23: "{",
	},

	{
		token.T_23: "{",
	},

	{
		token.EOF: "$",
	},

	{
		token.T_23: "{",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_8:  "dQuote",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_2: "[",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_16: "line_comment",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.T_6: "block_comment",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_24: "}",
	},

	{
		token.T_24: "}",
	},

	{
		token.T_18: "null",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_19: "optNeg",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_23: "{",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_24: "}",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_12: "exp",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_14: "frac",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_1: ":",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_24: "}",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_20: "true",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_19: "optNeg",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_23: "{",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_2: "[",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_20: "true",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_13: "false",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_18: "null",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
	},

	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
}

var followSets = []map[token.Type]string{

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},

	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_3: "]",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
		token.T_19: "optNeg",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.EOF: "$",
	},

	{
		token.T_8: "dQuote",
	},

	{
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},

	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_3: "]",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},

	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
}

type Error struct {

	cI int

	Slot slot.Label

	Token *token.Token

	Line, Column int

	Expected map[token.Type]string
}

func (pe *Error) String() string {
	w := new(bytes.Buffer)
	fmt.Fprintf(w, "Parse Error: %s I[%d]=%s at line %d col %d\n",
		pe.Slot, pe.cI, pe.Token, pe.Line, pe.Column)
	exp := []string{}
	for _, e := range pe.Expected {
		exp = append(exp, e)
	}
	fmt.Fprintf(w, "Expected one of: [%s]", strings.Join(exp, ","))
	return w.String()
}

func (p *parser) parseError(slot slot.Label, i int, expected map[token.Type]string) {
	pe := &Error{cI: i, Slot: slot, Token: p.lex.Tokens[i], Expected: expected}
	p.parseErrors = append(p.parseErrors, pe)
}

func (p *parser) sortParseErrors() {
	sort.Slice(p.parseErrors,
		func(i, j int) bool {
			return p.parseErrors[j].Token.Lext() < p.parseErrors[i].Token.Lext()
		})
	for _, pe := range p.parseErrors {
		pe.Line, pe.Column = p.lex.GetLineColumn(pe.Token.Lext())
	}
}
// Package parser is generated by gogll. Do not edit.
package parser

import (
	"bytes"
	"fmt"
	"sort"
	"strings"

	"JSON/lexer"
	"JSON/parser/bsr"
	"JSON/parser/slot"
	"JSON/parser/symbols"
	"JSON/token"
)

type parser struct {
	cI int

	R *descriptors
	U *descriptors

	popped   map[poppedNode]bool
	crf      map[clusterNode][]*crfNode
	crfNodes map[crfNode]*crfNode

	lex         *lexer.Lexer
	parseErrors []*Error

	bsrSet *bsr.Set
}

func newParser(l *lexer.Lexer) *parser {
	return &parser{
		cI:     0,
		lex:    l,
		R:      &descriptors{},
		U:      &descriptors{},
		popped: make(map[poppedNode]bool),
		crf: map[clusterNode][]*crfNode{
			{symbols.NT_JSON, 0}: {},
		},
		crfNodes:    map[crfNode]*crfNode{},
		bsrSet:      bsr.New(symbols.NT_JSON, l),
		parseErrors: nil,
	}
}

// Parse returns the BSR set containing the parse forest.
// If the parse was successfull []*Error is nil
func Parse(l *lexer.Lexer) (*bsr.Set, []*Error) {
	return newParser(l).parse()
}

func (p *parser) parse() (*bsr.Set, []*Error) {
	var L slot.Label
	m, cU := len(p.lex.Tokens)-1, 0
	p.ntAdd(symbols.NT_JSON, 0)
	// p.DumpDescriptors()
	for !p.R.empty() {
		L, cU, p.cI = p.R.remove()

		// fmt.Println()
		// fmt.Printf("L:%s, cI:%d, I[p.cI]:%s, cU:%d\n", L, p.cI, p.lex.Tokens[p.cI], cU)
		// p.DumpDescriptors()

		switch L {
		case slot.Array0R0: // Array : ∙LBRACKET OptElem RBRACKET

			p.call(slot.Array0R1, cU, p.cI)
		case slot.Array0R1: // Array : LBRACKET ∙OptElem RBRACKET

			if !p.testSelect(slot.Array0R1) {
				p.parseError(slot.Array0R1, p.cI, first[slot.Array0R1])
				break
			}

			p.call(slot.Array0R2, cU, p.cI)
		case slot.Array0R2: // Array : LBRACKET OptElem ∙RBRACKET

			if !p.testSelect(slot.Array0R2) {
				p.parseError(slot.Array0R2, p.cI, first[slot.Array0R2])
				break
			}

			p.call(slot.Array0R3, cU, p.cI)
		case slot.Array0R3: // Array : LBRACKET OptElem RBRACKET ∙

			if p.follow(symbols.NT_Array) {
				p.rtn(symbols.NT_Array, cU, p.cI)
			} else {
				p.parseError(slot.Array0R0, p.cI, followSets[symbols.NT_Array])
			}
		case slot.CHAR0R0: // CHAR : ∙carrotSlash

			p.bsrSet.Add(slot.CHAR0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_CHAR) {
				p.rtn(symbols.NT_CHAR, cU, p.cI)
			} else {
				p.parseError(slot.CHAR0R0, p.cI, followSets[symbols.NT_CHAR])
			}
		case slot.CHAR1R0: // CHAR : ∙bSlash CharCode

			p.bsrSet.Add(slot.CHAR1R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.CHAR1R1) {
				p.parseError(slot.CHAR1R1, p.cI, first[slot.CHAR1R1])
				break
			}

			p.call(slot.CHAR1R2, cU, p.cI)
		case slot.CHAR1R2: // CHAR : bSlash CharCode ∙

			if p.follow(symbols.NT_CHAR) {
				p.rtn(symbols.NT_CHAR, cU, p.cI)
			} else {
				p.parseError(slot.CHAR1R0, p.cI, followSets[symbols.NT_CHAR])
			}
		case slot.COLON0R0: // COLON : ∙: WS

			p.bsrSet.Add(slot.COLON0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.COLON0R1) {
				p.parseError(slot.COLON0R1, p.cI, first[slot.COLON0R1])
				break
			}

			p.call(slot.COLON0R2, cU, p.cI)
		case slot.COLON0R2: // COLON : : WS ∙

			if p.follow(symbols.NT_COLON) {
				p.rtn(symbols.NT_COLON, cU, p.cI)
			} else {
				p.parseError(slot.COLON0R0, p.cI, followSets[symbols.NT_COLON])
			}
		case slot.COMMA0R0: // COMMA : ∙, WS

			p.bsrSet.Add(slot.COMMA0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.COMMA0R1) {
				p.parseError(slot.COMMA0R1, p.cI, first[slot.COMMA0R1])
				break
			}

			p.call(slot.COMMA0R2, cU, p.cI)
		case slot.COMMA0R2: // COMMA : , WS ∙

			if p.follow(symbols.NT_COMMA) {
				p.rtn(symbols.NT_COMMA, cU, p.cI)
			} else {
				p.parseError(slot.COMMA0R0, p.cI, followSets[symbols.NT_COMMA])
			}
		case slot.CharCode0R0: // CharCode : ∙esc

			p.bsrSet.Add(slot.CharCode0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_CharCode) {
				p.rtn(symbols.NT_CharCode, cU, p.cI)
			} else {
				p.parseError(slot.CharCode0R0, p.cI, followSets[symbols.NT_CharCode])
			}
		case slot.CharCode1R0: // CharCode : ∙u HEX HEX HEX HEX

			p.bsrSet.Add(slot.CharCode1R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.CharCode1R1) {
				p.parseError(slot.CharCode1R1, p.cI, first[slot.CharCode1R1])
				break
			}

			p.call(slot.CharCode1R2, cU, p.cI)
		case slot.CharCode1R2: // CharCode : u HEX ∙HEX HEX HEX

			if !p.testSelect(slot.CharCode1R2) {
				p.parseError(slot.CharCode1R2, p.cI, first[slot.CharCode1R2])
				break
			}

			p.call(slot.CharCode1R3, cU, p.cI)
		case slot.CharCode1R3: // CharCode : u HEX HEX ∙HEX HEX

			if !p.testSelect(slot.CharCode1R3) {
				p.parseError(slot.CharCode1R3, p.cI, first[slot.CharCode1R3])
				break
			}

			p.call(slot.CharCode1R4, cU, p.cI)
		case slot.CharCode1R4: // CharCode : u HEX HEX HEX ∙HEX

			if !p.testSelect(slot.CharCode1R4) {
				p.parseError(slot.CharCode1R4, p.cI, first[slot.CharCode1R4])
				break
			}

			p.call(slot.CharCode1R5, cU, p.cI)
		case slot.CharCode1R5: // CharCode : u HEX HEX HEX HEX ∙

			if p.follow(symbols.NT_CharCode) {
				p.rtn(symbols.NT_CharCode, cU, p.cI)
			} else {
				p.parseError(slot.CharCode1R0, p.cI, followSets[symbols.NT_CharCode])
			}
		case slot.Close0R0: // Close : ∙dQuote

			p.bsrSet.Add(slot.Close0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_Close) {
				p.rtn(symbols.NT_Close, cU, p.cI)
			} else {
				p.parseError(slot.Close0R0, p.cI, followSets[symbols.NT_Close])
			}
		case slot.Close1R0: // Close : ∙CHAR Close

			p.call(slot.Close1R1, cU, p.cI)
		case slot.Close1R1: // Close : CHAR ∙Close

			if !p.testSelect(slot.Close1R1) {
				p.parseError(slot.Close1R1, p.cI, first[slot.Close1R1])
				break
			}

			p.call(slot.Close1R2, cU, p.cI)
		case slot.Close1R2: // Close : CHAR Close ∙

			if p.follow(symbols.NT_Close) {
				p.rtn(symbols.NT_Close, cU, p.cI)
			} else {
				p.parseError(slot.Close1R0, p.cI, followSets[symbols.NT_Close])
			}
		case slot.ComPair0x0R0: // ComPair0x : ∙COMMA Pair ComPair0x

			p.call(slot.ComPair0x0R1, cU, p.cI)
		case slot.ComPair0x0R1: // ComPair0x : COMMA ∙Pair ComPair0x

			if !p.testSelect(slot.ComPair0x0R1) {
				p.parseError(slot.ComPair0x0R1, p.cI, first[slot.ComPair0x0R1])
				break
			}

			p.call(slot.ComPair0x0R2, cU, p.cI)
		case slot.ComPair0x0R2: // ComPair0x : COMMA Pair ∙ComPair0x

			if !p.testSelect(slot.ComPair0x0R2) {
				p.parseError(slot.ComPair0x0R2, p.cI, first[slot.ComPair0x0R2])
				break
			}

			p.call(slot.ComPair0x0R3, cU, p.cI)
		case slot.ComPair0x0R3: // ComPair0x : COMMA Pair ComPair0x ∙

			if p.follow(symbols.NT_ComPair0x) {
				p.rtn(symbols.NT_ComPair0x, cU, p.cI)
			} else {
				p.parseError(slot.ComPair0x0R0, p.cI, followSets[symbols.NT_ComPair0x])
			}
		case slot.ComPair0x1R0: // ComPair0x : ∙
			p.bsrSet.AddEmpty(slot.ComPair0x1R0, p.cI)

			if p.follow(symbols.NT_ComPair0x) {
				p.rtn(symbols.NT_ComPair0x, cU, p.cI)
			} else {
				p.parseError(slot.ComPair0x1R0, p.cI, followSets[symbols.NT_ComPair0x])
			}
		case slot.ComVal0x0R0: // ComVal0x : ∙COMMA Value ComVal0x

			p.call(slot.ComVal0x0R1, cU, p.cI)
		case slot.ComVal0x0R1: // ComVal0x : COMMA ∙Value ComVal0x

			if !p.testSelect(slot.ComVal0x0R1) {
				p.parseError(slot.ComVal0x0R1, p.cI, first[slot.ComVal0x0R1])
				break
			}

			p.call(slot.ComVal0x0R2, cU, p.cI)
		case slot.ComVal0x0R2: // ComVal0x : COMMA Value ∙ComVal0x

			if !p.testSelect(slot.ComVal0x0R2) {
				p.parseError(slot.ComVal0x0R2, p.cI, first[slot.ComVal0x0R2])
				break
			}

			p.call(slot.ComVal0x0R3, cU, p.cI)
		case slot.ComVal0x0R3: // ComVal0x : COMMA Value ComVal0x ∙

			if p.follow(symbols.NT_ComVal0x) {
				p.rtn(symbols.NT_ComVal0x, cU, p.cI)
			} else {
				p.parseError(slot.ComVal0x0R0, p.cI, followSets[symbols.NT_ComVal0x])
			}
		case slot.ComVal0x1R0: // ComVal0x : ∙
			p.bsrSet.AddEmpty(slot.ComVal0x1R0, p.cI)

			if p.follow(symbols.NT_ComVal0x) {
				p.rtn(symbols.NT_ComVal0x, cU, p.cI)
			} else {
				p.parseError(slot.ComVal0x1R0, p.cI, followSets[symbols.NT_ComVal0x])
			}
		case slot.Elements0R0: // Elements : ∙Value ComVal0x

			p.call(slot.Elements0R1, cU, p.cI)
		case slot.Elements0R1: // Elements : Value ∙ComVal0x

			if !p.testSelect(slot.Elements0R1) {
				p.parseError(slot.Elements0R1, p.cI, first[slot.Elements0R1])
				break
			}

			p.call(slot.Elements0R2, cU, p.cI)
		case slot.Elements0R2: // Elements : Value ComVal0x ∙

			if p.follow(symbols.NT_Elements) {
				p.rtn(symbols.NT_Elements, cU, p.cI)
			} else {
				p.parseError(slot.Elements0R0, p.cI, followSets[symbols.NT_Elements])
			}
		case slot.EscOrComment0R0: // EscOrComment : ∙escChar

			p.bsrSet.Add(slot.EscOrComment0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_EscOrComment) {
				p.rtn(symbols.NT_EscOrComment, cU, p.cI)
			} else {
				p.parseError(slot.EscOrComment0R0, p.cI, followSets[symbols.NT_EscOrComment])
			}
		case slot.EscOrComment1R0: // EscOrComment : ∙LineOrBlock

			p.call(slot.EscOrComment1R1, cU, p.cI)
		case slot.EscOrComment1R1: // EscOrComment : LineOrBlock ∙

			if p.follow(symbols.NT_EscOrComment) {
				p.rtn(symbols.NT_EscOrComment, cU, p.cI)
			} else {
				p.parseError(slot.EscOrComment1R0, p.cI, followSets[symbols.NT_EscOrComment])
			}
		case slot.FALSE0R0: // FALSE : ∙false WS

			p.bsrSet.Add(slot.FALSE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.FALSE0R1) {
				p.parseError(slot.FALSE0R1, p.cI, first[slot.FALSE0R1])
				break
			}

			p.call(slot.FALSE0R2, cU, p.cI)
		case slot.FALSE0R2: // FALSE : false WS ∙

			if p.follow(symbols.NT_FALSE) {
				p.rtn(symbols.NT_FALSE, cU, p.cI)
			} else {
				p.parseError(slot.FALSE0R0, p.cI, followSets[symbols.NT_FALSE])
			}
		case slot.HEX0R0: // HEX : ∙Number aA_fF

			p.call(slot.HEX0R1, cU, p.cI)
		case slot.HEX0R1: // HEX : Number ∙aA_fF

			if !p.testSelect(slot.HEX0R1) {
				p.parseError(slot.HEX0R1, p.cI, first[slot.HEX0R1])
				break
			}

			p.bsrSet.Add(slot.HEX0R2, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_HEX) {
				p.rtn(symbols.NT_HEX, cU, p.cI)
			} else {
				p.parseError(slot.HEX0R0, p.cI, followSets[symbols.NT_HEX])
			}
		case slot.HEX1R0: // HEX : ∙
			p.bsrSet.AddEmpty(slot.HEX1R0, p.cI)

			if p.follow(symbols.NT_HEX) {
				p.rtn(symbols.NT_HEX, cU, p.cI)
			} else {
				p.parseError(slot.HEX1R0, p.cI, followSets[symbols.NT_HEX])
			}
		case slot.INT0R0: // INT : ∙optNeg Integers

			p.bsrSet.Add(slot.INT0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.INT0R1) {
				p.parseError(slot.INT0R1, p.cI, first[slot.INT0R1])
				break
			}

			p.call(slot.INT0R2, cU, p.cI)
		case slot.INT0R2: // INT : optNeg Integers ∙

			if p.follow(symbols.NT_INT) {
				p.rtn(symbols.NT_INT, cU, p.cI)
			} else {
				p.parseError(slot.INT0R0, p.cI, followSets[symbols.NT_INT])
			}
		case slot.Integers0R0: // Integers : ∙integer

			p.bsrSet.Add(slot.Integers0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_Integers) {
				p.rtn(symbols.NT_Integers, cU, p.cI)
			} else {
				p.parseError(slot.Integers0R0, p.cI, followSets[symbols.NT_Integers])
			}
		case slot.Integers1R0: // Integers : ∙zero

			p.bsrSet.Add(slot.Integers1R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_Integers) {
				p.rtn(symbols.NT_Integers, cU, p.cI)
			} else {
				p.parseError(slot.Integers1R0, p.cI, followSets[symbols.NT_Integers])
			}
		case slot.JSON0R0: // JSON : ∙WS Object

			p.call(slot.JSON0R1, cU, p.cI)
		case slot.JSON0R1: // JSON : WS ∙Object

			if !p.testSelect(slot.JSON0R1) {
				p.parseError(slot.JSON0R1, p.cI, first[slot.JSON0R1])
				break
			}

			p.call(slot.JSON0R2, cU, p.cI)
		case slot.JSON0R2: // JSON : WS Object ∙

			if p.follow(symbols.NT_JSON) {
				p.rtn(symbols.NT_JSON, cU, p.cI)
			} else {
				p.parseError(slot.JSON0R0, p.cI, followSets[symbols.NT_JSON])
			}
		case slot.LBRACE0R0: // LBRACE : ∙{ WS

			p.bsrSet.Add(slot.LBRACE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.LBRACE0R1) {
				p.parseError(slot.LBRACE0R1, p.cI, first[slot.LBRACE0R1])
				break
			}

			p.call(slot.LBRACE0R2, cU, p.cI)
		case slot.LBRACE0R2: // LBRACE : { WS ∙

			if p.follow(symbols.NT_LBRACE) {
				p.rtn(symbols.NT_LBRACE, cU, p.cI)
			} else {
				p.parseError(slot.LBRACE0R0, p.cI, followSets[symbols.NT_LBRACE])
			}
		case slot.LBRACKET0R0: // LBRACKET : ∙[ WS

			p.bsrSet.Add(slot.LBRACKET0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.LBRACKET0R1) {
				p.parseError(slot.LBRACKET0R1, p.cI, first[slot.LBRACKET0R1])
				break
			}

			p.call(slot.LBRACKET0R2, cU, p.cI)
		case slot.LBRACKET0R2: // LBRACKET : [ WS ∙

			if p.follow(symbols.NT_LBRACKET) {
				p.rtn(symbols.NT_LBRACKET, cU, p.cI)
			} else {
				p.parseError(slot.LBRACKET0R0, p.cI, followSets[symbols.NT_LBRACKET])
			}
		case slot.LineOrBlock0R0: // LineOrBlock : ∙line_comment

			p.bsrSet.Add(slot.LineOrBlock0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_LineOrBlock) {
				p.rtn(symbols.NT_LineOrBlock, cU, p.cI)
			} else {
				p.parseError(slot.LineOrBlock0R0, p.cI, followSets[symbols.NT_LineOrBlock])
			}
		case slot.LineOrBlock1R0: // LineOrBlock : ∙block_comment

			p.bsrSet.Add(slot.LineOrBlock1R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_LineOrBlock) {
				p.rtn(symbols.NT_LineOrBlock, cU, p.cI)
			} else {
				p.parseError(slot.LineOrBlock1R0, p.cI, followSets[symbols.NT_LineOrBlock])
			}
		case slot.Members0R0: // Members : ∙Pair ComPair0x

			p.call(slot.Members0R1, cU, p.cI)
		case slot.Members0R1: // Members : Pair ∙ComPair0x

			if !p.testSelect(slot.Members0R1) {
				p.parseError(slot.Members0R1, p.cI, first[slot.Members0R1])
				break
			}

			p.call(slot.Members0R2, cU, p.cI)
		case slot.Members0R2: // Members : Pair ComPair0x ∙

			if p.follow(symbols.NT_Members) {
				p.rtn(symbols.NT_Members, cU, p.cI)
			} else {
				p.parseError(slot.Members0R0, p.cI, followSets[symbols.NT_Members])
			}
		case slot.Mems0x0R0: // Mems0x : ∙Members Mems0x

			p.call(slot.Mems0x0R1, cU, p.cI)
		case slot.Mems0x0R1: // Mems0x : Members ∙Mems0x

			if !p.testSelect(slot.Mems0x0R1) {
				p.parseError(slot.Mems0x0R1, p.cI, first[slot.Mems0x0R1])
				break
			}

			p.call(slot.Mems0x0R2, cU, p.cI)
		case slot.Mems0x0R2: // Mems0x : Members Mems0x ∙

			if p.follow(symbols.NT_Mems0x) {
				p.rtn(symbols.NT_Mems0x, cU, p.cI)
			} else {
				p.parseError(slot.Mems0x0R0, p.cI, followSets[symbols.NT_Mems0x])
			}
		case slot.Mems0x1R0: // Mems0x : ∙
			p.bsrSet.AddEmpty(slot.Mems0x1R0, p.cI)

			if p.follow(symbols.NT_Mems0x) {
				p.rtn(symbols.NT_Mems0x, cU, p.cI)
			} else {
				p.parseError(slot.Mems0x1R0, p.cI, followSets[symbols.NT_Mems0x])
			}
		case slot.NUL0R0: // NUL : ∙null WS

			p.bsrSet.Add(slot.NUL0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.NUL0R1) {
				p.parseError(slot.NUL0R1, p.cI, first[slot.NUL0R1])
				break
			}

			p.call(slot.NUL0R2, cU, p.cI)
		case slot.NUL0R2: // NUL : null WS ∙

			if p.follow(symbols.NT_NUL) {
				p.rtn(symbols.NT_NUL, cU, p.cI)
			} else {
				p.parseError(slot.NUL0R0, p.cI, followSets[symbols.NT_NUL])
			}
		case slot.Number0R0: // Number : ∙INT OptFrac OptExp WS

			p.call(slot.Number0R1, cU, p.cI)
		case slot.Number0R1: // Number : INT ∙OptFrac OptExp WS

			if !p.testSelect(slot.Number0R1) {
				p.parseError(slot.Number0R1, p.cI, first[slot.Number0R1])
				break
			}

			p.call(slot.Number0R2, cU, p.cI)
		case slot.Number0R2: // Number : INT OptFrac ∙OptExp WS

			if !p.testSelect(slot.Number0R2) {
				p.parseError(slot.Number0R2, p.cI, first[slot.Number0R2])
				break
			}

			p.call(slot.Number0R3, cU, p.cI)
		case slot.Number0R3: // Number : INT OptFrac OptExp ∙WS

			if !p.testSelect(slot.Number0R3) {
				p.parseError(slot.Number0R3, p.cI, first[slot.Number0R3])
				break
			}

			p.call(slot.Number0R4, cU, p.cI)
		case slot.Number0R4: // Number : INT OptFrac OptExp WS ∙

			if p.follow(symbols.NT_Number) {
				p.rtn(symbols.NT_Number, cU, p.cI)
			} else {
				p.parseError(slot.Number0R0, p.cI, followSets[symbols.NT_Number])
			}
		case slot.Object0R0: // Object : ∙LBRACE Members Mems0x RBRACE

			p.call(slot.Object0R1, cU, p.cI)
		case slot.Object0R1: // Object : LBRACE ∙Members Mems0x RBRACE

			if !p.testSelect(slot.Object0R1) {
				p.parseError(slot.Object0R1, p.cI, first[slot.Object0R1])
				break
			}

			p.call(slot.Object0R2, cU, p.cI)
		case slot.Object0R2: // Object : LBRACE Members ∙Mems0x RBRACE

			if !p.testSelect(slot.Object0R2) {
				p.parseError(slot.Object0R2, p.cI, first[slot.Object0R2])
				break
			}

			p.call(slot.Object0R3, cU, p.cI)
		case slot.Object0R3: // Object : LBRACE Members Mems0x ∙RBRACE

			if !p.testSelect(slot.Object0R3) {
				p.parseError(slot.Object0R3, p.cI, first[slot.Object0R3])
				break
			}

			p.call(slot.Object0R4, cU, p.cI)
		case slot.Object0R4: // Object : LBRACE Members Mems0x RBRACE ∙

			if p.follow(symbols.NT_Object) {
				p.rtn(symbols.NT_Object, cU, p.cI)
			} else {
				p.parseError(slot.Object0R0, p.cI, followSets[symbols.NT_Object])
			}
		case slot.OptElem0R0: // OptElem : ∙Elements

			p.call(slot.OptElem0R1, cU, p.cI)
		case slot.OptElem0R1: // OptElem : Elements ∙

			if p.follow(symbols.NT_OptElem) {
				p.rtn(symbols.NT_OptElem, cU, p.cI)
			} else {
				p.parseError(slot.OptElem0R0, p.cI, followSets[symbols.NT_OptElem])
			}
		case slot.OptElem1R0: // OptElem : ∙
			p.bsrSet.AddEmpty(slot.OptElem1R0, p.cI)

			if p.follow(symbols.NT_OptElem) {
				p.rtn(symbols.NT_OptElem, cU, p.cI)
			} else {
				p.parseError(slot.OptElem1R0, p.cI, followSets[symbols.NT_OptElem])
			}
		case slot.OptExp0R0: // OptExp : ∙exp

			p.bsrSet.Add(slot.OptExp0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_OptExp) {
				p.rtn(symbols.NT_OptExp, cU, p.cI)
			} else {
				p.parseError(slot.OptExp0R0, p.cI, followSets[symbols.NT_OptExp])
			}
		case slot.OptExp1R0: // OptExp : ∙
			p.bsrSet.AddEmpty(slot.OptExp1R0, p.cI)

			if p.follow(symbols.NT_OptExp) {
				p.rtn(symbols.NT_OptExp, cU, p.cI)
			} else {
				p.parseError(slot.OptExp1R0, p.cI, followSets[symbols.NT_OptExp])
			}
		case slot.OptFrac0R0: // OptFrac : ∙frac

			p.bsrSet.Add(slot.OptFrac0R1, cU, p.cI, p.cI+1)
			p.cI++
			if p.follow(symbols.NT_OptFrac) {
				p.rtn(symbols.NT_OptFrac, cU, p.cI)
			} else {
				p.parseError(slot.OptFrac0R0, p.cI, followSets[symbols.NT_OptFrac])
			}
		case slot.OptFrac1R0: // OptFrac : ∙
			p.bsrSet.AddEmpty(slot.OptFrac1R0, p.cI)

			if p.follow(symbols.NT_OptFrac) {
				p.rtn(symbols.NT_OptFrac, cU, p.cI)
			} else {
				p.parseError(slot.OptFrac1R0, p.cI, followSets[symbols.NT_OptFrac])
			}
		case slot.Pair0R0: // Pair : ∙String COLON Value

			p.call(slot.Pair0R1, cU, p.cI)
		case slot.Pair0R1: // Pair : String ∙COLON Value

			if !p.testSelect(slot.Pair0R1) {
				p.parseError(slot.Pair0R1, p.cI, first[slot.Pair0R1])
				break
			}

			p.call(slot.Pair0R2, cU, p.cI)
		case slot.Pair0R2: // Pair : String COLON ∙Value

			if !p.testSelect(slot.Pair0R2) {
				p.parseError(slot.Pair0R2, p.cI, first[slot.Pair0R2])
				break
			}

			p.call(slot.Pair0R3, cU, p.cI)
		case slot.Pair0R3: // Pair : String COLON Value ∙

			if p.follow(symbols.NT_Pair) {
				p.rtn(symbols.NT_Pair, cU, p.cI)
			} else {
				p.parseError(slot.Pair0R0, p.cI, followSets[symbols.NT_Pair])
			}
		case slot.RBRACE0R0: // RBRACE : ∙} WS

			p.bsrSet.Add(slot.RBRACE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.RBRACE0R1) {
				p.parseError(slot.RBRACE0R1, p.cI, first[slot.RBRACE0R1])
				break
			}

			p.call(slot.RBRACE0R2, cU, p.cI)
		case slot.RBRACE0R2: // RBRACE : } WS ∙

			if p.follow(symbols.NT_RBRACE) {
				p.rtn(symbols.NT_RBRACE, cU, p.cI)
			} else {
				p.parseError(slot.RBRACE0R0, p.cI, followSets[symbols.NT_RBRACE])
			}
		case slot.RBRACKET0R0: // RBRACKET : ∙] WS

			p.bsrSet.Add(slot.RBRACKET0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.RBRACKET0R1) {
				p.parseError(slot.RBRACKET0R1, p.cI, first[slot.RBRACKET0R1])
				break
			}

			p.call(slot.RBRACKET0R2, cU, p.cI)
		case slot.RBRACKET0R2: // RBRACKET : ] WS ∙

			if p.follow(symbols.NT_RBRACKET) {
				p.rtn(symbols.NT_RBRACKET, cU, p.cI)
			} else {
				p.parseError(slot.RBRACKET0R0, p.cI, followSets[symbols.NT_RBRACKET])
			}
		case slot.String0R0: // String : ∙dQuote Close WS

			p.bsrSet.Add(slot.String0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.String0R1) {
				p.parseError(slot.String0R1, p.cI, first[slot.String0R1])
				break
			}

			p.call(slot.String0R2, cU, p.cI)
		case slot.String0R2: // String : dQuote Close ∙WS

			if !p.testSelect(slot.String0R2) {
				p.parseError(slot.String0R2, p.cI, first[slot.String0R2])
				break
			}

			p.call(slot.String0R3, cU, p.cI)
		case slot.String0R3: // String : dQuote Close WS ∙

			if p.follow(symbols.NT_String) {
				p.rtn(symbols.NT_String, cU, p.cI)
			} else {
				p.parseError(slot.String0R0, p.cI, followSets[symbols.NT_String])
			}
		case slot.TRUE0R0: // TRUE : ∙true WS

			p.bsrSet.Add(slot.TRUE0R1, cU, p.cI, p.cI+1)
			p.cI++
			if !p.testSelect(slot.TRUE0R1) {
				p.parseError(slot.TRUE0R1, p.cI, first[slot.TRUE0R1])
				break
			}

			p.call(slot.TRUE0R2, cU, p.cI)
		case slot.TRUE0R2: // TRUE : true WS ∙

			if p.follow(symbols.NT_TRUE) {
				p.rtn(symbols.NT_TRUE, cU, p.cI)
			} else {
				p.parseError(slot.TRUE0R0, p.cI, followSets[symbols.NT_TRUE])
			}
		case slot.Value0R0: // Value : ∙String

			p.call(slot.Value0R1, cU, p.cI)
		case slot.Value0R1: // Value : String ∙

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value0R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value1R0: // Value : ∙Number

			p.call(slot.Value1R1, cU, p.cI)
		case slot.Value1R1: // Value : Number ∙

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value1R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value2R0: // Value : ∙Object

			p.call(slot.Value2R1, cU, p.cI)
		case slot.Value2R1: // Value : Object ∙

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value2R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value3R0: // Value : ∙Array

			p.call(slot.Value3R1, cU, p.cI)
		case slot.Value3R1: // Value : Array ∙

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value3R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value4R0: // Value : ∙TRUE

			p.call(slot.Value4R1, cU, p.cI)
		case slot.Value4R1: // Value : TRUE ∙

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value4R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value5R0: // Value : ∙FALSE

			p.call(slot.Value5R1, cU, p.cI)
		case slot.Value5R1: // Value : FALSE ∙

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value5R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.Value6R0: // Value : ∙NUL

			p.call(slot.Value6R1, cU, p.cI)
		case slot.Value6R1: // Value : NUL ∙

			if p.follow(symbols.NT_Value) {
				p.rtn(symbols.NT_Value, cU, p.cI)
			} else {
				p.parseError(slot.Value6R0, p.cI, followSets[symbols.NT_Value])
			}
		case slot.WS0R0: // WS : ∙EscOrComment WS

			p.call(slot.WS0R1, cU, p.cI)
		case slot.WS0R1: // WS : EscOrComment ∙WS

			if !p.testSelect(slot.WS0R1) {
				p.parseError(slot.WS0R1, p.cI, first[slot.WS0R1])
				break
			}

			p.call(slot.WS0R2, cU, p.cI)
		case slot.WS0R2: // WS : EscOrComment WS ∙

			if p.follow(symbols.NT_WS) {
				p.rtn(symbols.NT_WS, cU, p.cI)
			} else {
				p.parseError(slot.WS0R0, p.cI, followSets[symbols.NT_WS])
			}
		case slot.WS1R0: // WS : ∙
			p.bsrSet.AddEmpty(slot.WS1R0, p.cI)

			if p.follow(symbols.NT_WS) {
				p.rtn(symbols.NT_WS, cU, p.cI)
			} else {
				p.parseError(slot.WS1R0, p.cI, followSets[symbols.NT_WS])
			}

		default:
			panic("This must not happen")
		}
	}
	if !p.bsrSet.Contain(symbols.NT_JSON, 0, m) {
		p.sortParseErrors()
		return nil, p.parseErrors
	}
	return p.bsrSet, nil
}

func (p *parser) ntAdd(nt symbols.NT, j int) {
	// fmt.Printf("p.ntAdd(%s, %d)\n", nt, j)
	failed := true
	expected := map[token.Type]string{}
	for _, l := range slot.GetAlternates(nt) {
		if p.testSelect(l) {
			p.dscAdd(l, j, j)
			failed = false
		} else {
			for k, v := range first[l] {
				expected[k] = v
			}
		}
	}
	if failed {
		for _, l := range slot.GetAlternates(nt) {
			p.parseError(l, j, expected)
		}
	}
}

/*** Call Return Forest ***/

type poppedNode struct {
	X    symbols.NT
	k, j int
}

type clusterNode struct {
	X symbols.NT
	k int
}

type crfNode struct {
	L slot.Label
	i int
}

/*
suppose that L is Y ::=αX ·β
if there is no CRF node labelled (L,i)
	create one let u be the CRF node labelled (L,i)
if there is no CRF node labelled (X, j) {
	create a CRF node v labelled (X, j)
	create an edge from v to u
	ntAdd(X, j)
} else {
	let v be the CRF node labelled (X, j)
	if there is not an edge from v to u {
		create an edge from v to u
		for all ((X, j,h)∈P) {
			dscAdd(L, i, h);
			bsrAdd(L, i, j, h)
		}
	}
}
*/
func (p *parser) call(L slot.Label, i, j int) {
	// fmt.Printf("p.call(%s,%d,%d)\n", L,i,j)
	u, exist := p.crfNodes[crfNode{L, i}]
	// fmt.Printf("  u exist=%t\n", exist)
	if !exist {
		u = &crfNode{L, i}
		p.crfNodes[*u] = u
	}
	X := L.Symbols()[L.Pos()-1].(symbols.NT)
	ndV := clusterNode{X, j}
	v, exist := p.crf[ndV]
	if !exist {
		// fmt.Println("  v !exist")
		p.crf[ndV] = []*crfNode{u}
		p.ntAdd(X, j)
	} else {
		// fmt.Println("  v exist")
		if !existEdge(v, u) {
			// fmt.Printf("  !existEdge(%v)\n", u)
			p.crf[ndV] = append(v, u)
			// fmt.Printf("|popped|=%d\n", len(popped))
			for pnd := range p.popped {
				if pnd.X == X && pnd.k == j {
					p.dscAdd(L, i, pnd.j)
					p.bsrSet.Add(L, i, j, pnd.j)
				}
			}
		}
	}
}

func existEdge(nds []*crfNode, nd *crfNode) bool {
	for _, nd1 := range nds {
		if nd1 == nd {
			return true
		}
	}
	return false
}

func (p *parser) rtn(X symbols.NT, k, j int) {
	// fmt.Printf("p.rtn(%s,%d,%d)\n", X,k,j)
	pn := poppedNode{X, k, j}
	if _, exist := p.popped[pn]; !exist {
		p.popped[pn] = true
		for _, nd := range p.crf[clusterNode{X, k}] {
			p.dscAdd(nd.L, nd.i, j)
			p.bsrSet.Add(nd.L, nd.i, k, j)
		}
	}
}

// func CRFString() string {
// 	buf := new(bytes.Buffer)
// 	buf.WriteString("CRF: {")
// 	for cn, nds := range crf{
// 		for _, nd := range nds {
// 			fmt.Fprintf(buf, "%s->%s, ", cn, nd)
// 		}
// 	}
// 	buf.WriteString("}")
// 	return buf.String()
// }

func (cn clusterNode) String() string {
	return fmt.Sprintf("(%s,%d)", cn.X, cn.k)
}

func (n crfNode) String() string {
	return fmt.Sprintf("(%s,%d)", n.L.String(), n.i)
}

// func PoppedString() string {
// 	buf := new(bytes.Buffer)
// 	buf.WriteString("Popped: {")
// 	for p, _ := range popped {
// 		fmt.Fprintf(buf, "(%s,%d,%d) ", p.X, p.k, p.j)
// 	}
// 	buf.WriteString("}")
// 	return buf.String()
// }

/*** descriptors ***/

type descriptors struct {
	set []*descriptor
}

func (ds *descriptors) contain(d *descriptor) bool {
	for _, d1 := range ds.set {
		if d1 == d {
			return true
		}
	}
	return false
}

func (ds *descriptors) empty() bool {
	return len(ds.set) == 0
}

func (ds *descriptors) String() string {
	buf := new(bytes.Buffer)
	buf.WriteString("{")
	for i, d := range ds.set {
		if i > 0 {
			buf.WriteString("; ")
		}
		fmt.Fprintf(buf, "%s", d)
	}
	buf.WriteString("}")
	return buf.String()
}

type descriptor struct {
	L slot.Label
	k int
	i int
}

func (d *descriptor) String() string {
	return fmt.Sprintf("%s,%d,%d", d.L, d.k, d.i)
}

func (p *parser) dscAdd(L slot.Label, k, i int) {
	// fmt.Printf("p.dscAdd(%s,%d,%d)\n", L, k, i)
	d := &descriptor{L, k, i}
	if !p.U.contain(d) {
		p.R.set = append(p.R.set, d)
		p.U.set = append(p.U.set, d)
	}
}

func (ds *descriptors) remove() (L slot.Label, k, i int) {
	d := ds.set[len(ds.set)-1]
	ds.set = ds.set[:len(ds.set)-1]
	// fmt.Printf("remove: %s,%d,%d\n", d.L, d.k, d.i)
	return d.L, d.k, d.i
}

func (p *parser) DumpDescriptors() {
	p.DumpR()
	p.DumpU()
}

func (p *parser) DumpR() {
	fmt.Println("R:")
	for _, d := range p.R.set {
		fmt.Printf(" %s\n", d)
	}
}

func (p *parser) DumpU() {
	fmt.Println("U:")
	for _, d := range p.U.set {
		fmt.Printf(" %s\n", d)
	}
}

/*** TestSelect ***/

func (p *parser) follow(nt symbols.NT) bool {
	_, exist := followSets[nt][p.lex.Tokens[p.cI].Type()]
	return exist
}

func (p *parser) testSelect(l slot.Label) bool {
	_, exist := first[l][p.lex.Tokens[p.cI].Type()]
	// fmt.Printf("testSelect(%s) = %t\n", l, exist)
	return exist
}

var first = []map[token.Type]string{
	// Array : ∙LBRACKET OptElem RBRACKET
	{
		token.T_2: "[",
	},
	// Array : LBRACKET ∙OptElem RBRACKET
	{
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// Array : LBRACKET OptElem ∙RBRACKET
	{
		token.T_3: "]",
	},
	// Array : LBRACKET OptElem RBRACKET ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// CHAR : ∙carrotSlash
	{
		token.T_7: "carrotSlash",
	},
	// CHAR : carrotSlash ∙
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// CHAR : ∙bSlash CharCode
	{
		token.T_5: "bSlash",
	},
	// CHAR : bSlash ∙CharCode
	{
		token.T_9:  "esc",
		token.T_21: "u",
	},
	// CHAR : bSlash CharCode ∙
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// COLON : ∙: WS
	{
		token.T_1: ":",
	},
	// COLON : : ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// COLON : : WS ∙
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// COMMA : ∙, WS
	{
		token.T_0: ",",
	},
	// COMMA : , ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// COMMA : , WS ∙
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// CharCode : ∙esc
	{
		token.T_9: "esc",
	},
	// CharCode : esc ∙
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// CharCode : ∙u HEX HEX HEX HEX
	{
		token.T_21: "u",
	},
	// CharCode : u ∙HEX HEX HEX HEX
	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},
	// CharCode : u HEX ∙HEX HEX HEX
	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},
	// CharCode : u HEX HEX ∙HEX HEX
	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},
	// CharCode : u HEX HEX HEX ∙HEX
	{
		token.T_19: "optNeg",
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
	},
	// CharCode : u HEX HEX HEX HEX ∙
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// Close : ∙dQuote
	{
		token.T_8: "dQuote",
	},
	// Close : dQuote ∙
	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// Close : ∙CHAR Close
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
	},
	// Close : CHAR ∙Close
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// Close : CHAR Close ∙
	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// ComPair0x : ∙COMMA Pair ComPair0x
	{
		token.T_0: ",",
	},
	// ComPair0x : COMMA ∙Pair ComPair0x
	{
		token.T_8: "dQuote",
	},
	// ComPair0x : COMMA Pair ∙ComPair0x
	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// ComPair0x : COMMA Pair ComPair0x ∙
	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// ComPair0x : ∙
	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// ComVal0x : ∙COMMA Value ComVal0x
	{
		token.T_0: ",",
	},
	// ComVal0x : COMMA ∙Value ComVal0x
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// ComVal0x : COMMA Value ∙ComVal0x
	{
		token.T_0: ",",
		token.T_3: "]",
	},
	// ComVal0x : COMMA Value ComVal0x ∙
	{
		token.T_3: "]",
	},
	// ComVal0x : ∙
	{
		token.T_3: "]",
	},
	// Elements : ∙Value ComVal0x
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// Elements : Value ∙ComVal0x
	{
		token.T_0: ",",
		token.T_3: "]",
	},
	// Elements : Value ComVal0x ∙
	{
		token.T_3: "]",
	},
	// EscOrComment : ∙escChar
	{
		token.T_10: "escChar",
	},
	// EscOrComment : escChar ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// EscOrComment : ∙LineOrBlock
	{
		token.T_6:  "block_comment",
		token.T_16: "line_comment",
	},
	// EscOrComment : LineOrBlock ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// FALSE : ∙false WS
	{
		token.T_13: "false",
	},
	// FALSE : false ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// FALSE : false WS ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// HEX : ∙Number aA_fF
	{
		token.T_19: "optNeg",
	},
	// HEX : Number ∙aA_fF
	{
		token.T_4: "aA_fF",
	},
	// HEX : Number aA_fF ∙
	{
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
		token.T_19: "optNeg",
	},
	// HEX : ∙
	{
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
		token.T_19: "optNeg",
	},
	// INT : ∙optNeg Integers
	{
		token.T_19: "optNeg",
	},
	// INT : optNeg ∙Integers
	{
		token.T_15: "integer",
		token.T_22: "zero",
	},
	// INT : optNeg Integers ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// Integers : ∙integer
	{
		token.T_15: "integer",
	},
	// Integers : integer ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// Integers : ∙zero
	{
		token.T_22: "zero",
	},
	// Integers : zero ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// JSON : ∙WS Object
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_23: "{",
	},
	// JSON : WS ∙Object
	{
		token.T_23: "{",
	},
	// JSON : WS Object ∙
	{
		token.EOF: "$",
	},
	// LBRACE : ∙{ WS
	{
		token.T_23: "{",
	},
	// LBRACE : { ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_8:  "dQuote",
	},
	// LBRACE : { WS ∙
	{
		token.T_8: "dQuote",
	},
	// LBRACKET : ∙[ WS
	{
		token.T_2: "[",
	},
	// LBRACKET : [ ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// LBRACKET : [ WS ∙
	{
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// LineOrBlock : ∙line_comment
	{
		token.T_16: "line_comment",
	},
	// LineOrBlock : line_comment ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// LineOrBlock : ∙block_comment
	{
		token.T_6: "block_comment",
	},
	// LineOrBlock : block_comment ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// Members : ∙Pair ComPair0x
	{
		token.T_8: "dQuote",
	},
	// Members : Pair ∙ComPair0x
	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Members : Pair ComPair0x ∙
	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Mems0x : ∙Members Mems0x
	{
		token.T_8: "dQuote",
	},
	// Mems0x : Members ∙Mems0x
	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Mems0x : Members Mems0x ∙
	{
		token.T_24: "}",
	},
	// Mems0x : ∙
	{
		token.T_24: "}",
	},
	// NUL : ∙null WS
	{
		token.T_18: "null",
	},
	// NUL : null ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// NUL : null WS ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Number : ∙INT OptFrac OptExp WS
	{
		token.T_19: "optNeg",
	},
	// Number : INT ∙OptFrac OptExp WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Number : INT OptFrac ∙OptExp WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Number : INT OptFrac OptExp ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Number : INT OptFrac OptExp WS ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Object : ∙LBRACE Members Mems0x RBRACE
	{
		token.T_23: "{",
	},
	// Object : LBRACE ∙Members Mems0x RBRACE
	{
		token.T_8: "dQuote",
	},
	// Object : LBRACE Members ∙Mems0x RBRACE
	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Object : LBRACE Members Mems0x ∙RBRACE
	{
		token.T_24: "}",
	},
	// Object : LBRACE Members Mems0x RBRACE ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// OptElem : ∙Elements
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// OptElem : Elements ∙
	{
		token.T_3: "]",
	},
	// OptElem : ∙
	{
		token.T_3: "]",
	},
	// OptExp : ∙exp
	{
		token.T_12: "exp",
	},
	// OptExp : exp ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// OptExp : ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// OptFrac : ∙frac
	{
		token.T_14: "frac",
	},
	// OptFrac : frac ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// OptFrac : ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// Pair : ∙String COLON Value
	{
		token.T_8: "dQuote",
	},
	// Pair : String ∙COLON Value
	{
		token.T_1: ":",
	},
	// Pair : String COLON ∙Value
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// Pair : String COLON Value ∙
	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// RBRACE : ∙} WS
	{
		token.T_24: "}",
	},
	// RBRACE : } ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// RBRACE : } WS ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// RBRACKET : ∙] WS
	{
		token.T_3: "]",
	},
	// RBRACKET : ] ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// RBRACKET : ] WS ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// String : ∙dQuote Close WS
	{
		token.T_8: "dQuote",
	},
	// String : dQuote ∙Close WS
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// String : dQuote Close ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// String : dQuote Close WS ∙
	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// TRUE : ∙true WS
	{
		token.T_20: "true",
	},
	// TRUE : true ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// TRUE : true WS ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value : ∙String
	{
		token.T_8: "dQuote",
	},
	// Value : String ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value : ∙Number
	{
		token.T_19: "optNeg",
	},
	// Value : Number ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value : ∙Object
	{
		token.T_23: "{",
	},
	// Value : Object ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value : ∙Array
	{
		token.T_2: "[",
	},
	// Value : Array ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value : ∙TRUE
	{
		token.T_20: "true",
	},
	// Value : TRUE ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value : ∙FALSE
	{
		token.T_13: "false",
	},
	// Value : FALSE ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value : ∙NUL
	{
		token.T_18: "null",
	},
	// Value : NUL ∙
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// WS : ∙EscOrComment WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
	},
	// WS : EscOrComment ∙WS
	{
		token.T_6:  "block_comment",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// WS : EscOrComment WS ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// WS : ∙
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
}

var followSets = []map[token.Type]string{
	// Array
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// CHAR
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// COLON
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// COMMA
	{
		token.T_2:  "[",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// CharCode
	{
		token.T_5: "bSlash",
		token.T_7: "carrotSlash",
		token.T_8: "dQuote",
	},
	// Close
	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// ComPair0x
	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// ComVal0x
	{
		token.T_3: "]",
	},
	// Elements
	{
		token.T_3: "]",
	},
	// EscOrComment
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// FALSE
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// HEX
	{
		token.T_5:  "bSlash",
		token.T_7:  "carrotSlash",
		token.T_8:  "dQuote",
		token.T_19: "optNeg",
	},
	// INT
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// Integers
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_14: "frac",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// JSON
	{
		token.EOF: "$",
	},
	// LBRACE
	{
		token.T_8: "dQuote",
	},
	// LBRACKET
	{
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
	},
	// LineOrBlock
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_13: "false",
		token.T_16: "line_comment",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
	// Members
	{
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Mems0x
	{
		token.T_24: "}",
	},
	// NUL
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Number
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Object
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// OptElem
	{
		token.T_3: "]",
	},
	// OptExp
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// OptFrac
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_6:  "block_comment",
		token.T_8:  "dQuote",
		token.T_10: "escChar",
		token.T_12: "exp",
		token.T_16: "line_comment",
		token.T_24: "}",
	},
	// Pair
	{
		token.T_0:  ",",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// RBRACE
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// RBRACKET
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// String
	{
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// TRUE
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// Value
	{
		token.T_0:  ",",
		token.T_3:  "]",
		token.T_8:  "dQuote",
		token.T_24: "}",
	},
	// WS
	{
		token.EOF:  "$",
		token.T_0:  ",",
		token.T_1:  ":",
		token.T_2:  "[",
		token.T_3:  "]",
		token.T_4:  "aA_fF",
		token.T_8:  "dQuote",
		token.T_13: "false",
		token.T_18: "null",
		token.T_19: "optNeg",
		token.T_20: "true",
		token.T_23: "{",
		token.T_24: "}",
	},
}

/*** Errors ***/

/*
Error is returned by Parse at every point at which the parser fails to parse
a grammar production. For non-LL-1 grammars there will be an error for each
alternate attempted by the parser.

The errors are sorted in descending order of input position (index of token in
the stream of tokens).

Normally the error of interest is the one that has parsed the largest number of
tokens.
*/
type Error struct {
	// Index of token that caused the error.
	cI int

	// Grammar slot at which the error occured.
	Slot slot.Label

	// The token at which the error occurred.
	Token *token.Token

	// The line and column in the input text at which the error occurred
	Line, Column int

	// The tokens expected at the point where the error occurred
	Expected map[token.Type]string
}

func (pe *Error) String() string {
	w := new(bytes.Buffer)
	fmt.Fprintf(w, "Parse Error: %s I[%d]=%s at line %d col %d\n",
		pe.Slot, pe.cI, pe.Token, pe.Line, pe.Column)
	exp := []string{}
	for _, e := range pe.Expected {
		exp = append(exp, e)
	}
	fmt.Fprintf(w, "Expected one of: [%s]", strings.Join(exp, ","))
	return w.String()
}

func (p *parser) parseError(slot slot.Label, i int, expected map[token.Type]string) {
	pe := &Error{cI: i, Slot: slot, Token: p.lex.Tokens[i], Expected: expected}
	p.parseErrors = append(p.parseErrors, pe)
}

func (p *parser) sortParseErrors() {
	sort.Slice(p.parseErrors,
		func(i, j int) bool {
			return p.parseErrors[j].Token.Lext() < p.parseErrors[i].Token.Lext()
		})
	for _, pe := range p.parseErrors {
		pe.Line, pe.Column = p.lex.GetLineColumn(pe.Token.Lext())
	}
}
