diff --git a/define.go b/define.go index fb292d8..791300c 100644 --- a/define.go +++ b/define.go @@ -24,6 +24,8 @@ func flagsToCommitType(n []Node) CommitType { ct |= NoKeyword case "failpass": ct |= FailPass + case "nofailpass": + ct |= NoFailPass case "root": ct |= Root } @@ -193,7 +195,7 @@ func defineExpression(s *Syntax, name string, ct CommitType, expression Node) er func commitTypeUserDefined(ct CommitType) CommitType { ct |= userDefined - if ct&Alias > 0 { + if ct&Alias > 0 && ct&NoFailPass == 0 { ct |= FailPass } diff --git a/errors_test.go b/errors_test.go index 04947bb..b864408 100644 --- a/errors_test.go +++ b/errors_test.go @@ -325,7 +325,6 @@ func TestFailPass(t *testing.T) { ` const doc = `f(a b c)` - testParseError(t, syntax, []errorTestItem{{ title: "fail in outer definition", doc: doc, @@ -337,4 +336,26 @@ func TestFailPass(t *testing.T) { }, }}) }) + + t.Run("force fail for alias", func(t *testing.T) { + const syntax = ` + space:ws = " "; + symbol:nows = [a-z]+; + list-separator:alias:nofailpass = ","; + argument-list:failpass = (symbol (list-separator+ symbol)*); + function-application = symbol "(" argument-list? ")"; + ` + + const doc = `f(a b c)` + testParseError(t, syntax, []errorTestItem{{ + title: "fail in outer definition", + doc: doc, + perr: ParseError{ + Offset: 4, + Line: 0, + Column: 4, + Definition: "list-separator", + }, + }}) + }) } diff --git a/head.gen.go b/head.gen.go index a7b8e61..50d6354 100644 --- a/head.gen.go +++ b/head.gen.go @@ -1,4 +1,4 @@ package treerack // generated with script/createhead.go -const headCode = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() commitType {\n\treturn alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount, itemIndex\tint\n\t\tparsed\t\t\tbool\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&whitespace == 0 && p.commitType()&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = errInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &parseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype node struct {\n\tName\tstring\n\tNodes\t[]node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype commitType int\n\nconst (\n\tnone\tcommitType\t= 0\n\talias\tcommitType\t= 1 << iota\n\twhitespace\n\tnoWhitespace\n\tkeyword\n\tnoKeyword\n\tfailPass\n\troot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype parseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() commitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]node, bool)\n}\n\nvar errInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *parseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn node{}, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*parseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn node{}, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" +const headCode = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() commitType {\n\treturn alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount, itemIndex\tint\n\t\tparsed\t\t\tbool\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tcommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() commitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&noKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&whitespace == 0 && p.commit&failPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&whitespace == 0 && p.commitType()&failPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = errInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &parseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype node struct {\n\tName\tstring\n\tNodes\t[]node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype commitType int\n\nconst (\n\tnone\tcommitType\t= 0\n\talias\tcommitType\t= 1 << iota\n\twhitespace\n\tnoWhitespace\n\tkeyword\n\tnoKeyword\n\tfailPass\n\tNoFailPass\n\troot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype parseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() commitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]node, bool)\n}\n\nvar errInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *parseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn node{}, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*parseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn node{}, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" diff --git a/headexported.gen.go b/headexported.gen.go index 38250e1..0519efe 100644 --- a/headexported.gen.go +++ b/headexported.gen.go @@ -1,4 +1,4 @@ package treerack // generated with script/createhead.go -const headCodeExported = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() CommitType {\n\treturn Alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]Node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount, itemIndex\tint\n\t\tparsed\t\t\tbool\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&Alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]Node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []Node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&Whitespace == 0 && p.commitType()&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []Node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = ErrInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &ParseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype Node struct {\n\tName\tstring\n\tNodes\t[]Node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n Node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n Node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n Node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype CommitType int\n\nconst (\n\tNone\tCommitType\t= 0\n\tAlias\tCommitType\t= 1 << iota\n\tWhitespace\n\tNoWhitespace\n\tKeyword\n\tNoKeyword\n\tFailPass\n\tRoot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype ParseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() CommitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]Node, bool)\n}\n\nvar ErrInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *ParseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (Node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn Node{}, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*ParseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn Node{}, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" +const headCodeExported = "import (\n\t\"strconv\"\n\t\"errors\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n)\n\ntype charParser struct {\n\tname\tstring\n\tid\tint\n\tnot\tbool\n\tchars\t[]rune\n\tranges\t[][]rune\n}\ntype charBuilder struct {\n\tname\tstring\n\tid\tint\n}\n\nfunc (p *charParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *charParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *charParser) commitType() CommitType {\n\treturn Alias\n}\nfunc matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool {\n\tfor _, ci := range chars {\n\t\tif ci == char {\n\t\t\treturn !not\n\t\t}\n\t}\n\tfor _, ri := range ranges {\n\t\tif char >= ri[0] && char <= ri[1] {\n\t\t\treturn !not\n\t\t}\n\t}\n\treturn not\n}\nfunc (p *charParser) match(t rune) bool {\n\treturn matchChar(p.chars, p.ranges, p.not, t)\n}\nfunc (p *charParser) parse(c *context) {\n\tif tok, ok := c.token(); !ok || !p.match(tok) {\n\t\tif c.offset > c.failOffset {\n\t\t\tc.failOffset = c.offset\n\t\t\tc.failingParser = nil\n\t\t}\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.success(c.offset + 1)\n}\nfunc (b *charBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *charBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *charBuilder) build(c *context) ([]Node, bool) {\n\treturn nil, false\n}\n\ntype sequenceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]parser\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\ntype sequenceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\titems\t\t[]builder\n\tranges\t\t[][]int\n\tgeneralizations\t[]int\n\tallChars\tbool\n}\n\nfunc (p *sequenceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *sequenceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *sequenceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *sequenceParser) parse(c *context) {\n\tif !p.allChars {\n\t\tif c.results.pending(c.offset, p.id) {\n\t\t\tc.fail(c.offset)\n\t\t\treturn\n\t\t}\n\t\tc.results.markPending(c.offset, p.id)\n\t}\n\tvar (\n\t\tcurrentCount, itemIndex\tint\n\t\tparsed\t\t\tbool\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tfor itemIndex < len(p.items) {\n\t\tp.items[itemIndex].parse(c)\n\t\tif !c.matchLast {\n\t\t\tif currentCount >= p.ranges[itemIndex][0] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tc.offset = from\n\t\t\tif c.fromResults(p) {\n\t\t\t\tif to > c.failOffset {\n\t\t\t\t\tc.failOffset = -1\n\t\t\t\t\tc.failingParser = nil\n\t\t\t\t}\n\t\t\t\tif !p.allChars {\n\t\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tif !p.allChars {\n\t\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\tparsed = c.offset > to\n\t\tif parsed {\n\t\t\tcurrentCount++\n\t\t}\n\t\tto = c.offset\n\t\tif !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t}\n\t}\n\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t\tc.fail(from)\n\t\tif !p.allChars {\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t}\n\t\treturn\n\t}\n\tfor _, g := range p.generalizations {\n\t\tif c.results.pending(from, g) {\n\t\t\tc.results.setMatch(from, g, to)\n\t\t}\n\t}\n\tif to > c.failOffset {\n\t\tc.failOffset = -1\n\t\tc.failingParser = nil\n\t}\n\tc.results.setMatch(from, p.id, to)\n\tc.success(to)\n\tif !p.allChars {\n\t\tc.results.unmarkPending(from, p.id)\n\t}\n}\nfunc (b *sequenceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *sequenceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *sequenceBuilder) build(c *context) ([]Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif b.allChars {\n\t\tc.offset = to\n\t\tif b.commit&Alias != 0 {\n\t\t\treturn nil, true\n\t\t}\n\t\treturn []Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true\n\t} else if parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar (\n\t\titemIndex\tint\n\t\tcurrentCount\tint\n\t\tnodes\t\t[]Node\n\t)\n\tfor itemIndex < len(b.items) {\n\t\titemFrom := c.offset\n\t\tn, ok := b.items[itemIndex].build(c)\n\t\tif !ok {\n\t\t\titemIndex++\n\t\t\tcurrentCount = 0\n\t\t\tcontinue\n\t\t}\n\t\tif c.offset > itemFrom {\n\t\t\tnodes = append(nodes, n...)\n\t\t\tcurrentCount++\n\t\t\tif b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] {\n\t\t\t\titemIndex++\n\t\t\t\tcurrentCount = 0\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif currentCount < b.ranges[itemIndex][0] {\n\t\t\tfor i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ {\n\t\t\t\tnodes = append(nodes, n...)\n\t\t\t}\n\t\t}\n\t\titemIndex++\n\t\tcurrentCount = 0\n\t}\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn nodes, true\n\t}\n\treturn []Node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true\n}\n\ntype choiceParser struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]parser\n\tgeneralizations\t[]int\n}\ntype choiceBuilder struct {\n\tname\t\tstring\n\tid\t\tint\n\tcommit\t\tCommitType\n\toptions\t\t[]builder\n\tgeneralizations\t[]int\n}\n\nfunc (p *choiceParser) nodeName() string {\n\treturn p.name\n}\nfunc (p *choiceParser) nodeID() int {\n\treturn p.id\n}\nfunc (p *choiceParser) commitType() CommitType {\n\treturn p.commit\n}\nfunc (p *choiceParser) parse(c *context) {\n\tif c.fromResults(p) {\n\t\treturn\n\t}\n\tif c.results.pending(c.offset, p.id) {\n\t\tc.fail(c.offset)\n\t\treturn\n\t}\n\tc.results.markPending(c.offset, p.id)\n\tvar (\n\t\tmatch\t\tbool\n\t\toptionIndex\tint\n\t\tfoundMatch\tbool\n\t\tfailingParser\tparser\n\t)\n\tfrom := c.offset\n\tto := c.offset\n\tinitialFailOffset := c.failOffset\n\tinitialFailingParser := c.failingParser\n\tfailOffset := initialFailOffset\n\tfor {\n\t\tfoundMatch = false\n\t\toptionIndex = 0\n\t\tfor optionIndex < len(p.options) {\n\t\t\tp.options[optionIndex].parse(c)\n\t\t\toptionIndex++\n\t\t\tif !c.matchLast {\n\t\t\t\tif c.failOffset > failOffset {\n\t\t\t\t\tfailOffset = c.failOffset\n\t\t\t\t\tfailingParser = c.failingParser\n\t\t\t\t}\n\t\t\t}\n\t\t\tif !c.matchLast || match && c.offset <= to {\n\t\t\t\tc.offset = from\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tmatch = true\n\t\t\tfoundMatch = true\n\t\t\tto = c.offset\n\t\t\tc.offset = from\n\t\t\tc.results.setMatch(from, p.id, to)\n\t\t}\n\t\tif !foundMatch {\n\t\t\tbreak\n\t\t}\n\t}\n\tif match {\n\t\tif p.commit&NoKeyword != 0 && c.isKeyword(from, to) {\n\t\t\tif c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 {\n\t\t\t\tc.failingParser = p\n\t\t\t}\n\t\t\tc.fail(from)\n\t\t\tc.results.unmarkPending(from, p.id)\n\t\t\treturn\n\t\t}\n\t\tif failOffset > to {\n\t\t\tc.failOffset = failOffset\n\t\t\tc.failingParser = failingParser\n\t\t} else if to > initialFailOffset {\n\t\t\tc.failOffset = -1\n\t\t\tc.failingParser = nil\n\t\t} else {\n\t\t\tc.failOffset = initialFailOffset\n\t\t\tc.failingParser = initialFailingParser\n\t\t}\n\t\tc.success(to)\n\t\tc.results.unmarkPending(from, p.id)\n\t\treturn\n\t}\n\tif failOffset > initialFailOffset {\n\t\tc.failOffset = failOffset\n\t\tc.failingParser = failingParser\n\t\tif c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&Whitespace == 0 && p.commitType()&FailPass == 0 {\n\t\t\tc.failingParser = p\n\t\t}\n\t}\n\tc.results.setNoMatch(from, p.id)\n\tc.fail(from)\n\tc.results.unmarkPending(from, p.id)\n}\nfunc (b *choiceBuilder) nodeName() string {\n\treturn b.name\n}\nfunc (b *choiceBuilder) nodeID() int {\n\treturn b.id\n}\nfunc (b *choiceBuilder) build(c *context) ([]Node, bool) {\n\tto, ok := c.results.longestMatch(c.offset, b.id)\n\tif !ok {\n\t\treturn nil, false\n\t}\n\tfrom := c.offset\n\tparsed := to > from\n\tif parsed {\n\t\tc.results.dropMatchTo(c.offset, b.id, to)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.dropMatchTo(c.offset, g, to)\n\t\t}\n\t} else {\n\t\tif c.results.pending(c.offset, b.id) {\n\t\t\treturn nil, false\n\t\t}\n\t\tc.results.markPending(c.offset, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.markPending(c.offset, g)\n\t\t}\n\t}\n\tvar option builder\n\tfor _, o := range b.options {\n\t\tif c.results.hasMatchTo(c.offset, o.nodeID(), to) {\n\t\t\toption = o\n\t\t\tbreak\n\t\t}\n\t}\n\tn, _ := option.build(c)\n\tif !parsed {\n\t\tc.results.unmarkPending(from, b.id)\n\t\tfor _, g := range b.generalizations {\n\t\t\tc.results.unmarkPending(from, g)\n\t\t}\n\t}\n\tif b.commit&Alias != 0 {\n\t\treturn n, true\n\t}\n\treturn []Node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true\n}\n\ntype idSet struct{ ids []uint }\n\nfunc divModBits(id int) (int, int) {\n\treturn id / strconv.IntSize, id % strconv.IntSize\n}\nfunc (s *idSet) set(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\tif d < cap(s.ids) {\n\t\t\ts.ids = s.ids[:d+1]\n\t\t} else {\n\t\t\ts.ids = s.ids[:cap(s.ids)]\n\t\t\tfor i := cap(s.ids); i <= d; i++ {\n\t\t\t\ts.ids = append(s.ids, 0)\n\t\t\t}\n\t\t}\n\t}\n\ts.ids[d] |= 1 << uint(m)\n}\nfunc (s *idSet) unset(id int) {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn\n\t}\n\ts.ids[d] &^= 1 << uint(m)\n}\nfunc (s *idSet) has(id int) bool {\n\td, m := divModBits(id)\n\tif d >= len(s.ids) {\n\t\treturn false\n\t}\n\treturn s.ids[d]&(1< offset {\n\t\treturn ints\n\t}\n\tif cap(ints) > offset {\n\t\tints = ints[:offset+1]\n\t\treturn ints\n\t}\n\tints = ints[:cap(ints)]\n\tfor i := len(ints); i <= offset; i++ {\n\t\tints = append(ints, nil)\n\t}\n\treturn ints\n}\nfunc ensureOffsetIDs(ids []*idSet, offset int) []*idSet {\n\tif len(ids) > offset {\n\t\treturn ids\n\t}\n\tif cap(ids) > offset {\n\t\tids = ids[:offset+1]\n\t\treturn ids\n\t}\n\tids = ids[:cap(ids)]\n\tfor i := len(ids); i <= offset; i++ {\n\t\tids = append(ids, nil)\n\t}\n\treturn ids\n}\nfunc (r *results) setMatch(offset, id, to int) {\n\tr.match = ensureOffsetInts(r.match, offset)\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id || r.match[offset][i+1] != to {\n\t\t\tcontinue\n\t\t}\n\t\treturn\n\t}\n\tr.match[offset] = append(r.match[offset], id, to)\n}\nfunc (r *results) setNoMatch(offset, id int) {\n\tif len(r.match) > offset {\n\t\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\t\tif r.match[offset][i] != id {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t}\n\tr.noMatch = ensureOffsetIDs(r.noMatch, offset)\n\tif r.noMatch[offset] == nil {\n\t\tr.noMatch[offset] = &idSet{}\n\t}\n\tr.noMatch[offset].set(id)\n}\nfunc (r *results) hasMatchTo(offset, id, to int) bool {\n\tif len(r.match) <= offset {\n\t\treturn false\n\t}\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) longestMatch(offset, id int) (int, bool) {\n\tif len(r.match) <= offset {\n\t\treturn 0, false\n\t}\n\tvar found bool\n\tto := -1\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] > to {\n\t\t\tto = r.match[offset][i+1]\n\t\t}\n\t\tfound = true\n\t}\n\treturn to, found\n}\nfunc (r *results) longestResult(offset, id int) (int, bool, bool) {\n\tif len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {\n\t\treturn 0, false, true\n\t}\n\tto, ok := r.longestMatch(offset, id)\n\treturn to, ok, ok\n}\nfunc (r *results) dropMatchTo(offset, id, to int) {\n\tfor i := 0; i < len(r.match[offset]); i += 2 {\n\t\tif r.match[offset][i] != id {\n\t\t\tcontinue\n\t\t}\n\t\tif r.match[offset][i+1] == to {\n\t\t\tr.match[offset][i] = -1\n\t\t\treturn\n\t\t}\n\t}\n}\nfunc (r *results) resetPending() {\n\tr.isPending = nil\n}\nfunc (r *results) pending(offset, id int) bool {\n\tif len(r.isPending) <= id {\n\t\treturn false\n\t}\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (r *results) markPending(offset, id int) {\n\tr.isPending = ensureOffsetInts(r.isPending, id)\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == -1 {\n\t\t\tr.isPending[id][i] = offset\n\t\t\treturn\n\t\t}\n\t}\n\tr.isPending[id] = append(r.isPending[id], offset)\n}\nfunc (r *results) unmarkPending(offset, id int) {\n\tfor i := range r.isPending[id] {\n\t\tif r.isPending[id][i] == offset {\n\t\t\tr.isPending[id][i] = -1\n\t\t\tbreak\n\t\t}\n\t}\n}\n\ntype context struct {\n\treader\t\tio.RuneReader\n\tkeywords\t[]parser\n\toffset\t\tint\n\treadOffset\tint\n\tconsumed\tint\n\toffsetLimit\tint\n\tfailOffset\tint\n\tfailingParser\tparser\n\treadErr\t\terror\n\teof\t\tbool\n\tresults\t\t*results\n\ttokens\t\t[]rune\n\tmatchLast\tbool\n}\n\nfunc newContext(r io.RuneReader, keywords []parser) *context {\n\treturn &context{reader: r, keywords: keywords, results: &results{}, offsetLimit: -1, failOffset: -1}\n}\nfunc (c *context) read() bool {\n\tif c.eof || c.readErr != nil {\n\t\treturn false\n\t}\n\ttoken, n, err := c.reader.ReadRune()\n\tif err != nil {\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tif n == 0 {\n\t\t\t\tc.eof = true\n\t\t\t\treturn false\n\t\t\t}\n\t\t} else {\n\t\t\tc.readErr = err\n\t\t\treturn false\n\t\t}\n\t}\n\tc.readOffset++\n\tif token == unicode.ReplacementChar {\n\t\tc.readErr = ErrInvalidUnicodeCharacter\n\t\treturn false\n\t}\n\tc.tokens = append(c.tokens, token)\n\treturn true\n}\nfunc (c *context) token() (rune, bool) {\n\tif c.offset == c.offsetLimit {\n\t\treturn 0, false\n\t}\n\tif c.offset == c.readOffset {\n\t\tif !c.read() {\n\t\t\treturn 0, false\n\t\t}\n\t}\n\treturn c.tokens[c.offset], true\n}\nfunc (c *context) fromResults(p parser) bool {\n\tto, m, ok := c.results.longestResult(c.offset, p.nodeID())\n\tif !ok {\n\t\treturn false\n\t}\n\tif m {\n\t\tc.success(to)\n\t} else {\n\t\tc.fail(c.offset)\n\t}\n\treturn true\n}\nfunc (c *context) isKeyword(from, to int) bool {\n\tol := c.offsetLimit\n\tc.offsetLimit = to\n\tdefer func() {\n\t\tc.offsetLimit = ol\n\t}()\n\tfor _, kw := range c.keywords {\n\t\tc.offset = from\n\t\tkw.parse(c)\n\t\tif c.matchLast && c.offset == to {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\nfunc (c *context) success(to int) {\n\tc.offset = to\n\tc.matchLast = true\n\tif to > c.consumed {\n\t\tc.consumed = to\n\t}\n}\nfunc (c *context) fail(offset int) {\n\tc.offset = offset\n\tc.matchLast = false\n}\nfunc findLine(tokens []rune, offset int) (line, column int) {\n\tif offset < 0 {\n\t\treturn 0, 0\n\t}\n\ttokens = tokens[:offset]\n\tfor i := range tokens {\n\t\tcolumn++\n\t\tif tokens[i] == '\\n' {\n\t\t\tcolumn = 0\n\t\t\tline++\n\t\t}\n\t}\n\treturn\n}\nfunc (c *context) parseError(p parser) error {\n\tdefinition := p.nodeName()\n\tflagIndex := strings.Index(definition, \":\")\n\tif flagIndex > 0 {\n\t\tdefinition = definition[:flagIndex]\n\t}\n\tif c.failingParser == nil {\n\t\tc.failOffset = c.consumed\n\t}\n\tline, col := findLine(c.tokens, c.failOffset)\n\treturn &ParseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition}\n}\nfunc (c *context) finalizeParse(root parser) error {\n\tfp := c.failingParser\n\tif fp == nil {\n\t\tfp = root\n\t}\n\tto, match, found := c.results.longestResult(0, root.nodeID())\n\tif !found || !match || found && match && to < c.readOffset {\n\t\treturn c.parseError(fp)\n\t}\n\tc.read()\n\tif c.eof {\n\t\treturn nil\n\t}\n\tif c.readErr != nil {\n\t\treturn c.readErr\n\t}\n\treturn c.parseError(root)\n}\n\ntype Node struct {\n\tName\tstring\n\tNodes\t[]Node\n\tFrom\tint\n\tTo\tint\n\ttokens\t[]rune\n}\n\nfunc (n Node) Tokens() []rune {\n\treturn n.tokens\n}\nfunc (n Node) String() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:%s\", n.Name, n.From, n.To, n.Text())\n}\nfunc (n Node) Text() string {\n\treturn string(n.Tokens()[n.From:n.To])\n}\n\ntype CommitType int\n\nconst (\n\tNone\tCommitType\t= 0\n\tAlias\tCommitType\t= 1 << iota\n\tWhitespace\n\tNoWhitespace\n\tKeyword\n\tNoKeyword\n\tFailPass\n\tNoFailPass\n\tRoot\n\tuserDefined\n)\n\ntype formatFlags int\n\nconst (\n\tformatNone\tformatFlags\t= 0\n\tformatPretty\tformatFlags\t= 1 << iota\n\tformatIncludeComments\n)\n\ntype formatOptions struct {\n\tmode\t\tformatFlags\n\ttargetWidth\tint\n}\ntype ParseError struct {\n\tInput\t\tstring\n\tOffset\t\tint\n\tLine\t\tint\n\tColumn\t\tint\n\tDefinition\tstring\n}\ntype parser interface {\n\tnodeName() string\n\tnodeID() int\n\tcommitType() CommitType\n\tparse(*context)\n}\ntype builder interface {\n\tnodeName() string\n\tnodeID() int\n\tbuild(*context) ([]Node, bool)\n}\n\nvar ErrInvalidUnicodeCharacter = errors.New(\"invalid unicode character\")\n\nfunc (pe *ParseError) Error() string {\n\treturn fmt.Sprintf(\"%s:%d:%d:parse failed, parsing: %s\", pe.Input, pe.Line+1, pe.Column+1, pe.Definition)\n}\nfunc parseInput(r io.Reader, p parser, b builder, kw []parser) (Node, error) {\n\tc := newContext(bufio.NewReader(r), kw)\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn Node{}, c.readErr\n\t}\n\tif err := c.finalizeParse(p); err != nil {\n\t\tif perr, ok := err.(*ParseError); ok {\n\t\t\tperr.Input = \"\"\n\t\t}\n\t\treturn Node{}, err\n\t}\n\tc.offset = 0\n\tc.results.resetPending()\n\tn, _ := b.build(c)\n\treturn n[0], nil\n}\n" diff --git a/internal/self/self.gen.go b/internal/self/self.gen.go index 0cb4bea..7a7eb53 100644 --- a/internal/self/self.gen.go +++ b/internal/self/self.gen.go @@ -758,6 +758,7 @@ const ( Keyword NoKeyword FailPass + NoFailPass Root userDefined ) @@ -820,15 +821,15 @@ func parseInput(r io.Reader, p parser, b builder, kw []parser) (Node, error) { func Parse(r io.Reader) (Node, error) { - var p172 = sequenceParser{id: 172, commit: 128, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var p170 = choiceParser{id: 170, commit: 2} - var p169 = choiceParser{id: 169, commit: 262, name: "wsc", generalizations: []int{170}} - var p2 = sequenceParser{id: 2, commit: 322, name: "wschar", allChars: true, ranges: [][]int{{1, 1}}, generalizations: []int{169, 170}} + var p183 = sequenceParser{id: 183, commit: 256, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var p181 = choiceParser{id: 181, commit: 2} + var p180 = choiceParser{id: 180, commit: 518, name: "wsc", generalizations: []int{181}} + var p2 = sequenceParser{id: 2, commit: 578, name: "wschar", allChars: true, ranges: [][]int{{1, 1}}, generalizations: []int{180, 181}} var p1 = charParser{id: 1, chars: []rune{32, 9, 10, 8, 12, 13, 11}} p2.items = []parser{&p1} - var p30 = sequenceParser{id: 30, commit: 264, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{169, 170}} - var p26 = choiceParser{id: 26, commit: 330, name: "comment-segment"} - var p25 = sequenceParser{id: 25, commit: 330, name: "line-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{26}} + var p30 = sequenceParser{id: 30, commit: 520, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{180, 181}} + var p26 = choiceParser{id: 26, commit: 586, name: "comment-segment"} + var p25 = sequenceParser{id: 25, commit: 586, name: "line-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{26}} var p22 = sequenceParser{id: 22, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} var p20 = charParser{id: 20, chars: []rune{47}} var p21 = charParser{id: 21, chars: []rune{47}} @@ -837,7 +838,7 @@ func Parse(r io.Reader) (Node, error) { var p23 = charParser{id: 23, not: true, chars: []rune{10}} p24.items = []parser{&p23} p25.items = []parser{&p22, &p24} - var p19 = sequenceParser{id: 19, commit: 330, name: "block-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{26}} + var p19 = sequenceParser{id: 19, commit: 586, name: "block-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{26}} var p7 = sequenceParser{id: 7, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} var p5 = charParser{id: 5, chars: []rune{47}} var p6 = charParser{id: 6, chars: []rune{42}} @@ -862,7 +863,7 @@ func Parse(r io.Reader) (Node, error) { p19.items = []parser{&p7, &p15, &p18} p26.options = []parser{&p25, &p19} var p29 = sequenceParser{id: 29, commit: 10, ranges: [][]int{{0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}} - var p4 = sequenceParser{id: 4, commit: 330, name: "ws-no-nl", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var p4 = sequenceParser{id: 4, commit: 586, name: "ws-no-nl", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p3 = charParser{id: 3, chars: []rune{32, 9, 8, 12, 13, 11}} p4.items = []parser{&p3} var p28 = sequenceParser{id: 28, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} @@ -870,57 +871,57 @@ func Parse(r io.Reader) (Node, error) { p28.items = []parser{&p27} p29.items = []parser{&p4, &p28, &p4, &p26} p30.items = []parser{&p26, &p29} - p169.options = []parser{&p2, &p30} - p170.options = []parser{&p169} - var p171 = sequenceParser{id: 171, commit: 258, name: "syntax:wsroot", ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}} - var p166 = sequenceParser{id: 166, commit: 2, ranges: [][]int{{1, 1}, {0, -1}}} - var p162 = sequenceParser{id: 162, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var p161 = charParser{id: 161, chars: []rune{59}} - p162.items = []parser{&p161} - var p165 = sequenceParser{id: 165, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - p165.items = []parser{&p170, &p162} - p166.items = []parser{&p162, &p165} - var p160 = sequenceParser{id: 160, commit: 322, name: "definitions", ranges: [][]int{{1, 1}, {0, 1}}} - var p153 = sequenceParser{id: 153, commit: 256, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} - var p150 = sequenceParser{id: 150, commit: 330, name: "definition-name", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} - var p68 = sequenceParser{id: 68, commit: 264, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{74, 100, 104}} + p180.options = []parser{&p2, &p30} + p181.options = []parser{&p180} + var p182 = sequenceParser{id: 182, commit: 514, name: "syntax:wsroot", ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}} + var p177 = sequenceParser{id: 177, commit: 2, ranges: [][]int{{1, 1}, {0, -1}}} + var p173 = sequenceParser{id: 173, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var p172 = charParser{id: 172, chars: []rune{59}} + p173.items = []parser{&p172} + var p176 = sequenceParser{id: 176, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} + p176.items = []parser{&p181, &p173} + p177.items = []parser{&p173, &p176} + var p171 = sequenceParser{id: 171, commit: 578, name: "definitions", ranges: [][]int{{1, 1}, {0, 1}}} + var p164 = sequenceParser{id: 164, commit: 512, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} + var p161 = sequenceParser{id: 161, commit: 586, name: "definition-name", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} + var p68 = sequenceParser{id: 68, commit: 520, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{74, 100, 104}} var p67 = sequenceParser{id: 67, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p66 = charParser{id: 66, not: true, chars: []rune{92, 32, 10, 9, 8, 12, 13, 11, 47, 46, 91, 93, 34, 123, 125, 94, 43, 42, 63, 124, 40, 41, 58, 61, 59}} p67.items = []parser{&p66} p68.items = []parser{&p67} - var p149 = sequenceParser{id: 149, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var p148 = sequenceParser{id: 148, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var p147 = charParser{id: 147, chars: []rune{58}} - p148.items = []parser{&p147} - var p146 = choiceParser{id: 146, commit: 322, name: "flag"} - var p115 = sequenceParser{id: 115, commit: 264, name: "alias", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var p160 = sequenceParser{id: 160, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var p159 = sequenceParser{id: 159, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var p158 = charParser{id: 158, chars: []rune{58}} + p159.items = []parser{&p158} + var p157 = choiceParser{id: 157, commit: 578, name: "flag"} + var p115 = sequenceParser{id: 115, commit: 520, name: "alias", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var p110 = charParser{id: 110, chars: []rune{97}} var p111 = charParser{id: 111, chars: []rune{108}} var p112 = charParser{id: 112, chars: []rune{105}} var p113 = charParser{id: 113, chars: []rune{97}} var p114 = charParser{id: 114, chars: []rune{115}} p115.items = []parser{&p110, &p111, &p112, &p113, &p114} - var p118 = sequenceParser{id: 118, commit: 264, name: "ws", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var p118 = sequenceParser{id: 118, commit: 520, name: "ws", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var p116 = charParser{id: 116, chars: []rune{119}} var p117 = charParser{id: 117, chars: []rune{115}} p118.items = []parser{&p116, &p117} - var p123 = sequenceParser{id: 123, commit: 264, name: "nows", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var p123 = sequenceParser{id: 123, commit: 520, name: "nows", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var p119 = charParser{id: 119, chars: []rune{110}} var p120 = charParser{id: 120, chars: []rune{111}} var p121 = charParser{id: 121, chars: []rune{119}} var p122 = charParser{id: 122, chars: []rune{115}} p123.items = []parser{&p119, &p120, &p121, &p122} - var p126 = sequenceParser{id: 126, commit: 264, name: "kw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var p126 = sequenceParser{id: 126, commit: 520, name: "kw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var p124 = charParser{id: 124, chars: []rune{107}} var p125 = charParser{id: 125, chars: []rune{119}} p126.items = []parser{&p124, &p125} - var p131 = sequenceParser{id: 131, commit: 264, name: "nokw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var p131 = sequenceParser{id: 131, commit: 520, name: "nokw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var p127 = charParser{id: 127, chars: []rune{110}} var p128 = charParser{id: 128, chars: []rune{111}} var p129 = charParser{id: 129, chars: []rune{107}} var p130 = charParser{id: 130, chars: []rune{119}} p131.items = []parser{&p127, &p128, &p129, &p130} - var p140 = sequenceParser{id: 140, commit: 264, name: "failpass", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var p140 = sequenceParser{id: 140, commit: 520, name: "failpass", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var p132 = charParser{id: 132, chars: []rune{102}} var p133 = charParser{id: 133, chars: []rune{97}} var p134 = charParser{id: 134, chars: []rune{105}} @@ -930,32 +931,44 @@ func Parse(r io.Reader) (Node, error) { var p138 = charParser{id: 138, chars: []rune{115}} var p139 = charParser{id: 139, chars: []rune{115}} p140.items = []parser{&p132, &p133, &p134, &p135, &p136, &p137, &p138, &p139} - var p145 = sequenceParser{id: 145, commit: 264, name: "root", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} - var p141 = charParser{id: 141, chars: []rune{114}} + var p151 = sequenceParser{id: 151, commit: 520, name: "nofailpass", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} + var p141 = charParser{id: 141, chars: []rune{110}} var p142 = charParser{id: 142, chars: []rune{111}} - var p143 = charParser{id: 143, chars: []rune{111}} - var p144 = charParser{id: 144, chars: []rune{116}} - p145.items = []parser{&p141, &p142, &p143, &p144} - p146.options = []parser{&p115, &p118, &p123, &p126, &p131, &p140, &p145} - p149.items = []parser{&p148, &p146} - p150.items = []parser{&p68, &p149} - var p152 = sequenceParser{id: 152, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var p151 = charParser{id: 151, chars: []rune{61}} - p152.items = []parser{&p151} - var p74 = choiceParser{id: 74, commit: 322, name: "expression"} - var p65 = choiceParser{id: 65, commit: 322, name: "terminal", generalizations: []int{74, 100, 104}} - var p32 = sequenceParser{id: 32, commit: 264, name: "any-char", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} + var p143 = charParser{id: 143, chars: []rune{102}} + var p144 = charParser{id: 144, chars: []rune{97}} + var p145 = charParser{id: 145, chars: []rune{105}} + var p146 = charParser{id: 146, chars: []rune{108}} + var p147 = charParser{id: 147, chars: []rune{112}} + var p148 = charParser{id: 148, chars: []rune{97}} + var p149 = charParser{id: 149, chars: []rune{115}} + var p150 = charParser{id: 150, chars: []rune{115}} + p151.items = []parser{&p141, &p142, &p143, &p144, &p145, &p146, &p147, &p148, &p149, &p150} + var p156 = sequenceParser{id: 156, commit: 520, name: "root", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} + var p152 = charParser{id: 152, chars: []rune{114}} + var p153 = charParser{id: 153, chars: []rune{111}} + var p154 = charParser{id: 154, chars: []rune{111}} + var p155 = charParser{id: 155, chars: []rune{116}} + p156.items = []parser{&p152, &p153, &p154, &p155} + p157.options = []parser{&p115, &p118, &p123, &p126, &p131, &p140, &p151, &p156} + p160.items = []parser{&p159, &p157} + p161.items = []parser{&p68, &p160} + var p163 = sequenceParser{id: 163, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var p162 = charParser{id: 162, chars: []rune{61}} + p163.items = []parser{&p162} + var p74 = choiceParser{id: 74, commit: 578, name: "expression"} + var p65 = choiceParser{id: 65, commit: 578, name: "terminal", generalizations: []int{74, 100, 104}} + var p32 = sequenceParser{id: 32, commit: 520, name: "any-char", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} var p31 = charParser{id: 31, chars: []rune{46}} p32.items = []parser{&p31} - var p51 = sequenceParser{id: 51, commit: 264, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} + var p51 = sequenceParser{id: 51, commit: 520, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} var p47 = sequenceParser{id: 47, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p46 = charParser{id: 46, chars: []rune{91}} p47.items = []parser{&p46} - var p34 = sequenceParser{id: 34, commit: 264, name: "class-not", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var p34 = sequenceParser{id: 34, commit: 520, name: "class-not", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p33 = charParser{id: 33, chars: []rune{94}} p34.items = []parser{&p33} var p48 = choiceParser{id: 48, commit: 10} - var p42 = choiceParser{id: 42, commit: 264, name: "class-char", generalizations: []int{48}} + var p42 = choiceParser{id: 42, commit: 520, name: "class-char", generalizations: []int{48}} var p36 = sequenceParser{id: 36, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{42, 48}} var p35 = charParser{id: 35, not: true, chars: []rune{92, 91, 93, 94, 45}} p36.items = []parser{&p35} @@ -968,7 +981,7 @@ func Parse(r io.Reader) (Node, error) { p40.items = []parser{&p39} p41.items = []parser{&p38, &p40} p42.options = []parser{&p36, &p41} - var p45 = sequenceParser{id: 45, commit: 264, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{48}} + var p45 = sequenceParser{id: 45, commit: 520, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{48}} var p44 = sequenceParser{id: 44, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p43 = charParser{id: 43, chars: []rune{45}} p44.items = []parser{&p43} @@ -978,11 +991,11 @@ func Parse(r io.Reader) (Node, error) { var p49 = charParser{id: 49, chars: []rune{93}} p50.items = []parser{&p49} p51.items = []parser{&p47, &p34, &p48, &p50} - var p64 = sequenceParser{id: 64, commit: 264, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} + var p64 = sequenceParser{id: 64, commit: 520, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} var p61 = sequenceParser{id: 61, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p60 = charParser{id: 60, chars: []rune{34}} p61.items = []parser{&p60} - var p59 = choiceParser{id: 59, commit: 264, name: "sequence-char"} + var p59 = choiceParser{id: 59, commit: 520, name: "sequence-char"} var p53 = sequenceParser{id: 53, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{59}} var p52 = charParser{id: 52, not: true, chars: []rune{92, 34}} p53.items = []parser{&p52} @@ -1000,25 +1013,25 @@ func Parse(r io.Reader) (Node, error) { p63.items = []parser{&p62} p64.items = []parser{&p61, &p59, &p63} p65.options = []parser{&p32, &p51, &p64} - var p73 = sequenceParser{id: 73, commit: 322, name: "group", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{74, 100, 104}} + var p73 = sequenceParser{id: 73, commit: 578, name: "group", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{74, 100, 104}} var p70 = sequenceParser{id: 70, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p69 = charParser{id: 69, chars: []rune{40}} p70.items = []parser{&p69} var p72 = sequenceParser{id: 72, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p71 = charParser{id: 71, chars: []rune{41}} p72.items = []parser{&p71} - p73.items = []parser{&p70, &p170, &p74, &p170, &p72} - var p103 = sequenceParser{id: 103, commit: 256, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{74, 104}} - var p101 = sequenceParser{id: 101, commit: 264, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}} + p73.items = []parser{&p70, &p181, &p74, &p181, &p72} + var p103 = sequenceParser{id: 103, commit: 512, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{74, 104}} + var p101 = sequenceParser{id: 101, commit: 520, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}} var p100 = choiceParser{id: 100, commit: 10} p100.options = []parser{&p65, &p68, &p73} - var p99 = choiceParser{id: 99, commit: 322, name: "quantity"} - var p83 = sequenceParser{id: 83, commit: 256, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} + var p99 = choiceParser{id: 99, commit: 578, name: "quantity"} + var p83 = sequenceParser{id: 83, commit: 512, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} var p80 = sequenceParser{id: 80, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p79 = charParser{id: 79, chars: []rune{123}} p80.items = []parser{&p79} - var p78 = sequenceParser{id: 78, commit: 256, name: "count", ranges: [][]int{{1, 1}}} - var p77 = sequenceParser{id: 77, commit: 330, name: "number", ranges: [][]int{{1, -1}, {1, -1}}} + var p78 = sequenceParser{id: 78, commit: 512, name: "count", ranges: [][]int{{1, 1}}} + var p77 = sequenceParser{id: 77, commit: 586, name: "number", ranges: [][]int{{1, -1}, {1, -1}}} var p76 = sequenceParser{id: 76, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p75 = charParser{id: 75, ranges: [][]rune{{48, 57}}} p76.items = []parser{&p75} @@ -1027,79 +1040,79 @@ func Parse(r io.Reader) (Node, error) { var p82 = sequenceParser{id: 82, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p81 = charParser{id: 81, chars: []rune{125}} p82.items = []parser{&p81} - p83.items = []parser{&p80, &p170, &p78, &p170, &p82} - var p92 = sequenceParser{id: 92, commit: 256, name: "range-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} + p83.items = []parser{&p80, &p181, &p78, &p181, &p82} + var p92 = sequenceParser{id: 92, commit: 512, name: "range-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} var p87 = sequenceParser{id: 87, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p86 = charParser{id: 86, chars: []rune{123}} p87.items = []parser{&p86} - var p84 = sequenceParser{id: 84, commit: 256, name: "range-from", ranges: [][]int{{1, 1}}} + var p84 = sequenceParser{id: 84, commit: 512, name: "range-from", ranges: [][]int{{1, 1}}} p84.items = []parser{&p77} var p89 = sequenceParser{id: 89, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p88 = charParser{id: 88, chars: []rune{44}} p89.items = []parser{&p88} - var p85 = sequenceParser{id: 85, commit: 256, name: "range-to", ranges: [][]int{{1, 1}}} + var p85 = sequenceParser{id: 85, commit: 512, name: "range-to", ranges: [][]int{{1, 1}}} p85.items = []parser{&p77} var p91 = sequenceParser{id: 91, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p90 = charParser{id: 90, chars: []rune{125}} p91.items = []parser{&p90} - p92.items = []parser{&p87, &p170, &p84, &p170, &p89, &p170, &p85, &p170, &p91} - var p94 = sequenceParser{id: 94, commit: 264, name: "one-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} + p92.items = []parser{&p87, &p181, &p84, &p181, &p89, &p181, &p85, &p181, &p91} + var p94 = sequenceParser{id: 94, commit: 520, name: "one-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} var p93 = charParser{id: 93, chars: []rune{43}} p94.items = []parser{&p93} - var p96 = sequenceParser{id: 96, commit: 264, name: "zero-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} + var p96 = sequenceParser{id: 96, commit: 520, name: "zero-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} var p95 = charParser{id: 95, chars: []rune{42}} p96.items = []parser{&p95} - var p98 = sequenceParser{id: 98, commit: 264, name: "zero-or-one", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} + var p98 = sequenceParser{id: 98, commit: 520, name: "zero-or-one", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} var p97 = charParser{id: 97, chars: []rune{63}} p98.items = []parser{&p97} p99.options = []parser{&p83, &p92, &p94, &p96, &p98} p101.items = []parser{&p100, &p99} var p102 = sequenceParser{id: 102, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - p102.items = []parser{&p170, &p101} + p102.items = []parser{&p181, &p101} p103.items = []parser{&p101, &p102} - var p109 = sequenceParser{id: 109, commit: 256, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{74}} - var p104 = choiceParser{id: 104, commit: 322, name: "option"} + var p109 = sequenceParser{id: 109, commit: 512, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{74}} + var p104 = choiceParser{id: 104, commit: 578, name: "option"} p104.options = []parser{&p65, &p68, &p73, &p103} var p107 = sequenceParser{id: 107, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}} var p106 = sequenceParser{id: 106, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var p105 = charParser{id: 105, chars: []rune{124}} p106.items = []parser{&p105} - p107.items = []parser{&p106, &p170, &p104} + p107.items = []parser{&p106, &p181, &p104} var p108 = sequenceParser{id: 108, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - p108.items = []parser{&p170, &p107} - p109.items = []parser{&p104, &p170, &p107, &p108} + p108.items = []parser{&p181, &p107} + p109.items = []parser{&p104, &p181, &p107, &p108} p74.options = []parser{&p65, &p68, &p73, &p103, &p109} - p153.items = []parser{&p150, &p170, &p152, &p170, &p74} - var p159 = sequenceParser{id: 159, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var p157 = sequenceParser{id: 157, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}} - var p155 = sequenceParser{id: 155, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var p154 = charParser{id: 154, chars: []rune{59}} - p155.items = []parser{&p154} - var p156 = sequenceParser{id: 156, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - p156.items = []parser{&p170, &p155} - p157.items = []parser{&p155, &p156, &p170, &p153} - var p158 = sequenceParser{id: 158, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - p158.items = []parser{&p170, &p157} - p159.items = []parser{&p170, &p157, &p158} - p160.items = []parser{&p153, &p159} - var p168 = sequenceParser{id: 168, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var p164 = sequenceParser{id: 164, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var p163 = charParser{id: 163, chars: []rune{59}} - p164.items = []parser{&p163} + p164.items = []parser{&p161, &p181, &p163, &p181, &p74} + var p170 = sequenceParser{id: 170, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var p168 = sequenceParser{id: 168, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}} + var p166 = sequenceParser{id: 166, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var p165 = charParser{id: 165, chars: []rune{59}} + p166.items = []parser{&p165} var p167 = sequenceParser{id: 167, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - p167.items = []parser{&p170, &p164} - p168.items = []parser{&p170, &p164, &p167} - p171.items = []parser{&p166, &p170, &p160, &p168} - p172.items = []parser{&p170, &p171, &p170} - var b172 = sequenceBuilder{id: 172, commit: 128, name: "syntax", ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var b170 = choiceBuilder{id: 170, commit: 2} - var b169 = choiceBuilder{id: 169, commit: 262, generalizations: []int{170}} - var b2 = sequenceBuilder{id: 2, commit: 322, allChars: true, ranges: [][]int{{1, 1}}, generalizations: []int{169, 170}} + p167.items = []parser{&p181, &p166} + p168.items = []parser{&p166, &p167, &p181, &p164} + var p169 = sequenceParser{id: 169, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} + p169.items = []parser{&p181, &p168} + p170.items = []parser{&p181, &p168, &p169} + p171.items = []parser{&p164, &p170} + var p179 = sequenceParser{id: 179, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var p175 = sequenceParser{id: 175, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var p174 = charParser{id: 174, chars: []rune{59}} + p175.items = []parser{&p174} + var p178 = sequenceParser{id: 178, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} + p178.items = []parser{&p181, &p175} + p179.items = []parser{&p181, &p175, &p178} + p182.items = []parser{&p177, &p181, &p171, &p179} + p183.items = []parser{&p181, &p182, &p181} + var b183 = sequenceBuilder{id: 183, commit: 256, name: "syntax", ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var b181 = choiceBuilder{id: 181, commit: 2} + var b180 = choiceBuilder{id: 180, commit: 518, generalizations: []int{181}} + var b2 = sequenceBuilder{id: 2, commit: 578, allChars: true, ranges: [][]int{{1, 1}}, generalizations: []int{180, 181}} var b1 = charBuilder{} b2.items = []builder{&b1} - var b30 = sequenceBuilder{id: 30, commit: 264, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{169, 170}} - var b26 = choiceBuilder{id: 26, commit: 330} - var b25 = sequenceBuilder{id: 25, commit: 330, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{26}} + var b30 = sequenceBuilder{id: 30, commit: 520, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{180, 181}} + var b26 = choiceBuilder{id: 26, commit: 586} + var b25 = sequenceBuilder{id: 25, commit: 586, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{26}} var b22 = sequenceBuilder{id: 22, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} var b20 = charBuilder{} var b21 = charBuilder{} @@ -1108,7 +1121,7 @@ func Parse(r io.Reader) (Node, error) { var b23 = charBuilder{} b24.items = []builder{&b23} b25.items = []builder{&b22, &b24} - var b19 = sequenceBuilder{id: 19, commit: 330, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{26}} + var b19 = sequenceBuilder{id: 19, commit: 586, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{26}} var b7 = sequenceBuilder{id: 7, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} var b5 = charBuilder{} var b6 = charBuilder{} @@ -1133,7 +1146,7 @@ func Parse(r io.Reader) (Node, error) { b19.items = []builder{&b7, &b15, &b18} b26.options = []builder{&b25, &b19} var b29 = sequenceBuilder{id: 29, commit: 10, ranges: [][]int{{0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}} - var b4 = sequenceBuilder{id: 4, commit: 330, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b4 = sequenceBuilder{id: 4, commit: 586, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b3 = charBuilder{} b4.items = []builder{&b3} var b28 = sequenceBuilder{id: 28, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} @@ -1141,57 +1154,57 @@ func Parse(r io.Reader) (Node, error) { b28.items = []builder{&b27} b29.items = []builder{&b4, &b28, &b4, &b26} b30.items = []builder{&b26, &b29} - b169.options = []builder{&b2, &b30} - b170.options = []builder{&b169} - var b171 = sequenceBuilder{id: 171, commit: 258, ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}} - var b166 = sequenceBuilder{id: 166, commit: 2, ranges: [][]int{{1, 1}, {0, -1}}} - var b162 = sequenceBuilder{id: 162, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b161 = charBuilder{} - b162.items = []builder{&b161} - var b165 = sequenceBuilder{id: 165, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - b165.items = []builder{&b170, &b162} - b166.items = []builder{&b162, &b165} - var b160 = sequenceBuilder{id: 160, commit: 322, ranges: [][]int{{1, 1}, {0, 1}}} - var b153 = sequenceBuilder{id: 153, commit: 256, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} - var b150 = sequenceBuilder{id: 150, commit: 330, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} - var b68 = sequenceBuilder{id: 68, commit: 264, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{74, 100, 104}} + b180.options = []builder{&b2, &b30} + b181.options = []builder{&b180} + var b182 = sequenceBuilder{id: 182, commit: 514, ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}} + var b177 = sequenceBuilder{id: 177, commit: 2, ranges: [][]int{{1, 1}, {0, -1}}} + var b173 = sequenceBuilder{id: 173, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b172 = charBuilder{} + b173.items = []builder{&b172} + var b176 = sequenceBuilder{id: 176, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} + b176.items = []builder{&b181, &b173} + b177.items = []builder{&b173, &b176} + var b171 = sequenceBuilder{id: 171, commit: 578, ranges: [][]int{{1, 1}, {0, 1}}} + var b164 = sequenceBuilder{id: 164, commit: 512, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} + var b161 = sequenceBuilder{id: 161, commit: 586, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} + var b68 = sequenceBuilder{id: 68, commit: 520, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{74, 100, 104}} var b67 = sequenceBuilder{id: 67, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b66 = charBuilder{} b67.items = []builder{&b66} b68.items = []builder{&b67} - var b149 = sequenceBuilder{id: 149, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b148 = sequenceBuilder{id: 148, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b147 = charBuilder{} - b148.items = []builder{&b147} - var b146 = choiceBuilder{id: 146, commit: 322} - var b115 = sequenceBuilder{id: 115, commit: 264, name: "alias", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var b160 = sequenceBuilder{id: 160, commit: 10, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b159 = sequenceBuilder{id: 159, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b158 = charBuilder{} + b159.items = []builder{&b158} + var b157 = choiceBuilder{id: 157, commit: 578} + var b115 = sequenceBuilder{id: 115, commit: 520, name: "alias", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var b110 = charBuilder{} var b111 = charBuilder{} var b112 = charBuilder{} var b113 = charBuilder{} var b114 = charBuilder{} b115.items = []builder{&b110, &b111, &b112, &b113, &b114} - var b118 = sequenceBuilder{id: 118, commit: 264, name: "ws", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var b118 = sequenceBuilder{id: 118, commit: 520, name: "ws", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var b116 = charBuilder{} var b117 = charBuilder{} b118.items = []builder{&b116, &b117} - var b123 = sequenceBuilder{id: 123, commit: 264, name: "nows", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var b123 = sequenceBuilder{id: 123, commit: 520, name: "nows", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var b119 = charBuilder{} var b120 = charBuilder{} var b121 = charBuilder{} var b122 = charBuilder{} b123.items = []builder{&b119, &b120, &b121, &b122} - var b126 = sequenceBuilder{id: 126, commit: 264, name: "kw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var b126 = sequenceBuilder{id: 126, commit: 520, name: "kw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var b124 = charBuilder{} var b125 = charBuilder{} b126.items = []builder{&b124, &b125} - var b131 = sequenceBuilder{id: 131, commit: 264, name: "nokw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var b131 = sequenceBuilder{id: 131, commit: 520, name: "nokw", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var b127 = charBuilder{} var b128 = charBuilder{} var b129 = charBuilder{} var b130 = charBuilder{} b131.items = []builder{&b127, &b128, &b129, &b130} - var b140 = sequenceBuilder{id: 140, commit: 264, name: "failpass", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var b140 = sequenceBuilder{id: 140, commit: 520, name: "failpass", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var b132 = charBuilder{} var b133 = charBuilder{} var b134 = charBuilder{} @@ -1201,32 +1214,44 @@ func Parse(r io.Reader) (Node, error) { var b138 = charBuilder{} var b139 = charBuilder{} b140.items = []builder{&b132, &b133, &b134, &b135, &b136, &b137, &b138, &b139} - var b145 = sequenceBuilder{id: 145, commit: 264, name: "root", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{146}} + var b151 = sequenceBuilder{id: 151, commit: 520, name: "nofailpass", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} var b141 = charBuilder{} var b142 = charBuilder{} var b143 = charBuilder{} var b144 = charBuilder{} - b145.items = []builder{&b141, &b142, &b143, &b144} - b146.options = []builder{&b115, &b118, &b123, &b126, &b131, &b140, &b145} - b149.items = []builder{&b148, &b146} - b150.items = []builder{&b68, &b149} - var b152 = sequenceBuilder{id: 152, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b151 = charBuilder{} - b152.items = []builder{&b151} - var b74 = choiceBuilder{id: 74, commit: 322} - var b65 = choiceBuilder{id: 65, commit: 322, generalizations: []int{74, 100, 104}} - var b32 = sequenceBuilder{id: 32, commit: 264, name: "any-char", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} + var b145 = charBuilder{} + var b146 = charBuilder{} + var b147 = charBuilder{} + var b148 = charBuilder{} + var b149 = charBuilder{} + var b150 = charBuilder{} + b151.items = []builder{&b141, &b142, &b143, &b144, &b145, &b146, &b147, &b148, &b149, &b150} + var b156 = sequenceBuilder{id: 156, commit: 520, name: "root", allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{157}} + var b152 = charBuilder{} + var b153 = charBuilder{} + var b154 = charBuilder{} + var b155 = charBuilder{} + b156.items = []builder{&b152, &b153, &b154, &b155} + b157.options = []builder{&b115, &b118, &b123, &b126, &b131, &b140, &b151, &b156} + b160.items = []builder{&b159, &b157} + b161.items = []builder{&b68, &b160} + var b163 = sequenceBuilder{id: 163, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b162 = charBuilder{} + b163.items = []builder{&b162} + var b74 = choiceBuilder{id: 74, commit: 578} + var b65 = choiceBuilder{id: 65, commit: 578, generalizations: []int{74, 100, 104}} + var b32 = sequenceBuilder{id: 32, commit: 520, name: "any-char", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} var b31 = charBuilder{} b32.items = []builder{&b31} - var b51 = sequenceBuilder{id: 51, commit: 264, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} + var b51 = sequenceBuilder{id: 51, commit: 520, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} var b47 = sequenceBuilder{id: 47, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b46 = charBuilder{} b47.items = []builder{&b46} - var b34 = sequenceBuilder{id: 34, commit: 264, name: "class-not", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b34 = sequenceBuilder{id: 34, commit: 520, name: "class-not", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b33 = charBuilder{} b34.items = []builder{&b33} var b48 = choiceBuilder{id: 48, commit: 10} - var b42 = choiceBuilder{id: 42, commit: 264, name: "class-char", generalizations: []int{48}} + var b42 = choiceBuilder{id: 42, commit: 520, name: "class-char", generalizations: []int{48}} var b36 = sequenceBuilder{id: 36, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{42, 48}} var b35 = charBuilder{} b36.items = []builder{&b35} @@ -1239,7 +1264,7 @@ func Parse(r io.Reader) (Node, error) { b40.items = []builder{&b39} b41.items = []builder{&b38, &b40} b42.options = []builder{&b36, &b41} - var b45 = sequenceBuilder{id: 45, commit: 264, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{48}} + var b45 = sequenceBuilder{id: 45, commit: 520, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{48}} var b44 = sequenceBuilder{id: 44, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b43 = charBuilder{} b44.items = []builder{&b43} @@ -1249,11 +1274,11 @@ func Parse(r io.Reader) (Node, error) { var b49 = charBuilder{} b50.items = []builder{&b49} b51.items = []builder{&b47, &b34, &b48, &b50} - var b64 = sequenceBuilder{id: 64, commit: 264, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} + var b64 = sequenceBuilder{id: 64, commit: 520, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{65, 74, 100, 104}} var b61 = sequenceBuilder{id: 61, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b60 = charBuilder{} b61.items = []builder{&b60} - var b59 = choiceBuilder{id: 59, commit: 264, name: "sequence-char"} + var b59 = choiceBuilder{id: 59, commit: 520, name: "sequence-char"} var b53 = sequenceBuilder{id: 53, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{59}} var b52 = charBuilder{} b53.items = []builder{&b52} @@ -1271,25 +1296,25 @@ func Parse(r io.Reader) (Node, error) { b63.items = []builder{&b62} b64.items = []builder{&b61, &b59, &b63} b65.options = []builder{&b32, &b51, &b64} - var b73 = sequenceBuilder{id: 73, commit: 322, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{74, 100, 104}} + var b73 = sequenceBuilder{id: 73, commit: 578, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{74, 100, 104}} var b70 = sequenceBuilder{id: 70, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b69 = charBuilder{} b70.items = []builder{&b69} var b72 = sequenceBuilder{id: 72, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b71 = charBuilder{} b72.items = []builder{&b71} - b73.items = []builder{&b70, &b170, &b74, &b170, &b72} - var b103 = sequenceBuilder{id: 103, commit: 256, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{74, 104}} - var b101 = sequenceBuilder{id: 101, commit: 264, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}} + b73.items = []builder{&b70, &b181, &b74, &b181, &b72} + var b103 = sequenceBuilder{id: 103, commit: 512, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{74, 104}} + var b101 = sequenceBuilder{id: 101, commit: 520, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}} var b100 = choiceBuilder{id: 100, commit: 10} b100.options = []builder{&b65, &b68, &b73} - var b99 = choiceBuilder{id: 99, commit: 322} - var b83 = sequenceBuilder{id: 83, commit: 256, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} + var b99 = choiceBuilder{id: 99, commit: 578} + var b83 = sequenceBuilder{id: 83, commit: 512, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} var b80 = sequenceBuilder{id: 80, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b79 = charBuilder{} b80.items = []builder{&b79} - var b78 = sequenceBuilder{id: 78, commit: 256, name: "count", ranges: [][]int{{1, 1}}} - var b77 = sequenceBuilder{id: 77, commit: 330, ranges: [][]int{{1, -1}, {1, -1}}} + var b78 = sequenceBuilder{id: 78, commit: 512, name: "count", ranges: [][]int{{1, 1}}} + var b77 = sequenceBuilder{id: 77, commit: 586, ranges: [][]int{{1, -1}, {1, -1}}} var b76 = sequenceBuilder{id: 76, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b75 = charBuilder{} b76.items = []builder{&b75} @@ -1298,72 +1323,72 @@ func Parse(r io.Reader) (Node, error) { var b82 = sequenceBuilder{id: 82, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b81 = charBuilder{} b82.items = []builder{&b81} - b83.items = []builder{&b80, &b170, &b78, &b170, &b82} - var b92 = sequenceBuilder{id: 92, commit: 256, name: "range-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} + b83.items = []builder{&b80, &b181, &b78, &b181, &b82} + var b92 = sequenceBuilder{id: 92, commit: 512, name: "range-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{99}} var b87 = sequenceBuilder{id: 87, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b86 = charBuilder{} b87.items = []builder{&b86} - var b84 = sequenceBuilder{id: 84, commit: 256, name: "range-from", ranges: [][]int{{1, 1}}} + var b84 = sequenceBuilder{id: 84, commit: 512, name: "range-from", ranges: [][]int{{1, 1}}} b84.items = []builder{&b77} var b89 = sequenceBuilder{id: 89, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b88 = charBuilder{} b89.items = []builder{&b88} - var b85 = sequenceBuilder{id: 85, commit: 256, name: "range-to", ranges: [][]int{{1, 1}}} + var b85 = sequenceBuilder{id: 85, commit: 512, name: "range-to", ranges: [][]int{{1, 1}}} b85.items = []builder{&b77} var b91 = sequenceBuilder{id: 91, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b90 = charBuilder{} b91.items = []builder{&b90} - b92.items = []builder{&b87, &b170, &b84, &b170, &b89, &b170, &b85, &b170, &b91} - var b94 = sequenceBuilder{id: 94, commit: 264, name: "one-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} + b92.items = []builder{&b87, &b181, &b84, &b181, &b89, &b181, &b85, &b181, &b91} + var b94 = sequenceBuilder{id: 94, commit: 520, name: "one-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} var b93 = charBuilder{} b94.items = []builder{&b93} - var b96 = sequenceBuilder{id: 96, commit: 264, name: "zero-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} + var b96 = sequenceBuilder{id: 96, commit: 520, name: "zero-or-more", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} var b95 = charBuilder{} b96.items = []builder{&b95} - var b98 = sequenceBuilder{id: 98, commit: 264, name: "zero-or-one", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} + var b98 = sequenceBuilder{id: 98, commit: 520, name: "zero-or-one", allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{99}} var b97 = charBuilder{} b98.items = []builder{&b97} b99.options = []builder{&b83, &b92, &b94, &b96, &b98} b101.items = []builder{&b100, &b99} var b102 = sequenceBuilder{id: 102, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - b102.items = []builder{&b170, &b101} + b102.items = []builder{&b181, &b101} b103.items = []builder{&b101, &b102} - var b109 = sequenceBuilder{id: 109, commit: 256, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{74}} - var b104 = choiceBuilder{id: 104, commit: 322} + var b109 = sequenceBuilder{id: 109, commit: 512, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{74}} + var b104 = choiceBuilder{id: 104, commit: 578} b104.options = []builder{&b65, &b68, &b73, &b103} var b107 = sequenceBuilder{id: 107, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}} var b106 = sequenceBuilder{id: 106, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} var b105 = charBuilder{} b106.items = []builder{&b105} - b107.items = []builder{&b106, &b170, &b104} + b107.items = []builder{&b106, &b181, &b104} var b108 = sequenceBuilder{id: 108, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - b108.items = []builder{&b170, &b107} - b109.items = []builder{&b104, &b170, &b107, &b108} + b108.items = []builder{&b181, &b107} + b109.items = []builder{&b104, &b181, &b107, &b108} b74.options = []builder{&b65, &b68, &b73, &b103, &b109} - b153.items = []builder{&b150, &b170, &b152, &b170, &b74} - var b159 = sequenceBuilder{id: 159, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var b157 = sequenceBuilder{id: 157, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}} - var b155 = sequenceBuilder{id: 155, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b154 = charBuilder{} - b155.items = []builder{&b154} - var b156 = sequenceBuilder{id: 156, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - b156.items = []builder{&b170, &b155} - b157.items = []builder{&b155, &b156, &b170, &b153} - var b158 = sequenceBuilder{id: 158, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - b158.items = []builder{&b170, &b157} - b159.items = []builder{&b170, &b157, &b158} - b160.items = []builder{&b153, &b159} - var b168 = sequenceBuilder{id: 168, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var b164 = sequenceBuilder{id: 164, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b163 = charBuilder{} - b164.items = []builder{&b163} + b164.items = []builder{&b161, &b181, &b163, &b181, &b74} + var b170 = sequenceBuilder{id: 170, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var b168 = sequenceBuilder{id: 168, commit: 2, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}} + var b166 = sequenceBuilder{id: 166, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b165 = charBuilder{} + b166.items = []builder{&b165} var b167 = sequenceBuilder{id: 167, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} - b167.items = []builder{&b170, &b164} - b168.items = []builder{&b170, &b164, &b167} - b171.items = []builder{&b166, &b170, &b160, &b168} - b172.items = []builder{&b170, &b171, &b170} + b167.items = []builder{&b181, &b166} + b168.items = []builder{&b166, &b167, &b181, &b164} + var b169 = sequenceBuilder{id: 169, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} + b169.items = []builder{&b181, &b168} + b170.items = []builder{&b181, &b168, &b169} + b171.items = []builder{&b164, &b170} + var b179 = sequenceBuilder{id: 179, commit: 2, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var b175 = sequenceBuilder{id: 175, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b174 = charBuilder{} + b175.items = []builder{&b174} + var b178 = sequenceBuilder{id: 178, commit: 2, ranges: [][]int{{0, -1}, {1, 1}}} + b178.items = []builder{&b181, &b175} + b179.items = []builder{&b181, &b175, &b178} + b182.items = []builder{&b177, &b181, &b171, &b179} + b183.items = []builder{&b181, &b182, &b181} var keywords = []parser{} - return parseInput(r, &p172, &b172, keywords) + return parseInput(r, &p183, &b183, keywords) } diff --git a/syntax.go b/syntax.go index e3fb616..c2b045e 100644 --- a/syntax.go +++ b/syntax.go @@ -116,7 +116,7 @@ func (ct CommitType) String() string { return "none" } - if ct&^(Alias|Whitespace|NoWhitespace|Keyword|NoKeyword|FailPass|Root|userDefined) != 0 { + if ct&^(Alias|Whitespace|NoWhitespace|Keyword|NoKeyword|FailPass|NoFailPass|Root|userDefined) != 0 { return "unknown" } @@ -145,6 +145,10 @@ func (ct CommitType) String() string { cts = append(cts, "failpass") } + if ct&NoFailPass > 0 { + cts = append(cts, "nofailpass") + } + if ct&Root > 0 { cts = append(cts, "root") } @@ -190,9 +194,9 @@ func intsContain(is []int, i int) bool { var incompatibleCommitTypes = map[CommitType][]CommitType{ Alias: {Root}, - Whitespace: {Keyword, NoKeyword, FailPass, Root}, + Whitespace: {Keyword, NoKeyword, FailPass, NoFailPass, Root}, Keyword: {NoKeyword, Root}, - FailPass: {Root}, + FailPass: {Root, NoFailPass}, } func (s *Syntax) checkCommitType(d definition) error { diff --git a/syntax.treerack b/syntax.treerack index 53a3137..f949744 100644 --- a/syntax.treerack +++ b/syntax.treerack @@ -57,8 +57,9 @@ nows = "nows"; kw = "kw"; nokw = "nokw"; failpass = "failpass"; +nofailpass = "nofailpass"; root = "root"; -flag:alias = alias | ws | nows | kw | nokw | failpass | root; +flag:alias = alias | ws | nows | kw | nokw | failpass | nofailpass | root; // a syntax document consists of definitions: definition-name:alias:nows = symbol (":" flag)*; diff --git a/syntaxhead.go b/syntaxhead.go index 6f43ed6..9eed986 100644 --- a/syntaxhead.go +++ b/syntaxhead.go @@ -38,6 +38,10 @@ const ( // locally. FailPass + // NoFailPass configures the parser to handle the failure locally. This overrides automatic fail-pass, + // e.g. in case of Alias definitions. + NoFailPass + // Root explicitly marks the parser as the root of the syntax. By default, the last defined parser is // considered the root. Root diff --git a/whitespace.go b/whitespace.go index a5af019..75c01e8 100644 --- a/whitespace.go +++ b/whitespace.go @@ -71,15 +71,14 @@ func applyWhitespaceToSeq(s *sequenceDefinition) []definition { } singleItem := SequenceItem{Name: item.Name, Min: 1, Max: 1} - restName := patchName(item.Name, s.nodeName(), "wsrest", strconv.Itoa(i)) restDef := newSequence(restName, Alias, []SequenceItem{whitespace, singleItem}) defs = append(defs, restDef) - restItems := SequenceItem{Name: restName, Min: 0, Max: -1} if item.Min > 0 { restItems.Min = item.Min - 1 } + if item.Max > 1 { restItems.Max = item.Max - 1 }