wand/iniparser.gen.go

824 lines
30 KiB
Go
Raw Normal View History

2025-09-01 02:07:48 +02:00
/*
This file was generated with treerack (https://code.squareroundforest.org/arpio/treerack).
The contents of this file fall under different licenses.
The code between the "// head" and "// eo head" lines falls under the same
license as the source code of treerack (https://code.squareroundforest.org/arpio/treerack),
unless explicitly stated otherwise, if treerack's license allows changing the
license of this source code.
Treerack's license: MIT https://opensource.org/licenses/MIT
where YEAR=2017, COPYRIGHT HOLDER=Arpad Ryszka (arpad.ryszka@gmail.com)
The rest of the content of this file falls under the same license as the one
that the user of treerack generating this file declares for it, or it is
unlicensed.
*/
2025-09-01 02:07:48 +02:00
package wand
// head
import (
"strconv"
2025-09-01 02:07:48 +02:00
"io"
"strings"
"unicode"
2025-09-01 02:07:48 +02:00
"fmt"
"bufio"
"errors"
)
type charParser struct {
2025-09-01 02:07:48 +02:00
name string
id int
not bool
chars []rune
ranges [][]rune
}
type charBuilder struct {
2025-09-01 02:07:48 +02:00
name string
id int
}
func (p *charParser) nodeName() string {
return p.name
}
func (p *charParser) nodeID() int {
return p.id
}
func (p *charParser) commitType() commitType {
return alias
}
func matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {
for _, ci := range chars {
if ci == char {
return !not
}
}
for _, ri := range ranges {
if char >= ri[0] && char <= ri[1] {
return !not
}
}
return not
}
func (p *charParser) match(t rune) bool {
return matchChar(p.chars, p.ranges, p.not, t)
}
func (p *charParser) parse(c *context) {
if tok, ok := c.token(); !ok || !p.match(tok) {
if c.offset > c.failOffset {
c.failOffset = c.offset
c.failingParser = nil
}
c.fail(c.offset)
return
}
c.success(c.offset + 1)
}
func (b *charBuilder) nodeName() string {
return b.name
}
func (b *charBuilder) nodeID() int {
return b.id
}
func (b *charBuilder) build(c *context) ([]*node, bool) {
return nil, false
}
type sequenceParser struct {
2025-09-01 02:07:48 +02:00
name string
id int
commit commitType
items []parser
ranges [][]int
generalizations []int
allChars bool
}
type sequenceBuilder struct {
2025-09-01 02:07:48 +02:00
name string
id int
commit commitType
items []builder
ranges [][]int
generalizations []int
allChars bool
}
func (p *sequenceParser) nodeName() string {
return p.name
}
func (p *sequenceParser) nodeID() int {
return p.id
}
func (p *sequenceParser) commitType() commitType {
return p.commit
}
func (p *sequenceParser) parse(c *context) {
if !p.allChars {
if c.results.pending(c.offset, p.id) {
c.fail(c.offset)
return
}
c.results.markPending(c.offset, p.id)
}
var (
2025-09-01 02:07:48 +02:00
currentCount int
parsed bool
)
itemIndex := 0
from := c.offset
to := c.offset
for itemIndex < len(p.items) {
p.items[itemIndex].parse(c)
if !c.matchLast {
if currentCount >= p.ranges[itemIndex][0] {
itemIndex++
currentCount = 0
continue
}
c.offset = from
if c.fromResults(p) {
if to > c.failOffset {
c.failOffset = -1
c.failingParser = nil
}
if !p.allChars {
c.results.unmarkPending(from, p.id)
}
return
}
if c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {
c.failingParser = p
}
c.fail(from)
if !p.allChars {
c.results.unmarkPending(from, p.id)
}
return
}
parsed = c.offset > to
if parsed {
currentCount++
}
to = c.offset
if !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {
itemIndex++
currentCount = 0
}
}
if p.commit&noKeyword != 0 && c.isKeyword(from, to) {
if c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {
c.failingParser = p
}
c.fail(from)
if !p.allChars {
c.results.unmarkPending(from, p.id)
}
return
}
for _, g := range p.generalizations {
if c.results.pending(from, g) {
c.results.setMatch(from, g, to)
}
}
if to > c.failOffset {
c.failOffset = -1
c.failingParser = nil
}
c.results.setMatch(from, p.id, to)
c.success(to)
if !p.allChars {
c.results.unmarkPending(from, p.id)
}
}
func (b *sequenceBuilder) nodeName() string {
return b.name
}
func (b *sequenceBuilder) nodeID() int {
return b.id
}
func (b *sequenceBuilder) build(c *context) ([]*node, bool) {
to, ok := c.results.longestMatch(c.offset, b.id)
if !ok {
return nil, false
}
from := c.offset
parsed := to > from
if b.allChars {
c.offset = to
if b.commit&alias != 0 {
return nil, true
}
return []*node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true
} else if parsed {
c.results.dropMatchTo(c.offset, b.id, to)
for _, g := range b.generalizations {
c.results.dropMatchTo(c.offset, g, to)
}
} else {
if c.results.pending(c.offset, b.id) {
return nil, false
}
c.results.markPending(c.offset, b.id)
for _, g := range b.generalizations {
c.results.markPending(c.offset, g)
}
}
var (
2025-09-01 02:07:48 +02:00
itemIndex int
currentCount int
nodes []*node
)
for itemIndex < len(b.items) {
itemFrom := c.offset
n, ok := b.items[itemIndex].build(c)
if !ok {
itemIndex++
currentCount = 0
continue
}
if c.offset > itemFrom {
nodes = append(nodes, n...)
currentCount++
if b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {
itemIndex++
currentCount = 0
}
continue
}
if currentCount < b.ranges[itemIndex][0] {
for i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {
nodes = append(nodes, n...)
}
}
itemIndex++
currentCount = 0
}
if !parsed {
c.results.unmarkPending(from, b.id)
for _, g := range b.generalizations {
c.results.unmarkPending(from, g)
}
}
if b.commit&alias != 0 {
return nodes, true
}
return []*node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true
}
type choiceParser struct {
2025-09-01 02:07:48 +02:00
name string
id int
commit commitType
options []parser
generalizations []int
}
type choiceBuilder struct {
2025-09-01 02:07:48 +02:00
name string
id int
commit commitType
options []builder
generalizations []int
}
func (p *choiceParser) nodeName() string {
return p.name
}
func (p *choiceParser) nodeID() int {
return p.id
}
func (p *choiceParser) commitType() commitType {
return p.commit
}
func (p *choiceParser) parse(c *context) {
if c.fromResults(p) {
return
}
if c.results.pending(c.offset, p.id) {
c.fail(c.offset)
return
}
c.results.markPending(c.offset, p.id)
var (
2025-09-01 02:07:48 +02:00
match bool
optionIndex int
foundMatch bool
failingParser parser
)
from := c.offset
to := c.offset
initialFailOffset := c.failOffset
initialFailingParser := c.failingParser
failOffset := initialFailOffset
for {
foundMatch = false
optionIndex = 0
for optionIndex < len(p.options) {
p.options[optionIndex].parse(c)
optionIndex++
if !c.matchLast {
if c.failOffset > failOffset {
failOffset = c.failOffset
failingParser = c.failingParser
}
}
if !c.matchLast || match && c.offset <= to {
c.offset = from
continue
}
match = true
foundMatch = true
to = c.offset
c.offset = from
c.results.setMatch(from, p.id, to)
}
if !foundMatch {
break
}
}
if match {
if p.commit&noKeyword != 0 && c.isKeyword(from, to) {
if c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {
c.failingParser = p
}
c.fail(from)
c.results.unmarkPending(from, p.id)
return
}
if failOffset > to {
c.failOffset = failOffset
c.failingParser = failingParser
} else if to > initialFailOffset {
c.failOffset = -1
c.failingParser = nil
} else {
c.failOffset = initialFailOffset
c.failingParser = initialFailingParser
}
c.success(to)
c.results.unmarkPending(from, p.id)
return
}
if failOffset > initialFailOffset {
c.failOffset = failOffset
c.failingParser = failingParser
if c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&whitespace == 0 && p.commitType()&failPass == 0 {
c.failingParser = p
}
}
c.results.setNoMatch(from, p.id)
c.fail(from)
c.results.unmarkPending(from, p.id)
}
func (b *choiceBuilder) nodeName() string {
return b.name
}
func (b *choiceBuilder) nodeID() int {
return b.id
}
func (b *choiceBuilder) build(c *context) ([]*node, bool) {
to, ok := c.results.longestMatch(c.offset, b.id)
if !ok {
return nil, false
}
from := c.offset
parsed := to > from
if parsed {
c.results.dropMatchTo(c.offset, b.id, to)
for _, g := range b.generalizations {
c.results.dropMatchTo(c.offset, g, to)
}
} else {
if c.results.pending(c.offset, b.id) {
return nil, false
}
c.results.markPending(c.offset, b.id)
for _, g := range b.generalizations {
c.results.markPending(c.offset, g)
}
}
var option builder
for _, o := range b.options {
if c.results.hasMatchTo(c.offset, o.nodeID(), to) {
option = o
break
}
}
n, _ := option.build(c)
if !parsed {
c.results.unmarkPending(from, b.id)
for _, g := range b.generalizations {
c.results.unmarkPending(from, g)
}
}
if b.commit&alias != 0 {
return n, true
}
return []*node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true
}
type idSet struct{ ids []uint }
func divModBits(id int) (int, int) {
return id / strconv.IntSize, id % strconv.IntSize
}
func (s *idSet) set(id int) {
d, m := divModBits(id)
if d >= len(s.ids) {
if d < cap(s.ids) {
s.ids = s.ids[:d+1]
} else {
s.ids = s.ids[:cap(s.ids)]
for i := cap(s.ids); i <= d; i++ {
s.ids = append(s.ids, 0)
}
}
}
s.ids[d] |= 1 << uint(m)
}
func (s *idSet) unset(id int) {
d, m := divModBits(id)
if d >= len(s.ids) {
return
}
s.ids[d] &^= 1 << uint(m)
}
func (s *idSet) has(id int) bool {
d, m := divModBits(id)
if d >= len(s.ids) {
return false
}
return s.ids[d]&(1<<uint(m)) != 0
}
type results struct {
2025-09-01 02:07:48 +02:00
noMatch []*idSet
match [][]int
isPending [][]int
}
func ensureOffsetInts(ints [][]int, offset int) [][]int {
if len(ints) > offset {
return ints
}
if cap(ints) > offset {
ints = ints[:offset+1]
return ints
}
ints = ints[:cap(ints)]
for i := len(ints); i <= offset; i++ {
ints = append(ints, nil)
}
return ints
}
func ensureOffsetIDs(ids []*idSet, offset int) []*idSet {
if len(ids) > offset {
return ids
}
if cap(ids) > offset {
ids = ids[:offset+1]
return ids
}
ids = ids[:cap(ids)]
for i := len(ids); i <= offset; i++ {
ids = append(ids, nil)
}
return ids
}
func (r *results) setMatch(offset, id, to int) {
r.match = ensureOffsetInts(r.match, offset)
for i := 0; i < len(r.match[offset]); i += 2 {
if r.match[offset][i] != id || r.match[offset][i+1] != to {
continue
}
return
}
r.match[offset] = append(r.match[offset], id, to)
}
func (r *results) setNoMatch(offset, id int) {
if len(r.match) > offset {
for i := 0; i < len(r.match[offset]); i += 2 {
if r.match[offset][i] != id {
continue
}
return
}
}
r.noMatch = ensureOffsetIDs(r.noMatch, offset)
if r.noMatch[offset] == nil {
r.noMatch[offset] = &idSet{}
}
r.noMatch[offset].set(id)
}
func (r *results) hasMatchTo(offset, id, to int) bool {
if len(r.match) <= offset {
return false
}
for i := 0; i < len(r.match[offset]); i += 2 {
if r.match[offset][i] != id {
continue
}
if r.match[offset][i+1] == to {
return true
}
}
return false
}
func (r *results) longestMatch(offset, id int) (int, bool) {
if len(r.match) <= offset {
return 0, false
}
var found bool
to := -1
for i := 0; i < len(r.match[offset]); i += 2 {
if r.match[offset][i] != id {
continue
}
if r.match[offset][i+1] > to {
to = r.match[offset][i+1]
}
found = true
}
return to, found
}
func (r *results) longestResult(offset, id int) (int, bool, bool) {
if len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {
return 0, false, true
}
to, ok := r.longestMatch(offset, id)
return to, ok, ok
}
func (r *results) dropMatchTo(offset, id, to int) {
for i := 0; i < len(r.match[offset]); i += 2 {
if r.match[offset][i] != id {
continue
}
if r.match[offset][i+1] == to {
r.match[offset][i] = -1
return
}
}
}
func (r *results) resetPending() {
r.isPending = nil
}
func (r *results) pending(offset, id int) bool {
if len(r.isPending) <= id {
return false
}
for i := range r.isPending[id] {
if r.isPending[id][i] == offset {
return true
}
}
return false
}
func (r *results) markPending(offset, id int) {
r.isPending = ensureOffsetInts(r.isPending, id)
for i := range r.isPending[id] {
if r.isPending[id][i] == -1 {
r.isPending[id][i] = offset
return
}
}
r.isPending[id] = append(r.isPending[id], offset)
}
func (r *results) unmarkPending(offset, id int) {
for i := range r.isPending[id] {
if r.isPending[id][i] == offset {
r.isPending[id][i] = -1
break
}
}
}
type context struct {
2025-09-01 02:07:48 +02:00
reader io.RuneReader
keywords []parser
offset int
readOffset int
consumed int
offsetLimit int
failOffset int
failingParser parser
readErr error
eof bool
results *results
tokens []rune
matchLast bool
}
func newContext(r io.RuneReader, keywords []parser) *context {
return &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}
}
func (c *context) read() bool {
if c.eof || c.readErr != nil {
return false
}
token, n, err := c.reader.ReadRune()
if err != nil {
if err == io.EOF {
if n == 0 {
c.eof = true
return false
}
} else {
c.readErr = err
return false
}
}
c.readOffset++
if token == unicode.ReplacementChar {
c.readErr = errInvalidUnicodeCharacter
return false
}
c.tokens = append(c.tokens, token)
return true
}
func (c *context) token() (rune, bool) {
if c.offset == c.offsetLimit {
return 0, false
}
if c.offset == c.readOffset {
if !c.read() {
return 0, false
}
}
return c.tokens[c.offset], true
}
func (c *context) fromResults(p parser) bool {
to, m, ok := c.results.longestResult(c.offset, p.nodeID())
if !ok {
return false
}
if m {
c.success(to)
} else {
c.fail(c.offset)
}
return true
}
func (c *context) isKeyword(from, to int) bool {
ol := c.offsetLimit
c.offsetLimit = to
defer func() {
c.offsetLimit = ol
}()
for _, kw := range c.keywords {
c.offset = from
kw.parse(c)
if c.matchLast && c.offset == to {
return true
}
}
return false
}
func (c *context) success(to int) {
c.offset = to
c.matchLast = true
if to > c.consumed {
c.consumed = to
}
}
func (c *context) fail(offset int) {
c.offset = offset
c.matchLast = false
}
func findLine(tokens []rune, offset int) (line, column int) {
tokens = tokens[:offset]
for i := range tokens {
column++
if tokens[i] == '\n' {
column = 0
line++
}
}
return
}
func (c *context) parseError(p parser) error {
definition := p.nodeName()
flagIndex := strings.Index(definition, ":")
if flagIndex > 0 {
definition = definition[:flagIndex]
}
if c.failingParser == nil {
c.failOffset = c.consumed
}
line, col := findLine(c.tokens, c.failOffset)
return &parseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}
}
func (c *context) finalizeParse(root parser) error {
fp := c.failingParser
if fp == nil {
fp = root
}
to, match, found := c.results.longestResult(0, root.nodeID())
if !found || !match || found && match && to < c.readOffset {
return c.parseError(fp)
}
c.read()
if c.eof {
return nil
}
if c.readErr != nil {
return c.readErr
}
return c.parseError(root)
}
type node struct {
2025-09-01 02:07:48 +02:00
Name string
Nodes []*node
From, To int
tokens []rune
}
func (n *node) Tokens() []rune {
return n.tokens
}
func (n *node) String() string {
return fmt.Sprintf("%s:%d:%d:%s", n.Name, n.From, n.To, n.Text())
}
func (n *node) Text() string {
return string(n.Tokens()[n.From:n.To])
}
type commitType int
const (
2025-09-01 02:07:48 +02:00
none commitType = 0
alias commitType = 1 << iota
whitespace
noWhitespace
keyword
noKeyword
failPass
root
userDefined
)
type formatFlags int
const (
2025-09-01 02:07:48 +02:00
formatNone formatFlags = 0
formatPretty formatFlags = 1 << iota
formatIncludeComments
)
type parseError struct {
2025-09-01 02:07:48 +02:00
Input string
Offset int
Line int
Column int
Definition string
}
type parser interface {
nodeName() string
nodeID() int
commitType() commitType
parse(*context)
}
type builder interface {
nodeName() string
nodeID() int
build(*context) ([]*node, bool)
}
var errInvalidUnicodeCharacter = errors.New("invalid unicode character")
func (pe *parseError) Error() string {
return fmt.Sprintf("%s:%d:%d:parse failed, parsing: %s", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)
}
func parseInput(r io.Reader, p parser, b builder, kw []parser) (*node, error) {
c := newContext(bufio.NewReader(r), kw)
p.parse(c)
if c.readErr != nil {
return nil, c.readErr
}
if err := c.finalizeParse(p); err != nil {
if perr, ok := err.(*parseError); ok {
perr.Input = "<input>"
}
return nil, err
}
c.offset = 0
c.results.resetPending()
n, _ := b.build(c)
return n[0], nil
}
// eo head
func parse(r io.Reader) (*node, error) {
2025-09-01 02:07:48 +02:00
var p67 = sequenceParser{id: 67, commit: 128,ranges: [][]int{{0, -1},{1, 1},{0, -1},},};var p65 = choiceParser{id: 65, commit: 2,};var p64 = sequenceParser{id: 64, commit: 262,name: "whitespace",allChars: true,ranges: [][]int{{1, 1},{1, 1},},generalizations: []int{65,},};var p1 = charParser{id: 1,chars: []rune{32,8,12,13,9,11,},};p64.items = []parser{&p1,};p65.options = []parser{&p64,};var p66 = sequenceParser{id: 66, commit: 258,name: "doc:wsroot",ranges: [][]int{{0, 1},},};var p63 = sequenceParser{id: 63, commit: 2,ranges: [][]int{{1, 1},{0, -1},},};var p61 = choiceParser{id: 61, commit: 2,};var p58 = sequenceParser{id: 58, commit: 256,name: "key-val",ranges: [][]int{{0, 1},{0, -1},{1, 1},{0, -1},{0, 1},{0, -1},{0, 1},},generalizations: []int{61,},};var p54 = sequenceParser{id: 54, commit: 2,ranges: [][]int{{1, 1},{0, -1},{1, 1},},};var p14 = sequenceParser{id: 14, commit: 256,name: "comment",ranges: [][]int{{1, 1},{0, 1},},};var p8 = sequenceParser{id: 8, commit: 258,name: "comment-line",ranges: [][]int{{1, 1},{0, 1},},generalizations: []int{61,},};var p3 = sequenceParser{id: 3, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},};var p2 = charParser{id: 2,chars: []rune{35,},};p3.items = []parser{&p2,};var p7 = sequenceParser{id: 7, commit: 2,ranges: [][]int{{0, -1},{1, 1},{0, -1},},};var p5 = sequenceParser{id: 5, commit: 2,allChars: true,ranges: [][]int{{1, 1},},};var p4 = charParser{id: 4,not: true,chars: []rune{10,},};p5.items = []parser{&p4,};var p6 = sequenceParser{id: 6, commit: 2,ranges: [][]int{{0, -1},{1, 1},},};p6.items = []parser{&p65,&p5,};p7.items = []parser{&p65,&p5,&p6,};p8.items = []parser{&p3,&p7,};var p13 = sequenceParser{id: 13, commit: 2,ranges: [][]int{{0, -1},{1, 1},{0, -1},},};var p11 = sequenceParser{id: 11, commit: 2,ranges: [][]int{{1, 1},{0, -1},{1, 1},},};var p10 = sequenceParser{id: 10, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},};var p9 = charParser{id: 9,chars: []rune{10,},};p10.items = []parser{&p9,};p11.items = []parser{&p10,&p65,&p8,};var p12 = sequenceParser{id: 12, commit: 2,ranges: [][]int{{0, -1},{1, 1},},};p12.items = []parser{&p65,&p11,};p13.items = []parser{&p65,&p11,&p12,};p14.items = []parser{&p8,&p13,};var p53 = sequenceParser{id: 53, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},};var p52 = charParser{id: 52,chars: []rune{10,},};p53.items = []parser{&p52,};p54.items = []parser{&p14,&p65,&p53,};var p39 = choiceParser{id: 39, commit: 256,name: "key",};var p38 = sequenceParser{id: 38, commit: 266,name: "word",ranges: [][]int{{1, 1},{0, -1},{1, 1},{0, -1},},generalizations: []int{39,},};var p29 = sequenceParser{id: 29, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},};var p28 = charParser{id: 28,chars: []rune{95,},ranges: [][]rune{{97, 122},{65, 90},},};p29.items = []parser{&p28,};var p37 = choiceParser{id: 37, commit: 10,};var p31 = sequenceParser{id: 31, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},generalizations: []int{37,},};var p30 = charParser{id: 30,chars: []rune{95,45,},ranges: [][]rune{{97, 122},{65, 90},{48, 57},},};p31.items = []parser{&p30,};var p36 = sequenceParser{id: 36, commit: 10,ranges: [][]int{{1, 1},{1, 1},{1, 1},{1, 1},},generalizations: []int{37,},};var p33 = sequenceParser{id: 33, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},};var p32 = charParser{id: 32,chars: []rune{92,},};p33.items = []parser{&p32,};var p35 = sequenceParser{id: 35, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},};var p34 = charParser{id: 34,not: true,};p35.items = []parser{&p34,};p36.items = []parser{&p33,&p35,};p37.options = []parser{&p31,&p36,};p38.items = []parser{&p29,&p37,};var p27 = sequenceParser{id: 27, commit: 266,name: "quoted",ranges: [][]int{{1, 1},{0, -1},{1, 1},{1, 1},{0, -1},{1, 1},},generalizations: []int{39,51,},};var p16 = sequenceParser{id: 16, commit: 10,allChars: true,ranges: [][]int{{1, 1},{1, 1},},};var p15 = charParser{id: 15,chars: []rune{34,},};p16.items = []parser{&p15,};var p24 = choiceParser{id: 24, commit: 10,};var p18 = sequenceParser{id: 18, commit: 10,allChars: true,rang
2025-09-01 02:07:48 +02:00
var keywords = []parser{}
2025-09-01 02:07:48 +02:00
return parseInput(r, &p67, &b67, keywords)
}