2025-08-26 03:37:55 +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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package wand
|
|
|
|
|
|
|
|
|
|
// head
|
|
|
|
|
import (
|
2025-09-06 02:46:28 +02:00
|
|
|
"bufio"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
2025-09-05 03:19:00 +02:00
|
|
|
"io"
|
2025-09-06 02:46:28 +02:00
|
|
|
"strconv"
|
2025-08-26 03:37:55 +02:00
|
|
|
"strings"
|
|
|
|
|
"unicode"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type charParser struct {
|
2025-09-06 02:46:28 +02:00
|
|
|
name string
|
|
|
|
|
id int
|
|
|
|
|
not bool
|
|
|
|
|
chars []rune
|
|
|
|
|
ranges [][]rune
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
type charBuilder struct {
|
2025-09-06 02:46:28 +02:00
|
|
|
name string
|
|
|
|
|
id int
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
name string
|
|
|
|
|
id int
|
|
|
|
|
commit commitType
|
|
|
|
|
items []parser
|
|
|
|
|
ranges [][]int
|
|
|
|
|
generalizations []int
|
|
|
|
|
allChars bool
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
type sequenceBuilder struct {
|
2025-09-06 02:46:28 +02:00
|
|
|
name string
|
|
|
|
|
id int
|
|
|
|
|
commit commitType
|
|
|
|
|
items []builder
|
|
|
|
|
ranges [][]int
|
|
|
|
|
generalizations []int
|
|
|
|
|
allChars bool
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
currentCount int
|
|
|
|
|
parsed bool
|
2025-08-26 03:37:55 +02:00
|
|
|
)
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
itemIndex int
|
|
|
|
|
currentCount int
|
|
|
|
|
nodes []*node
|
2025-08-26 03:37:55 +02:00
|
|
|
)
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
name string
|
|
|
|
|
id int
|
|
|
|
|
commit commitType
|
|
|
|
|
options []parser
|
|
|
|
|
generalizations []int
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
type choiceBuilder struct {
|
2025-09-06 02:46:28 +02:00
|
|
|
name string
|
|
|
|
|
id int
|
|
|
|
|
commit commitType
|
|
|
|
|
options []builder
|
|
|
|
|
generalizations []int
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
match bool
|
|
|
|
|
optionIndex int
|
|
|
|
|
foundMatch bool
|
|
|
|
|
failingParser parser
|
2025-08-26 03:37:55 +02:00
|
|
|
)
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
noMatch []*idSet
|
|
|
|
|
match [][]int
|
|
|
|
|
isPending [][]int
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-06 02:46:28 +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
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
Name string
|
|
|
|
|
Nodes []*node
|
|
|
|
|
From, To int
|
|
|
|
|
tokens []rune
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
none commitType = 0
|
|
|
|
|
alias commitType = 1 << iota
|
2025-08-26 03:37:55 +02:00
|
|
|
whitespace
|
|
|
|
|
noWhitespace
|
|
|
|
|
keyword
|
|
|
|
|
noKeyword
|
|
|
|
|
failPass
|
|
|
|
|
root
|
|
|
|
|
userDefined
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type formatFlags int
|
|
|
|
|
|
|
|
|
|
const (
|
2025-09-06 02:46:28 +02:00
|
|
|
formatNone formatFlags = 0
|
|
|
|
|
formatPretty formatFlags = 1 << iota
|
2025-08-26 03:37:55 +02:00
|
|
|
formatIncludeComments
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type parseError struct {
|
2025-09-06 02:46:28 +02:00
|
|
|
Input string
|
|
|
|
|
Offset int
|
|
|
|
|
Line int
|
|
|
|
|
Column int
|
|
|
|
|
Definition string
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|
|
|
|
|
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-06 02:46:28 +02:00
|
|
|
var p60 = sequenceParser{id: 60, commit: 128, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var p58 = choiceParser{id: 58, commit: 2}
|
|
|
|
|
var p57 = sequenceParser{id: 57, commit: 262, name: "whitespace", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{58}}
|
|
|
|
|
var p1 = charParser{id: 1, chars: []rune{32, 8, 12, 13, 9, 11}}
|
|
|
|
|
p57.items = []parser{&p1}
|
|
|
|
|
p58.options = []parser{&p57}
|
|
|
|
|
var p59 = sequenceParser{id: 59, commit: 258, name: "doc:wsroot", ranges: [][]int{{0, 1}, {0, -1}, {1, 1}, {0, 1}, {0, 1}}}
|
|
|
|
|
var p52 = sequenceParser{id: 52, commit: 2, ranges: [][]int{{1, 1}, {0, -1}}}
|
|
|
|
|
var p42 = sequenceParser{id: 42, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p41 = charParser{id: 41, chars: []rune{10}}
|
|
|
|
|
p42.items = []parser{&p41}
|
|
|
|
|
var p51 = sequenceParser{id: 51, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
p51.items = []parser{&p58, &p42}
|
|
|
|
|
p52.items = []parser{&p42, &p51}
|
|
|
|
|
var p43 = choiceParser{id: 43, commit: 2}
|
|
|
|
|
var p40 = sequenceParser{id: 40, commit: 256, name: "key-val", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {0, 1}}, generalizations: []int{43, 46}}
|
|
|
|
|
var p13 = sequenceParser{id: 13, commit: 264, name: "key", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var p10 = sequenceParser{id: 10, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p9 = charParser{id: 9, chars: []rune{95}, ranges: [][]rune{{97, 122}, {65, 90}}}
|
|
|
|
|
p10.items = []parser{&p9}
|
|
|
|
|
var p12 = sequenceParser{id: 12, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p11 = charParser{id: 11, chars: []rune{95, 45}, ranges: [][]rune{{97, 122}, {65, 90}, {48, 57}}}
|
|
|
|
|
p12.items = []parser{&p11}
|
|
|
|
|
p13.items = []parser{&p10, &p12}
|
|
|
|
|
var p39 = sequenceParser{id: 39, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}}
|
|
|
|
|
var p38 = sequenceParser{id: 38, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p37 = charParser{id: 37, chars: []rune{61}}
|
|
|
|
|
p38.items = []parser{&p37}
|
|
|
|
|
var p36 = choiceParser{id: 36, commit: 256, name: "value"}
|
|
|
|
|
var p35 = sequenceParser{id: 35, commit: 264, name: "value-chars", ranges: [][]int{{0, -1}, {0, -1}}, generalizations: []int{36}}
|
|
|
|
|
var p34 = choiceParser{id: 34, commit: 10}
|
|
|
|
|
var p28 = sequenceParser{id: 28, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{34}}
|
|
|
|
|
var p27 = charParser{id: 27, not: true, chars: []rune{92, 34, 10, 61, 35, 32, 8, 12, 13, 9, 11}}
|
|
|
|
|
p28.items = []parser{&p27}
|
|
|
|
|
var p33 = sequenceParser{id: 33, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{34}}
|
|
|
|
|
var p30 = sequenceParser{id: 30, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p29 = charParser{id: 29, chars: []rune{92}}
|
|
|
|
|
p30.items = []parser{&p29}
|
|
|
|
|
var p32 = sequenceParser{id: 32, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p31 = charParser{id: 31, not: true}
|
|
|
|
|
p32.items = []parser{&p31}
|
|
|
|
|
p33.items = []parser{&p30, &p32}
|
|
|
|
|
p34.options = []parser{&p28, &p33}
|
|
|
|
|
p35.items = []parser{&p34}
|
|
|
|
|
var p26 = sequenceParser{id: 26, commit: 264, name: "quoted", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{36}}
|
|
|
|
|
var p15 = sequenceParser{id: 15, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p14 = charParser{id: 14, chars: []rune{34}}
|
|
|
|
|
p15.items = []parser{&p14}
|
|
|
|
|
var p23 = choiceParser{id: 23, commit: 10}
|
|
|
|
|
var p17 = sequenceParser{id: 17, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{23}}
|
|
|
|
|
var p16 = charParser{id: 16, not: true, chars: []rune{92, 34}}
|
|
|
|
|
p17.items = []parser{&p16}
|
|
|
|
|
var p22 = sequenceParser{id: 22, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{23}}
|
|
|
|
|
var p19 = sequenceParser{id: 19, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p18 = charParser{id: 18, chars: []rune{92}}
|
|
|
|
|
p19.items = []parser{&p18}
|
|
|
|
|
var p21 = sequenceParser{id: 21, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p20 = charParser{id: 20, not: true}
|
|
|
|
|
p21.items = []parser{&p20}
|
|
|
|
|
p22.items = []parser{&p19, &p21}
|
|
|
|
|
p23.options = []parser{&p17, &p22}
|
|
|
|
|
var p25 = sequenceParser{id: 25, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p24 = charParser{id: 24, chars: []rune{34}}
|
|
|
|
|
p25.items = []parser{&p24}
|
|
|
|
|
p26.items = []parser{&p15, &p23, &p25}
|
|
|
|
|
p36.options = []parser{&p35, &p26}
|
|
|
|
|
p39.items = []parser{&p38, &p58, &p36}
|
|
|
|
|
var p8 = sequenceParser{id: 8, commit: 258, name: "comment-line", ranges: [][]int{{1, 1}, {0, 1}}, generalizations: []int{43, 46}}
|
|
|
|
|
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{&p58, &p5}
|
|
|
|
|
p7.items = []parser{&p58, &p5, &p6}
|
|
|
|
|
p8.items = []parser{&p3, &p7}
|
|
|
|
|
p40.items = []parser{&p13, &p58, &p39, &p58, &p8}
|
|
|
|
|
p43.options = []parser{&p40, &p8}
|
|
|
|
|
var p54 = sequenceParser{id: 54, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var p48 = sequenceParser{id: 48, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}}
|
|
|
|
|
var p45 = sequenceParser{id: 45, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p44 = charParser{id: 44, chars: []rune{10}}
|
|
|
|
|
p45.items = []parser{&p44}
|
|
|
|
|
var p47 = sequenceParser{id: 47, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
p47.items = []parser{&p58, &p45}
|
|
|
|
|
var p46 = choiceParser{id: 46, commit: 2}
|
|
|
|
|
p46.options = []parser{&p40, &p8}
|
|
|
|
|
p48.items = []parser{&p45, &p47, &p58, &p46}
|
|
|
|
|
var p53 = sequenceParser{id: 53, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
p53.items = []parser{&p58, &p48}
|
|
|
|
|
p54.items = []parser{&p58, &p48, &p53}
|
|
|
|
|
var p56 = sequenceParser{id: 56, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var p50 = sequenceParser{id: 50, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var p49 = charParser{id: 49, chars: []rune{10}}
|
|
|
|
|
p50.items = []parser{&p49}
|
|
|
|
|
var p55 = sequenceParser{id: 55, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
p55.items = []parser{&p58, &p50}
|
|
|
|
|
p56.items = []parser{&p58, &p50, &p55}
|
|
|
|
|
p59.items = []parser{&p52, &p58, &p43, &p54, &p56}
|
|
|
|
|
p60.items = []parser{&p58, &p59, &p58}
|
|
|
|
|
var b60 = sequenceBuilder{id: 60, commit: 128, name: "doc", ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var b58 = choiceBuilder{id: 58, commit: 2}
|
|
|
|
|
var b57 = sequenceBuilder{id: 57, commit: 262, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{58}}
|
|
|
|
|
var b1 = charBuilder{}
|
|
|
|
|
b57.items = []builder{&b1}
|
|
|
|
|
b58.options = []builder{&b57}
|
|
|
|
|
var b59 = sequenceBuilder{id: 59, commit: 258, ranges: [][]int{{0, 1}, {0, -1}, {1, 1}, {0, 1}, {0, 1}}}
|
|
|
|
|
var b52 = sequenceBuilder{id: 52, commit: 2, ranges: [][]int{{1, 1}, {0, -1}}}
|
|
|
|
|
var b42 = sequenceBuilder{id: 42, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b41 = charBuilder{}
|
|
|
|
|
b42.items = []builder{&b41}
|
|
|
|
|
var b51 = sequenceBuilder{id: 51, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
b51.items = []builder{&b58, &b42}
|
|
|
|
|
b52.items = []builder{&b42, &b51}
|
|
|
|
|
var b43 = choiceBuilder{id: 43, commit: 2}
|
|
|
|
|
var b40 = sequenceBuilder{id: 40, commit: 256, name: "key-val", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {0, 1}}, generalizations: []int{43, 46}}
|
|
|
|
|
var b13 = sequenceBuilder{id: 13, commit: 264, name: "key", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var b10 = sequenceBuilder{id: 10, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b9 = charBuilder{}
|
|
|
|
|
b10.items = []builder{&b9}
|
|
|
|
|
var b12 = sequenceBuilder{id: 12, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b11 = charBuilder{}
|
|
|
|
|
b12.items = []builder{&b11}
|
|
|
|
|
b13.items = []builder{&b10, &b12}
|
|
|
|
|
var b39 = sequenceBuilder{id: 39, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}}
|
|
|
|
|
var b38 = sequenceBuilder{id: 38, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b37 = charBuilder{}
|
|
|
|
|
b38.items = []builder{&b37}
|
|
|
|
|
var b36 = choiceBuilder{id: 36, commit: 256, name: "value"}
|
|
|
|
|
var b35 = sequenceBuilder{id: 35, commit: 264, name: "value-chars", ranges: [][]int{{0, -1}, {0, -1}}, generalizations: []int{36}}
|
|
|
|
|
var b34 = choiceBuilder{id: 34, commit: 10}
|
|
|
|
|
var b28 = sequenceBuilder{id: 28, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{34}}
|
|
|
|
|
var b27 = charBuilder{}
|
|
|
|
|
b28.items = []builder{&b27}
|
|
|
|
|
var b33 = sequenceBuilder{id: 33, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{34}}
|
|
|
|
|
var b30 = sequenceBuilder{id: 30, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b29 = charBuilder{}
|
|
|
|
|
b30.items = []builder{&b29}
|
|
|
|
|
var b32 = sequenceBuilder{id: 32, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b31 = charBuilder{}
|
|
|
|
|
b32.items = []builder{&b31}
|
|
|
|
|
b33.items = []builder{&b30, &b32}
|
|
|
|
|
b34.options = []builder{&b28, &b33}
|
|
|
|
|
b35.items = []builder{&b34}
|
|
|
|
|
var b26 = sequenceBuilder{id: 26, commit: 264, name: "quoted", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{36}}
|
|
|
|
|
var b15 = sequenceBuilder{id: 15, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b14 = charBuilder{}
|
|
|
|
|
b15.items = []builder{&b14}
|
|
|
|
|
var b23 = choiceBuilder{id: 23, commit: 10}
|
|
|
|
|
var b17 = sequenceBuilder{id: 17, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{23}}
|
|
|
|
|
var b16 = charBuilder{}
|
|
|
|
|
b17.items = []builder{&b16}
|
|
|
|
|
var b22 = sequenceBuilder{id: 22, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{23}}
|
|
|
|
|
var b19 = sequenceBuilder{id: 19, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b18 = charBuilder{}
|
|
|
|
|
b19.items = []builder{&b18}
|
|
|
|
|
var b21 = sequenceBuilder{id: 21, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b20 = charBuilder{}
|
|
|
|
|
b21.items = []builder{&b20}
|
|
|
|
|
b22.items = []builder{&b19, &b21}
|
|
|
|
|
b23.options = []builder{&b17, &b22}
|
|
|
|
|
var b25 = sequenceBuilder{id: 25, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b24 = charBuilder{}
|
|
|
|
|
b25.items = []builder{&b24}
|
|
|
|
|
b26.items = []builder{&b15, &b23, &b25}
|
|
|
|
|
b36.options = []builder{&b35, &b26}
|
|
|
|
|
b39.items = []builder{&b38, &b58, &b36}
|
|
|
|
|
var b8 = sequenceBuilder{id: 8, commit: 258, ranges: [][]int{{1, 1}, {0, 1}}, generalizations: []int{43, 46}}
|
|
|
|
|
var b3 = sequenceBuilder{id: 3, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b2 = charBuilder{}
|
|
|
|
|
b3.items = []builder{&b2}
|
|
|
|
|
var b7 = sequenceBuilder{id: 7, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var b5 = sequenceBuilder{id: 5, commit: 2, allChars: true, ranges: [][]int{{1, 1}}}
|
|
|
|
|
var b4 = charBuilder{}
|
|
|
|
|
b5.items = []builder{&b4}
|
|
|
|
|
var b6 = sequenceBuilder{id: 6, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
b6.items = []builder{&b58, &b5}
|
|
|
|
|
b7.items = []builder{&b58, &b5, &b6}
|
|
|
|
|
b8.items = []builder{&b3, &b7}
|
|
|
|
|
b40.items = []builder{&b13, &b58, &b39, &b58, &b8}
|
|
|
|
|
b43.options = []builder{&b40, &b8}
|
|
|
|
|
var b54 = sequenceBuilder{id: 54, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var b48 = sequenceBuilder{id: 48, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}}
|
|
|
|
|
var b45 = sequenceBuilder{id: 45, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b44 = charBuilder{}
|
|
|
|
|
b45.items = []builder{&b44}
|
|
|
|
|
var b47 = sequenceBuilder{id: 47, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
b47.items = []builder{&b58, &b45}
|
|
|
|
|
var b46 = choiceBuilder{id: 46, commit: 2}
|
|
|
|
|
b46.options = []builder{&b40, &b8}
|
|
|
|
|
b48.items = []builder{&b45, &b47, &b58, &b46}
|
|
|
|
|
var b53 = sequenceBuilder{id: 53, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
b53.items = []builder{&b58, &b48}
|
|
|
|
|
b54.items = []builder{&b58, &b48, &b53}
|
|
|
|
|
var b56 = sequenceBuilder{id: 56, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}}
|
|
|
|
|
var b50 = sequenceBuilder{id: 50, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}}
|
|
|
|
|
var b49 = charBuilder{}
|
|
|
|
|
b50.items = []builder{&b49}
|
|
|
|
|
var b55 = sequenceBuilder{id: 55, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}}
|
|
|
|
|
b55.items = []builder{&b58, &b50}
|
|
|
|
|
b56.items = []builder{&b58, &b50, &b55}
|
|
|
|
|
b59.items = []builder{&b52, &b58, &b43, &b54, &b56}
|
|
|
|
|
b60.items = []builder{&b58, &b59, &b58}
|
2025-08-26 03:37:55 +02:00
|
|
|
|
2025-09-06 02:46:28 +02:00
|
|
|
var keywords = []parser{}
|
2025-08-26 03:37:55 +02:00
|
|
|
|
2025-09-06 02:46:28 +02:00
|
|
|
return parseInput(r, &p60, &b60, keywords)
|
2025-08-26 03:37:55 +02:00
|
|
|
}
|