From 68ce88cc6fe55d7ec71b881c2292ad1cd76155d4 Mon Sep 17 00:00:00 2001 From: Arpad Ryszka Date: Fri, 5 Jan 2018 19:06:10 +0100 Subject: [PATCH] use generated syntax for all parsers --- Makefile | 41 +- boot.go | 6 +- bootsyntax.go | 284 --------- char.go | 122 +--- chardefine.go | 118 ++++ choice.go | 222 ------- choicedefine.go | 223 +++++++ context.go | 8 +- gendoc.go | 23 + head.go | 4 + node.go | 26 +- nodehead.go | 28 + notes.txt | 2 + parsegen.go | 625 ------------------- scripts/boot.go | 7 +- scripts/createhead.go | 102 ++++ self/self.go | 1345 +++++++++++++++++++++++++++++++++++++++++ sequence.go | 374 ------------ sequencedefine.go | 375 ++++++++++++ syntax.go | 229 +++---- syntax_test.go | 4 +- syntaxhead.go | 103 ++++ 22 files changed, 2455 insertions(+), 1816 deletions(-) delete mode 100644 bootsyntax.go create mode 100644 chardefine.go create mode 100644 choicedefine.go create mode 100644 gendoc.go create mode 100644 head.go create mode 100644 nodehead.go delete mode 100644 parsegen.go create mode 100644 scripts/createhead.go create mode 100644 self/self.go create mode 100644 sequencedefine.go create mode 100644 syntaxhead.go diff --git a/Makefile b/Makefile index fa363b5..6caf554 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,35 @@ deps: go get -t ./... imports: $(SOURCES) + @echo imports @goimports -w $(SOURCES) build: $(SOURCES) - go build ./... + go build + +head: $(SOURCES) + go run scripts/createhead.go -- \ + char.go \ + sequence.go \ + choice.go \ + idset.go \ + results.go \ + context.go \ + nodehead.go \ + syntaxhead.go \ + > head.go + +generate: $(SOURCES) $(PARSERS) head + go run scripts/boot.go < syntax.treerack > self/self.go.next + @mv self/self.go{.next,} + @gofmt -s -w self/self.go + +regenerate: $(SOURCES) $(PARSERS) head + go run scripts/boot.go < syntax.treerack > self/self.go.next + @mv self/self.go{.next,} + go run scripts/boot.go < syntax.treerack > self/self.go.next + @mv self/self.go{.next,} + @gofmt -s -w self/self.go check: imports build $(PARSERS) go test -test.short -run ^Test @@ -39,21 +64,23 @@ cpu: cpu.out go tool pprof -top cpu.out fmt: $(SOURCES) + @echo fmt @gofmt -w -s $(SOURCES) check-fmt: $(SOURCES) + @echo check fmt @if [ "$$(gofmt -s -d $(SOURCES))" != "" ]; then false; else true; fi vet: - @go vet + go vet -precommit: fmt vet build check-full +precommit: regenerate fmt vet build check-full clean: - @rm -f *.test - @rm -f cpu.out - @rm -f .coverprofile - @go clean -i ./... + rm -f *.test + rm -f cpu.out + rm -f .coverprofile + go clean -i ./... ci-trigger: deps check-fmt build check-full ifeq ($(TRAVIS_BRANCH)_$(TRAVIS_PULL_REQUEST), master_false) diff --git a/boot.go b/boot.go index ec6631f..f775140 100644 --- a/boot.go +++ b/boot.go @@ -5,10 +5,6 @@ import "os" func bootSyntax() (*Syntax, error) { f, _ := os.Open("syntax.treerack") defer f.Close() - - // never fails: - doc, _ := parsegen(f) - s := &Syntax{} - return s, define(s, doc) + return s, s.ReadSyntax(f) } diff --git a/bootsyntax.go b/bootsyntax.go deleted file mode 100644 index c5ba048..0000000 --- a/bootsyntax.go +++ /dev/null @@ -1,284 +0,0 @@ -package treerack - -var bootSyntaxDefs = [][]string{{ - "chars", "space", "alias", " ", -}, { - "chars", "tab", "alias", "\\t", -}, { - "chars", "nl", "alias", "\\n", -}, { - "chars", "backspace", "alias", "\\b", -}, { - "chars", "formfeed", "alias", "\\f", -}, { - "chars", "carryreturn", "alias", "\\r", -}, { - "chars", "verticaltab", "alias", "\\v", -}, { - "choice", - "wschar", - "alias", - "space", - "tab", - "nl", - "backspace", - "formfeed", - "carryreturn", - "verticaltab", -}, { - "chars", "open-block-comment", "alias", "/*", -}, { - "chars", "close-block-comment", "alias", "*/", -}, { - "chars", "star", "alias", "*", -}, { - "class", "not-slash", "alias", "^/", -}, { - "class", "not-star", "alias", "^*", -}, { - "chars", "double-slash", "alias", "//", -}, { - "class", "not-nl", "alias", "^\\n", -}, { - "sequence", "not-block-close", "alias", "star", "not-slash", -}, { - "choice", "block-comment-char", "alias", "not-block-close", "not-star", -}, { - "sequence", "block-comment-body", "alias", "block-comment-char:0:-1", -}, { - "sequence", - "block-comment", - "alias", - "open-block-comment", - "block-comment-body", - "close-block-comment", -}, { - "sequence", "not-nls", "alias", "not-nl:0:-1", -}, { - "sequence", "line-comment", "alias", "double-slash", "not-nls", -}, { - "choice", "comment-segment", "alias", "block-comment", "line-comment", -}, { - "sequence", "wss", "alias", "wschar:0:-1", -}, { - "sequence", "optional-nl", "alias", "nl:0:1", -}, { - "choice", - "ws-no-nl", - "alias", - "space", - "tab", - "backspace", - "formfeed", - "carryreturn", - "verticaltab", -}, { - "sequence", - "continue-comment-segment", - "alias", - "ws-no-nl", - "optional-nl", - "ws-no-nl", - "comment-segment", -}, { - "sequence", "continue-comment", "alias", "continue-comment-segment:0:-1", -}, { - "sequence", - "comment", - "none", - "comment-segment", - "continue-comment", -}, { - "choice", "wsc", "alias", "wschar", "comment", -}, { - "sequence", "wscs", "alias", "wsc:0:-1", -}, { - "anything", "anything", "alias", -}, { - "chars", "any-char", "none", ".", -}, { - "chars", "open-square", "alias", "[", -}, { - "chars", "close-square", "alias", "]", -}, { - "chars", "class-not", "none", "^", -}, { - "chars", "dash", "alias", "-", -}, { - "sequence", "optional-class-not", "alias", "class-not:0:1", -}, { - "class", "not-class-control", "alias", "^\\\\\\[\\]\\^\\-", -}, { - "chars", "escape", "alias", "\\\\", -}, { - "sequence", "escaped-char", "alias", "escape", "anything", -}, { - "choice", "class-char", "none", "not-class-control", "escaped-char", -}, { - "sequence", "char-range", "none", "class-char", "dash", "class-char", -}, { - "choice", "char-or-range", "alias", "class-char", "char-range", -}, { - "sequence", "chars-or-ranges", "alias", "char-or-range:0:-1", -}, { - "sequence", "char-class", "none", "open-square", "optional-class-not", "chars-or-ranges", "close-square", -}, { - "chars", "double-quote", "alias", "\\\"", -}, { - "class", "not-char-sequence-control", "alias", "^\\\\\"", -}, { - "choice", "sequence-char", "none", "not-char-sequence-control", "escaped-char", -}, { - "sequence", "char-sequence-chars", "alias", "sequence-char:0:-1", -}, { - "sequence", "char-sequence", "none", "double-quote", "char-sequence-chars", "double-quote", -}, { - "choice", "terminal", "alias", "any-char", "char-class", "char-sequence", -}, { - "class", "symbol-char", "alias", symbolChars, -}, { - "sequence", "symbol-chars", "alias", "symbol-char:1:-1", -}, { - "sequence", "symbol", "none", "symbol-chars", -}, { - "chars", "open-paren", "alias", "(", -}, { - "chars", "close-paren", "alias", ")", -}, { - "sequence", "group", "alias", "open-paren", "wscs", "expression", "wscs", "close-paren", -}, { - "chars", "open-brace", "alias", "{", -}, { - "chars", "close-brace", "alias", "}", -}, { - "class", "digit", "alias", "0-9", -}, { - "sequence", "number", "alias", "digit:1:-1", -}, { - "sequence", "count", "none", "number", -}, { - "sequence", "count-quantifier", "none", "open-brace", "wscs", "count", "wscs", "close-brace", -}, { - "sequence", "range-from", "none", "number", -}, { - "sequence", "range-to", "none", "number", -}, { - "chars", "comma", "alias", ",", -}, { - "sequence", - "range-quantifier", - "none", - "open-brace", - "wscs", - "range-from", - "wscs", - "comma", - "wscs", - "range-to", - "close-brace", -}, { - "chars", "one-or-more", "none", "+", -}, { - "chars", "zero-or-more", "none", "*", -}, { - "chars", "zero-or-one", "none", "?", -}, { - "choice", - "quantity", - "alias", - "count-quantifier", - "range-quantifier", - "one-or-more", - "zero-or-more", - "zero-or-one", -}, { - "choice", "quantifiable", "alias", "terminal", "symbol", "group", -}, { - "choice", "item-choice", "alias", "terminal", "symbol", "group", -}, { - "sequence", "item", "none", "item-choice", "quantity:0:1", -}, { - "sequence", "item-continue", "alias", "wscs", "item", -}, { - "sequence", "items-continue", "alias", "item-continue:0:-1", -}, { - "sequence", "sequence", "none", "item", "items-continue", -}, { - "choice", "option", "alias", "terminal", "symbol", "group", "sequence", -}, { - "chars", "pipe", "alias", "|", -}, { - "sequence", "option-continue", "alias", "wscs", "pipe", "wscs", "option", -}, { - "sequence", "options-continue", "alias", "option-continue:1:-1", -}, { - "sequence", "choice", "none", "option", "options-continue", -}, { - "choice", - "expression", - "alias", - "terminal", - "symbol", - "group", - "sequence", - "choice", -}, { - "chars", "alias", "none", "alias", -}, { - "chars", "ws", "none", "ws", -}, { - "chars", "nows", "none", "nows", -}, { - "chars", "failpass", "none", "failpass", -}, { - "chars", "root", "none", "root", -}, { - "choice", "flag", "alias", "alias", "ws", "nows", "failpass", "root", -}, { - "chars", "colon", "alias", ":", -}, { - "sequence", "flag-tag", "alias", "colon", "flag", -}, { - "sequence", "flags", "alias", "flag-tag:0:-1", -}, { - "chars", "equal", "alias", "=", -}, { - "sequence", "definition", "none", "symbol", "flags", "wscs", "equal", "wscs", "expression", -}, { - "chars", "semicolon", "alias", ";", -}, { - "choice", "wsc-or-semicolon", "alias", "wsc", "semicolon", -}, { - "sequence", "wsc-or-semicolons", "alias", "wsc-or-semicolon:0:-1", -}, { - "sequence", - "subsequent-definition", - "alias", - "wscs", - "semicolon", - "wsc-or-semicolons", - "definition", -}, { - "sequence", - "subsequent-definitions", - "alias", - "subsequent-definition:0:-1", -}, { - "sequence", - "definitions", - "alias", - "definition", - "subsequent-definitions", -}, { - "sequence", - "opt-definitions", - "alias", - "definitions:0:1", -}, { - "sequence", - "syntax", - "root", - "wsc-or-semicolons", - "opt-definitions", - "wsc-or-semicolons", -}} diff --git a/char.go b/char.go index 0b58482..0ed206c 100644 --- a/char.go +++ b/char.go @@ -1,15 +1,5 @@ package treerack -import ( - "fmt" - "io" -) - -const ( - charClassEscape = '\\' - charClassBanned = "\\[]^-\b\f\n\r\t\v" -) - type charParser struct { name string id int @@ -23,70 +13,9 @@ type charBuilder struct { id int } -func newChar( - name string, - not bool, - chars []rune, - ranges [][]rune, -) *charParser { - return &charParser{ - name: name, - not: not, - chars: chars, - ranges: ranges, - } -} - -func (p *charParser) nodeName() string { return p.name } -func (p *charParser) setName(n string) { p.name = n } -func (p *charParser) nodeID() int { return p.id } -func (p *charParser) setID(id int) { p.id = id } -func (p *charParser) commitType() CommitType { return Alias } -func (p *charParser) setCommitType(ct CommitType) {} -func (p *charParser) preinit() {} -func (p *charParser) validate(*registry) error { return nil } -func (p *charParser) init(*registry) {} -func (p *charParser) addGeneralization(int) {} -func (p *charParser) parser() parser { return p } - -func (p *charParser) builder() builder { - return &charBuilder{ - id: p.id, - name: p.name, - } -} - -func (p *charParser) isSingleChar() bool { - return !p.not && len(p.chars) == 1 && len(p.ranges) == 0 -} - -func (p *charParser) format(_ *registry, f formatFlags) string { - if p.not && len(p.chars) == 0 && len(p.ranges) == 0 { - return "." - } - - esc := func(c ...rune) []rune { - return escape(charClassEscape, []rune(charClassBanned), c) - } - - var s []rune - s = append(s, '[') - - if p.not { - s = append(s, '^') - } - - s = append(s, esc(p.chars...)...) - - for i := range p.ranges { - s = append(s, esc(p.ranges[i][0])...) - s = append(s, '-') - s = append(s, esc(p.ranges[i][1])...) - } - - s = append(s, ']') - return string(s) -} +func (p *charParser) nodeName() string { return p.name } +func (p *charParser) nodeID() int { return p.id } +func (p *charParser) commitType() CommitType { return Alias } func matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool { for _, ci := range chars { @@ -122,54 +51,9 @@ func (p *charParser) parse(c *context) { c.success(c.offset + 1) } -func (p *charParser) generate(w io.Writer, done map[string]bool) error { - if done[p.name] { - return nil - } - - done[p.name] = true - - var err error - fprintf := func(f string, args ...interface{}) { - if err != nil { - return - } - - _, err = fmt.Fprintf(w, f, args...) - } - - fprintf("var p%d = charParser{", p.id) - fprintf("id: %d, not: %t,", p.id, p.not) - - fprintf("chars: []rune{") - for i := range p.chars { - fprintf("%d,", p.chars[i]) - } - - fprintf("},") - - fprintf("ranges: [][]rune{") - for i := range p.ranges { - fprintf("{%d, %d},", p.ranges[i][0], p.ranges[i][1]) - } - - fprintf("}};") - return err -} - func (b *charBuilder) nodeName() string { return b.name } func (b *charBuilder) nodeID() int { return b.id } func (b *charBuilder) build(c *context) ([]*Node, bool) { return nil, false } - -func (b *charBuilder) generate(w io.Writer, done map[string]bool) error { - if done[b.name] { - return nil - } - - done[b.name] = true - _, err := fmt.Fprintf(w, "var b%d = charBuilder{};", b.id) - return err -} diff --git a/chardefine.go b/chardefine.go new file mode 100644 index 0000000..232b4f0 --- /dev/null +++ b/chardefine.go @@ -0,0 +1,118 @@ +package treerack + +import ( + "fmt" + "io" +) + +const ( + charClassEscape = '\\' + charClassBanned = "\\[]^-\b\f\n\r\t\v" +) + +func newChar( + name string, + not bool, + chars []rune, + ranges [][]rune, +) *charParser { + return &charParser{ + name: name, + not: not, + chars: chars, + ranges: ranges, + } +} + +func (p *charParser) setName(n string) { p.name = n } +func (p *charParser) setID(id int) { p.id = id } +func (p *charParser) setCommitType(ct CommitType) {} +func (p *charParser) preinit() {} +func (p *charParser) validate(*registry) error { return nil } +func (p *charParser) init(*registry) {} +func (p *charParser) addGeneralization(int) {} +func (p *charParser) parser() parser { return p } + +func (p *charParser) builder() builder { + return &charBuilder{ + id: p.id, + name: p.name, + } +} + +func (p *charParser) isSingleChar() bool { + return !p.not && len(p.chars) == 1 && len(p.ranges) == 0 +} + +func (p *charParser) format(_ *registry, f formatFlags) string { + if p.not && len(p.chars) == 0 && len(p.ranges) == 0 { + return "." + } + + esc := func(c ...rune) []rune { + return escape(charClassEscape, []rune(charClassBanned), c) + } + + var s []rune + s = append(s, '[') + + if p.not { + s = append(s, '^') + } + + s = append(s, esc(p.chars...)...) + + for i := range p.ranges { + s = append(s, esc(p.ranges[i][0])...) + s = append(s, '-') + s = append(s, esc(p.ranges[i][1])...) + } + + s = append(s, ']') + return string(s) +} + +func (p *charParser) generate(w io.Writer, done map[string]bool) error { + if done[p.name] { + return nil + } + + done[p.name] = true + + var err error + fprintf := func(f string, args ...interface{}) { + if err != nil { + return + } + + _, err = fmt.Fprintf(w, f, args...) + } + + fprintf("var p%d = charParser{", p.id) + fprintf("id: %d, not: %t,", p.id, p.not) + + fprintf("chars: []rune{") + for i := range p.chars { + fprintf("%d,", p.chars[i]) + } + + fprintf("},") + + fprintf("ranges: [][]rune{") + for i := range p.ranges { + fprintf("{%d, %d},", p.ranges[i][0], p.ranges[i][1]) + } + + fprintf("}};") + return err +} + +func (b *charBuilder) generate(w io.Writer, done map[string]bool) error { + if done[b.name] { + return nil + } + + done[b.name] = true + _, err := fmt.Fprintf(w, "var b%d = charBuilder{};", b.id) + return err +} diff --git a/choice.go b/choice.go index 1aff59a..833ad07 100644 --- a/choice.go +++ b/choice.go @@ -1,23 +1,5 @@ package treerack -import ( - "fmt" - "io" -) - -type choiceDefinition struct { - name string - id int - commit CommitType - options []string - optionDefs []definition - generalizations []int - cparser *choiceParser - cbuilder *choiceBuilder - validated bool - initialized bool -} - type choiceParser struct { name string id int @@ -33,127 +15,6 @@ type choiceBuilder struct { options []builder } -func newChoice(name string, ct CommitType, options []string) *choiceDefinition { - return &choiceDefinition{ - name: name, - commit: ct, - options: options, - } -} - -func (d *choiceDefinition) nodeName() string { return d.name } -func (d *choiceDefinition) setName(n string) { d.name = n } -func (d *choiceDefinition) nodeID() int { return d.id } -func (d *choiceDefinition) setID(id int) { d.id = id } -func (d *choiceDefinition) commitType() CommitType { return d.commit } -func (d *choiceDefinition) setCommitType(ct CommitType) { d.commit = ct } -func (d *choiceDefinition) preinit() {} - -func (d *choiceDefinition) validate(r *registry) error { - if d.validated { - return nil - } - - d.validated = true - for i := range d.options { - o, ok := r.definitions[d.options[i]] - if !ok { - return parserNotFound(d.options[i]) - } - - if err := o.validate(r); err != nil { - return err - } - } - - return nil -} - -func (d *choiceDefinition) createBuilder() { - d.cbuilder = &choiceBuilder{ - name: d.name, - id: d.id, - commit: d.commit, - } -} - -func (d *choiceDefinition) initOptions(r *registry) { - for _, o := range d.options { - def := r.definitions[o] - d.optionDefs = append(d.optionDefs, def) - def.init(r) - d.cbuilder.options = append(d.cbuilder.options, def.builder()) - def.addGeneralization(d.id) - } -} - -func (d *choiceDefinition) init(r *registry) { - if d.initialized { - return - } - - d.initialized = true - d.createBuilder() - d.initOptions(r) -} - -func (d *choiceDefinition) addGeneralization(g int) { - if intsContain(d.generalizations, g) { - return - } - - d.generalizations = append(d.generalizations, g) - for _, o := range d.optionDefs { - o.addGeneralization(g) - } -} - -func (d *choiceDefinition) createParser() { - d.cparser = &choiceParser{ - name: d.name, - id: d.id, - commit: d.commit, - generalizations: d.generalizations, - } -} - -func (d *choiceDefinition) createOptionParsers() { - for _, def := range d.optionDefs { - option := def.parser() - d.cparser.options = append(d.cparser.options, option) - } -} - -func (d *choiceDefinition) parser() parser { - if d.cparser != nil { - return d.cparser - } - - d.createParser() - d.createOptionParsers() - return d.cparser -} - -func (d *choiceDefinition) builder() builder { return d.cbuilder } - -func (d *choiceDefinition) format(r *registry, f formatFlags) string { - var chars []rune - for i := range d.options { - if i > 0 { - chars = append(chars, []rune(" | ")...) - } - - optionDef, _ := r.definition(d.options[i]) - if optionDef.commitType()&userDefined != 0 { - chars = append(chars, []rune(optionDef.nodeName())...) - } else { - chars = append(chars, []rune(optionDef.format(r, f))...) - } - } - - return string(chars) -} - func (p *choiceParser) nodeName() string { return p.name } func (p *choiceParser) nodeID() int { return p.id } func (p *choiceParser) commitType() CommitType { return p.commit } @@ -248,50 +109,6 @@ func (p *choiceParser) parse(c *context) { c.results.unmarkPending(from, p.id) } -func (p *choiceParser) generate(w io.Writer, done map[string]bool) error { - if done[p.name] { - return nil - } - - done[p.name] = true - - var err error - fprintf := func(f string, args ...interface{}) { - if err != nil { - return - } - - _, err = fmt.Fprintf(w, f, args...) - } - - fprintf("var p%d = choiceParser{", p.id) - fprintf("id: %d, commit: %d,", p.id, p.commit) - if p.commitType()&userDefined != 0 { - fprintf("name: \"%s\",", p.name) - } - - fprintf("generalizations: []int{") - for i := range p.generalizations { - fprintf("%d,", p.generalizations[i]) - } - - fprintf("}};") - - for i := range p.options { - if err := p.options[i].generate(w, done); err != nil { - return err - } - } - - fprintf("p%d.options = []parser{", p.id) - for i := range p.options { - fprintf("&p%d,", p.options[i].nodeID()) - } - - fprintf("};") - return err -} - func (b *choiceBuilder) nodeName() string { return b.name } func (b *choiceBuilder) nodeID() int { return b.id } @@ -339,42 +156,3 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) { tokens: c.tokens, }}, true } - -func (b *choiceBuilder) generate(w io.Writer, done map[string]bool) error { - if done[b.name] { - return nil - } - - done[b.name] = true - - var err error - fprintf := func(f string, args ...interface{}) { - if err != nil { - return - } - - _, err = fmt.Fprintf(w, f, args...) - } - - fprintf("var b%d = choiceBuilder{", b.id) - fprintf("id: %d, commit: %d,", b.id, b.commit) - if b.commit&Alias == 0 { - fprintf("name: \"%s\",", b.name) - } - - fprintf("};") - - for i := range b.options { - if err := b.options[i].generate(w, done); err != nil { - return err - } - } - - fprintf("b%d.options = []builder{", b.id) - for i := range b.options { - fprintf("&b%d,", b.options[i].nodeID()) - } - - fprintf("};") - return err -} diff --git a/choicedefine.go b/choicedefine.go new file mode 100644 index 0000000..16f8735 --- /dev/null +++ b/choicedefine.go @@ -0,0 +1,223 @@ +package treerack + +import ( + "fmt" + "io" +) + +type choiceDefinition struct { + name string + id int + commit CommitType + options []string + optionDefs []definition + generalizations []int + cparser *choiceParser + cbuilder *choiceBuilder + validated bool + initialized bool +} + +func (d *choiceDefinition) nodeName() string { return d.name } +func (d *choiceDefinition) setName(n string) { d.name = n } +func (d *choiceDefinition) nodeID() int { return d.id } +func (d *choiceDefinition) setID(id int) { d.id = id } +func (d *choiceDefinition) commitType() CommitType { return d.commit } +func (d *choiceDefinition) setCommitType(ct CommitType) { d.commit = ct } +func (d *choiceDefinition) preinit() {} + +func newChoice(name string, ct CommitType, options []string) *choiceDefinition { + return &choiceDefinition{ + name: name, + commit: ct, + options: options, + } +} + +func (d *choiceDefinition) validate(r *registry) error { + if d.validated { + return nil + } + + d.validated = true + for i := range d.options { + o, ok := r.definitions[d.options[i]] + if !ok { + return parserNotFound(d.options[i]) + } + + if err := o.validate(r); err != nil { + return err + } + } + + return nil +} + +func (d *choiceDefinition) createBuilder() { + d.cbuilder = &choiceBuilder{ + name: d.name, + id: d.id, + commit: d.commit, + } +} + +func (d *choiceDefinition) initOptions(r *registry) { + for _, o := range d.options { + def := r.definitions[o] + d.optionDefs = append(d.optionDefs, def) + def.init(r) + d.cbuilder.options = append(d.cbuilder.options, def.builder()) + def.addGeneralization(d.id) + } +} + +func (d *choiceDefinition) init(r *registry) { + if d.initialized { + return + } + + d.initialized = true + d.createBuilder() + d.initOptions(r) +} + +func (d *choiceDefinition) addGeneralization(g int) { + if intsContain(d.generalizations, g) { + return + } + + d.generalizations = append(d.generalizations, g) + for _, o := range d.optionDefs { + o.addGeneralization(g) + } +} + +func (d *choiceDefinition) createParser() { + d.cparser = &choiceParser{ + name: d.name, + id: d.id, + commit: d.commit, + generalizations: d.generalizations, + } +} + +func (d *choiceDefinition) createOptionParsers() { + for _, def := range d.optionDefs { + option := def.parser() + d.cparser.options = append(d.cparser.options, option) + } +} + +func (d *choiceDefinition) parser() parser { + if d.cparser != nil { + return d.cparser + } + + d.createParser() + d.createOptionParsers() + return d.cparser +} + +func (d *choiceDefinition) builder() builder { return d.cbuilder } + +func (d *choiceDefinition) format(r *registry, f formatFlags) string { + var chars []rune + for i := range d.options { + if i > 0 { + chars = append(chars, []rune(" | ")...) + } + + optionDef, _ := r.definition(d.options[i]) + if optionDef.commitType()&userDefined != 0 { + chars = append(chars, []rune(optionDef.nodeName())...) + } else { + chars = append(chars, []rune(optionDef.format(r, f))...) + } + } + + return string(chars) +} + +func (p *choiceParser) generate(w io.Writer, done map[string]bool) error { + if done[p.name] { + return nil + } + + done[p.name] = true + + var err error + fprintf := func(f string, args ...interface{}) { + if err != nil { + return + } + + _, err = fmt.Fprintf(w, f, args...) + } + + fprintf("var p%d = choiceParser{", p.id) + fprintf("id: %d, commit: %d,", p.id, p.commit) + if p.commitType()&userDefined != 0 { + fprintf("name: \"%s\",", p.name) + } + + fprintf("generalizations: []int{") + for i := range p.generalizations { + fprintf("%d,", p.generalizations[i]) + } + + fprintf("}};") + + for i := range p.options { + if err := p.options[i].(generator).generate(w, done); err != nil { + return err + } + } + + fprintf("p%d.options = []parser{", p.id) + for i := range p.options { + fprintf("&p%d,", p.options[i].nodeID()) + } + + fprintf("};") + return err +} + +func (b *choiceBuilder) generate(w io.Writer, done map[string]bool) error { + if done[b.name] { + return nil + } + + done[b.name] = true + + var err error + fprintf := func(f string, args ...interface{}) { + if err != nil { + return + } + + _, err = fmt.Fprintf(w, f, args...) + } + + fprintf("var b%d = choiceBuilder{", b.id) + fprintf("id: %d, commit: %d,", b.id, b.commit) + if b.commit&Alias == 0 { + fprintf("name: \"%s\",", b.name) + } + + fprintf("};") + + for i := range b.options { + if err := b.options[i].(generator).generate(w, done); err != nil { + return err + } + } + + fprintf("b%d.options = []builder{", b.id) + for i := range b.options { + fprintf("&b%d,", b.options[i].nodeID()) + } + + fprintf("};") + return err +} diff --git a/context.go b/context.go index ee8a150..80ae302 100644 --- a/context.go +++ b/context.go @@ -130,14 +130,14 @@ func (c *context) parseError(p parser) error { } func (c *context) finalizeParse(root parser) error { - p := c.failingParser - if p == nil { - p = root + fp := c.failingParser + if fp == nil { + fp = root } to, match, found := c.results.longestResult(0, root.nodeID()) if !found || !match || found && match && to < c.readOffset { - return c.parseError(p) + return c.parseError(fp) } c.read() diff --git a/gendoc.go b/gendoc.go new file mode 100644 index 0000000..cab240d --- /dev/null +++ b/gendoc.go @@ -0,0 +1,23 @@ +package treerack + +// The below doc doesn't apply to treerack's source code +// only to the source code generated with treerack. +const gendoc = ` +/* +This file was generated by treerack (https://github.com/aryszka/treerack). + +The contents of this file fall under different licenses. + +The code between the "// head" and "// eo head" lines falls under the same +license as the source code of treerack (https://github.com/aryszka/treerack), +unless explicitly stated otherwise, if treerack's license allows changing the +license of this source code. + +Treerack's license: MIT https://opensource.org/licenses/MIT +where YEAR=2018, COPYRIGHT HOLDER=Arpad Ryszka (arpad.ryszka@gmail.com) + +The rest of the content of this file falls under the same license as the one +that the user of treerack generating this file declares for it, or it is +unlicensed. +*/ +` diff --git a/head.go b/head.go new file mode 100644 index 0000000..3b2fbe8 --- /dev/null +++ b/head.go @@ -0,0 +1,4 @@ +package treerack + +// generated with scripts/createhead.go +const headCode = "import (\n\t\"strconv\"\n\t\"io\"\n\t\"strings\"\n\t\"unicode\"\n\t\"fmt\"\n\t\"bufio\"\n\t\"errors\"\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\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\tint\n\t\tparsed\t\tbool\n\t)\n\titemIndex := 0\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\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\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} 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}\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}\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\tstring\n\tid\tint\n\tcommit\tCommitType\n\toptions\t[]builder\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 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} 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}\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}\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\toffset\t\tint\n\treadOffset\tint\n\tconsumed\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) *context {\n\treturn &context{reader: r, results: &results{}, 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 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.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) 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\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\t\tstring\n\tNodes\t\t[]*Node\n\tFrom, To\tint\n\ttokens\t\t[]rune\n}\n\nfunc (n *Node) Tokens() []rune {\n\tdefer func() {\n\t\tif err := recover(); err != nil {\n\t\t\tprintln(len(n.tokens), n.From, n.To)\n\t\t\tpanic(err)\n\t\t}\n\t}()\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\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 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 parse(r io.Reader, p parser, b builder) (*Node, error) {\n\tc := newContext(bufio.NewReader(r))\n\tp.parse(c)\n\tif c.readErr != nil {\n\t\treturn nil, 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 nil, 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/node.go b/node.go index 3ad0392..5c4140a 100644 --- a/node.go +++ b/node.go @@ -1,13 +1,6 @@ package treerack -import "fmt" - -type Node struct { - Name string - Nodes []*Node - From, To int - tokens []rune -} +import "github.com/aryszka/treerack/self" func mapNodes(m func(n *Node) *Node, n []*Node) []*Node { var nn []*Node @@ -29,10 +22,17 @@ func filterNodes(f func(n *Node) bool, n []*Node) []*Node { return nn } -func (n *Node) String() string { - return fmt.Sprintf("%s:%d:%d:%s", n.Name, n.From, n.To, n.Text()) -} +func mapSelfNode(n *self.Node) *Node { + nn := Node{ + Name: n.Name, + From: n.From, + To: n.To, + tokens: n.Tokens(), + } -func (n *Node) Text() string { - return string(n.tokens[n.From:n.To]) + for i := range n.Nodes { + nn.Nodes = append(nn.Nodes, mapSelfNode(n.Nodes[i])) + } + + return &nn } diff --git a/nodehead.go b/nodehead.go new file mode 100644 index 0000000..9942c45 --- /dev/null +++ b/nodehead.go @@ -0,0 +1,28 @@ +package treerack + +import "fmt" + +type Node struct { + Name string + Nodes []*Node + From, To int + tokens []rune +} + +func (n *Node) Tokens() []rune { + defer func() { + if err := recover(); err != nil { + println(len(n.tokens), n.From, n.To) + panic(err) + } + }() + return n.tokens +} + +func (n *Node) String() string { + return fmt.Sprintf("%s:%d:%d:%s", n.Name, n.From, n.To, n.Text()) +} + +func (n *Node) Text() string { + return string(n.Tokens()[n.From:n.To]) +} diff --git a/notes.txt b/notes.txt index bdd63c0..ec1193a 100644 --- a/notes.txt +++ b/notes.txt @@ -34,6 +34,8 @@ test all docs warn nows usage in docs, e.g. spaces in symbol = [a-z]+ test error report on invalid flag report unused definitions +simplify generated output +parse hashed, storing only the results [optimization] try preallocate larger store chunks diff --git a/parsegen.go b/parsegen.go deleted file mode 100644 index df9348b..0000000 --- a/parsegen.go +++ /dev/null @@ -1,625 +0,0 @@ -package treerack - -import ( - "bufio" - "io" -) - -func parsegen(r io.Reader) (*Node, error) { - var p188 = sequenceParser{id: 188, commit: 32, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} - var p186 = choiceParser{id: 186, commit: 2, generalizations: []int{}} - var p185 = choiceParser{id: 185, commit: 70, name: "wsc", generalizations: []int{186}} - var p171 = choiceParser{id: 171, commit: 66, name: "wschar", generalizations: []int{185, 186}} - var p63 = sequenceParser{id: 63, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{171, 185, 186}} - var p28 = charParser{id: 28, not: false, chars: []rune{32}, ranges: [][]rune{}} - p63.items = []parser{&p28} - var p121 = sequenceParser{id: 121, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{171, 185, 186}} - var p17 = charParser{id: 17, not: false, chars: []rune{9}, ranges: [][]rune{}} - p121.items = []parser{&p17} - var p79 = sequenceParser{id: 79, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{171, 185, 186}} - var p53 = charParser{id: 53, not: false, chars: []rune{10}, ranges: [][]rune{}} - p79.items = []parser{&p53} - var p114 = sequenceParser{id: 114, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{171, 185, 186}} - var p96 = charParser{id: 96, not: false, chars: []rune{8}, ranges: [][]rune{}} - p114.items = []parser{&p96} - var p141 = sequenceParser{id: 141, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{171, 185, 186}} - var p9 = charParser{id: 9, not: false, chars: []rune{12}, ranges: [][]rune{}} - p141.items = []parser{&p9} - var p47 = sequenceParser{id: 47, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{171, 185, 186}} - var p87 = charParser{id: 87, not: false, chars: []rune{13}, ranges: [][]rune{}} - p47.items = []parser{&p87} - var p40 = sequenceParser{id: 40, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{171, 185, 186}} - var p18 = charParser{id: 18, not: false, chars: []rune{11}, ranges: [][]rune{}} - p40.items = []parser{&p18} - p171.options = []parser{&p63, &p121, &p79, &p114, &p141, &p47, &p40} - var p90 = sequenceParser{id: 90, commit: 72, allChars: false, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{185, 186}} - var p142 = choiceParser{id: 142, commit: 74, name: "comment-segment", generalizations: []int{}} - var p80 = sequenceParser{id: 80, commit: 74, allChars: false, name: "line-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{142}} - var p41 = sequenceParser{id: 41, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} - var p65 = charParser{id: 65, not: false, chars: []rune{47}, ranges: [][]rune{}} - var p148 = charParser{id: 148, not: false, chars: []rune{47}, ranges: [][]rune{}} - p41.items = []parser{&p65, &p148} - var p55 = sequenceParser{id: 55, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p124 = charParser{id: 124, not: true, chars: []rune{10}, ranges: [][]rune{}} - p55.items = []parser{&p124} - p80.items = []parser{&p41, &p55} - var p48 = sequenceParser{id: 48, commit: 74, allChars: false, name: "block-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{142}} - var p97 = sequenceParser{id: 97, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} - var p64 = charParser{id: 64, not: false, chars: []rune{47}, ranges: [][]rune{}} - var p54 = charParser{id: 54, not: false, chars: []rune{42}, ranges: [][]rune{}} - p97.items = []parser{&p64, &p54} - var p89 = choiceParser{id: 89, commit: 10, generalizations: []int{}} - var p104 = sequenceParser{id: 104, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{89}} - var p29 = sequenceParser{id: 29, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p88 = charParser{id: 88, not: false, chars: []rune{42}, ranges: [][]rune{}} - p29.items = []parser{&p88} - var p122 = sequenceParser{id: 122, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p131 = charParser{id: 131, not: true, chars: []rune{47}, ranges: [][]rune{}} - p122.items = []parser{&p131} - p104.items = []parser{&p29, &p122} - var p159 = sequenceParser{id: 159, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{89}} - var p123 = charParser{id: 123, not: true, chars: []rune{42}, ranges: [][]rune{}} - p159.items = []parser{&p123} - p89.options = []parser{&p104, &p159} - var p19 = sequenceParser{id: 19, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} - var p153 = charParser{id: 153, not: false, chars: []rune{42}, ranges: [][]rune{}} - var p24 = charParser{id: 24, not: false, chars: []rune{47}, ranges: [][]rune{}} - p19.items = []parser{&p153, &p24} - p48.items = []parser{&p97, &p89, &p19} - p142.options = []parser{&p80, &p48} - var p3 = sequenceParser{id: 3, commit: 10, allChars: false, ranges: [][]int{{0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{}} - var p160 = choiceParser{id: 160, commit: 74, name: "ws-no-nl", generalizations: []int{}} - var p66 = sequenceParser{id: 66, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{160}} - var p109 = charParser{id: 109, not: false, chars: []rune{32}, ranges: [][]rune{}} - p66.items = []parser{&p109} - var p180 = sequenceParser{id: 180, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{160}} - var p30 = charParser{id: 30, not: false, chars: []rune{9}, ranges: [][]rune{}} - p180.items = []parser{&p30} - var p136 = sequenceParser{id: 136, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{160}} - var p125 = charParser{id: 125, not: false, chars: []rune{8}, ranges: [][]rune{}} - p136.items = []parser{&p125} - var p118 = sequenceParser{id: 118, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{160}} - var p31 = charParser{id: 31, not: false, chars: []rune{12}, ranges: [][]rune{}} - p118.items = []parser{&p31} - var p49 = sequenceParser{id: 49, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{160}} - var p73 = charParser{id: 73, not: false, chars: []rune{13}, ranges: [][]rune{}} - p49.items = []parser{&p73} - var p182 = sequenceParser{id: 182, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{160}} - var p181 = charParser{id: 181, not: false, chars: []rune{11}, ranges: [][]rune{}} - p182.items = []parser{&p181} - p160.options = []parser{&p66, &p180, &p136, &p118, &p49, &p182} - var p137 = sequenceParser{id: 137, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p105 = charParser{id: 105, not: false, chars: []rune{10}, ranges: [][]rune{}} - p137.items = []parser{&p105} - p3.items = []parser{&p160, &p137, &p160, &p142} - p90.items = []parser{&p142, &p3} - p185.options = []parser{&p171, &p90} - p186.options = []parser{&p185} - var p187 = sequenceParser{id: 187, commit: 66, allChars: false, name: "syntax:wsroot", ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}, generalizations: []int{}} - var p70 = sequenceParser{id: 70, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{}} - var p36 = sequenceParser{id: 36, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p140 = charParser{id: 140, not: false, chars: []rune{59}, ranges: [][]rune{}} - p36.items = []parser{&p140} - var p69 = sequenceParser{id: 69, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} - p69.items = []parser{&p186, &p36} - p70.items = []parser{&p36, &p69} - var p35 = sequenceParser{id: 35, commit: 66, allChars: false, name: "definitions", ranges: [][]int{{1, 1}, {0, 1}}, generalizations: []int{}} - var p165 = sequenceParser{id: 165, commit: 64, allChars: false, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{}} - var p95 = sequenceParser{id: 95, commit: 74, allChars: false, name: "definition-name", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} - var p42 = sequenceParser{id: 42, commit: 72, allChars: false, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{14, 128, 94}} - var p144 = sequenceParser{id: 144, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p169 = charParser{id: 169, 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}, ranges: [][]rune{}} - p144.items = []parser{&p169} - p42.items = []parser{&p144} - var p77 = sequenceParser{id: 77, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} - var p155 = sequenceParser{id: 155, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p147 = charParser{id: 147, not: false, chars: []rune{58}, ranges: [][]rune{}} - p155.items = []parser{&p147} - var p52 = choiceParser{id: 52, commit: 66, name: "flag", generalizations: []int{}} - var p139 = sequenceParser{id: 139, commit: 72, allChars: true, name: "alias", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{52}} - var p15 = charParser{id: 15, not: false, chars: []rune{97}, ranges: [][]rune{}} - var p99 = charParser{id: 99, not: false, chars: []rune{108}, ranges: [][]rune{}} - var p174 = charParser{id: 174, not: false, chars: []rune{105}, ranges: [][]rune{}} - var p135 = charParser{id: 135, not: false, chars: []rune{97}, ranges: [][]rune{}} - var p16 = charParser{id: 16, not: false, chars: []rune{115}, ranges: [][]rune{}} - p139.items = []parser{&p15, &p99, &p174, &p135, &p16} - var p157 = sequenceParser{id: 157, commit: 72, allChars: true, name: "ws", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{52}} - var p43 = charParser{id: 43, not: false, chars: []rune{119}, ranges: [][]rune{}} - var p39 = charParser{id: 39, not: false, chars: []rune{115}, ranges: [][]rune{}} - p157.items = []parser{&p43, &p39} - var p116 = sequenceParser{id: 116, commit: 72, allChars: true, name: "nows", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{52}} - var p22 = charParser{id: 22, not: false, chars: []rune{110}, ranges: [][]rune{}} - var p145 = charParser{id: 145, not: false, chars: []rune{111}, ranges: [][]rune{}} - var p113 = charParser{id: 113, not: false, chars: []rune{119}, ranges: [][]rune{}} - var p1 = charParser{id: 1, not: false, chars: []rune{115}, ranges: [][]rune{}} - p116.items = []parser{&p22, &p145, &p113, &p1} - var p2 = sequenceParser{id: 2, commit: 72, allChars: true, name: "failpass", 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{52}} - var p23 = charParser{id: 23, not: false, chars: []rune{102}, ranges: [][]rune{}} - var p82 = charParser{id: 82, not: false, chars: []rune{97}, ranges: [][]rune{}} - var p62 = charParser{id: 62, not: false, chars: []rune{105}, ranges: [][]rune{}} - var p59 = charParser{id: 59, not: false, chars: []rune{108}, ranges: [][]rune{}} - var p44 = charParser{id: 44, not: false, chars: []rune{112}, ranges: [][]rune{}} - var p100 = charParser{id: 100, not: false, chars: []rune{97}, ranges: [][]rune{}} - var p158 = charParser{id: 158, not: false, chars: []rune{115}, ranges: [][]rune{}} - var p103 = charParser{id: 103, not: false, chars: []rune{115}, ranges: [][]rune{}} - p2.items = []parser{&p23, &p82, &p62, &p59, &p44, &p100, &p158, &p103} - var p177 = sequenceParser{id: 177, commit: 72, allChars: true, name: "root", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{52}} - var p76 = charParser{id: 76, not: false, chars: []rune{114}, ranges: [][]rune{}} - var p83 = charParser{id: 83, not: false, chars: []rune{111}, ranges: [][]rune{}} - var p78 = charParser{id: 78, not: false, chars: []rune{111}, ranges: [][]rune{}} - var p45 = charParser{id: 45, not: false, chars: []rune{116}, ranges: [][]rune{}} - p177.items = []parser{&p76, &p83, &p78, &p45} - p52.options = []parser{&p139, &p157, &p116, &p2, &p177} - p77.items = []parser{&p155, &p52} - p95.items = []parser{&p42, &p77} - var p13 = sequenceParser{id: 13, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p117 = charParser{id: 117, not: false, chars: []rune{61}, ranges: [][]rune{}} - p13.items = []parser{&p117} - var p14 = choiceParser{id: 14, commit: 66, name: "expression", generalizations: []int{}} - var p168 = choiceParser{id: 168, commit: 66, name: "terminal", generalizations: []int{14, 128, 94}} - var p91 = sequenceParser{id: 91, commit: 72, allChars: true, name: "any-char", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{168, 14, 128, 94}} - var p106 = charParser{id: 106, not: false, chars: []rune{46}, ranges: [][]rune{}} - p91.items = []parser{&p106} - var p143 = sequenceParser{id: 143, commit: 72, allChars: false, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{168, 14, 128, 94}} - var p111 = sequenceParser{id: 111, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p81 = charParser{id: 81, not: false, chars: []rune{91}, ranges: [][]rune{}} - p111.items = []parser{&p81} - var p50 = sequenceParser{id: 50, commit: 72, allChars: true, name: "class-not", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p119 = charParser{id: 119, not: false, chars: []rune{94}, ranges: [][]rune{}} - p50.items = []parser{&p119} - var p149 = choiceParser{id: 149, commit: 10, generalizations: []int{}} - var p98 = choiceParser{id: 98, commit: 72, name: "class-char", generalizations: []int{149}} - var p166 = sequenceParser{id: 166, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{98, 149}} - var p107 = charParser{id: 107, not: true, chars: []rune{92, 91, 93, 94, 45}, ranges: [][]rune{}} - p166.items = []parser{&p107} - var p110 = sequenceParser{id: 110, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{98, 149}} - var p133 = sequenceParser{id: 133, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p132 = charParser{id: 132, not: false, chars: []rune{92}, ranges: [][]rune{}} - p133.items = []parser{&p132} - var p162 = sequenceParser{id: 162, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p161 = charParser{id: 161, not: true, chars: []rune{}, ranges: [][]rune{}} - p162.items = []parser{&p161} - p110.items = []parser{&p133, &p162} - p98.options = []parser{&p166, &p110} - var p4 = sequenceParser{id: 4, commit: 72, allChars: false, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{149}} - var p167 = sequenceParser{id: 167, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p175 = charParser{id: 175, not: false, chars: []rune{45}, ranges: [][]rune{}} - p167.items = []parser{&p175} - p4.items = []parser{&p98, &p167, &p98} - p149.options = []parser{&p98, &p4} - var p5 = sequenceParser{id: 5, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p183 = charParser{id: 183, not: false, chars: []rune{93}, ranges: [][]rune{}} - p5.items = []parser{&p183} - p143.items = []parser{&p111, &p50, &p149, &p5} - var p84 = sequenceParser{id: 84, commit: 72, allChars: false, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{168, 14, 128, 94}} - var p101 = sequenceParser{id: 101, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p150 = charParser{id: 150, not: false, chars: []rune{34}, ranges: [][]rune{}} - p101.items = []parser{&p150} - var p172 = choiceParser{id: 172, commit: 72, name: "sequence-char", generalizations: []int{}} - var p67 = sequenceParser{id: 67, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{172}} - var p74 = charParser{id: 74, not: true, chars: []rune{92, 34}, ranges: [][]rune{}} - p67.items = []parser{&p74} - var p32 = sequenceParser{id: 32, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{172}} - var p108 = sequenceParser{id: 108, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p184 = charParser{id: 184, not: false, chars: []rune{92}, ranges: [][]rune{}} - p108.items = []parser{&p184} - var p10 = sequenceParser{id: 10, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p68 = charParser{id: 68, not: true, chars: []rune{}, ranges: [][]rune{}} - p10.items = []parser{&p68} - p32.items = []parser{&p108, &p10} - p172.options = []parser{&p67, &p32} - var p25 = sequenceParser{id: 25, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p37 = charParser{id: 37, not: false, chars: []rune{34}, ranges: [][]rune{}} - p25.items = []parser{&p37} - p84.items = []parser{&p101, &p172, &p25} - p168.options = []parser{&p91, &p143, &p84} - var p21 = sequenceParser{id: 21, commit: 66, allChars: false, name: "group", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{14, 128, 94}} - var p154 = sequenceParser{id: 154, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p56 = charParser{id: 56, not: false, chars: []rune{40}, ranges: [][]rune{}} - p154.items = []parser{&p56} - var p120 = sequenceParser{id: 120, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p20 = charParser{id: 20, not: false, chars: []rune{41}, ranges: [][]rune{}} - p120.items = []parser{&p20} - p21.items = []parser{&p154, &p186, &p14, &p186, &p120} - var p8 = sequenceParser{id: 8, commit: 64, allChars: false, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{14, 94}} - var p115 = sequenceParser{id: 115, commit: 72, allChars: false, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}, generalizations: []int{}} - var p128 = choiceParser{id: 128, commit: 10, generalizations: []int{}} - p128.options = []parser{&p168, &p42, &p21} - var p179 = choiceParser{id: 179, commit: 66, name: "quantity", generalizations: []int{}} - var p152 = sequenceParser{id: 152, commit: 64, allChars: false, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{179}} - var p170 = sequenceParser{id: 170, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p151 = charParser{id: 151, not: false, chars: []rune{123}, ranges: [][]rune{}} - p170.items = []parser{&p151} - var p127 = sequenceParser{id: 127, commit: 64, allChars: false, name: "count", ranges: [][]int{{1, 1}}, generalizations: []int{}} - var p51 = sequenceParser{id: 51, commit: 74, allChars: false, name: "number", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{}} - var p176 = sequenceParser{id: 176, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p126 = charParser{id: 126, not: false, chars: []rune{}, ranges: [][]rune{{48, 57}}} - p176.items = []parser{&p126} - p51.items = []parser{&p176} - p127.items = []parser{&p51} - var p6 = sequenceParser{id: 6, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p26 = charParser{id: 26, not: false, chars: []rune{125}, ranges: [][]rune{}} - p6.items = []parser{&p26} - p152.items = []parser{&p170, &p186, &p127, &p186, &p6} - var p92 = sequenceParser{id: 92, commit: 64, allChars: false, 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{179}} - var p85 = sequenceParser{id: 85, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p75 = charParser{id: 75, not: false, chars: []rune{123}, ranges: [][]rune{}} - p85.items = []parser{&p75} - var p102 = sequenceParser{id: 102, commit: 64, allChars: false, name: "range-from", ranges: [][]int{{1, 1}}, generalizations: []int{}} - p102.items = []parser{&p51} - var p112 = sequenceParser{id: 112, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p86 = charParser{id: 86, not: false, chars: []rune{44}, ranges: [][]rune{}} - p112.items = []parser{&p86} - var p138 = sequenceParser{id: 138, commit: 64, allChars: false, name: "range-to", ranges: [][]int{{1, 1}}, generalizations: []int{}} - p138.items = []parser{&p51} - var p57 = sequenceParser{id: 57, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p58 = charParser{id: 58, not: false, chars: []rune{125}, ranges: [][]rune{}} - p57.items = []parser{&p58} - p92.items = []parser{&p85, &p186, &p102, &p186, &p112, &p186, &p138, &p186, &p57} - var p38 = sequenceParser{id: 38, commit: 72, allChars: true, name: "one-or-more", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{179}} - var p163 = charParser{id: 163, not: false, chars: []rune{43}, ranges: [][]rune{}} - p38.items = []parser{&p163} - var p178 = sequenceParser{id: 178, commit: 72, allChars: true, name: "zero-or-more", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{179}} - var p93 = charParser{id: 93, not: false, chars: []rune{42}, ranges: [][]rune{}} - p178.items = []parser{&p93} - var p156 = sequenceParser{id: 156, commit: 72, allChars: true, name: "zero-or-one", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{179}} - var p146 = charParser{id: 146, not: false, chars: []rune{63}, ranges: [][]rune{}} - p156.items = []parser{&p146} - p179.options = []parser{&p152, &p92, &p38, &p178, &p156} - p115.items = []parser{&p128, &p179} - var p7 = sequenceParser{id: 7, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} - p7.items = []parser{&p186, &p115} - p8.items = []parser{&p115, &p7} - var p61 = sequenceParser{id: 61, commit: 64, allChars: false, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{14}} - var p94 = choiceParser{id: 94, commit: 66, name: "option", generalizations: []int{}} - p94.options = []parser{&p168, &p42, &p21, &p8} - var p11 = sequenceParser{id: 11, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}, generalizations: []int{}} - var p134 = sequenceParser{id: 134, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p173 = charParser{id: 173, not: false, chars: []rune{124}, ranges: [][]rune{}} - p134.items = []parser{&p173} - p11.items = []parser{&p134, &p186, &p94} - var p60 = sequenceParser{id: 60, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} - p60.items = []parser{&p186, &p11} - p61.items = []parser{&p94, &p186, &p11, &p60} - p14.options = []parser{&p168, &p42, &p21, &p8, &p61} - p165.items = []parser{&p95, &p186, &p13, &p186, &p14} - var p34 = sequenceParser{id: 34, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} - var p130 = sequenceParser{id: 130, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}, generalizations: []int{}} - var p12 = sequenceParser{id: 12, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p27 = charParser{id: 27, not: false, chars: []rune{59}, ranges: [][]rune{}} - p12.items = []parser{&p27} - var p129 = sequenceParser{id: 129, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} - p129.items = []parser{&p186, &p12} - p130.items = []parser{&p12, &p129, &p186, &p165} - var p33 = sequenceParser{id: 33, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} - p33.items = []parser{&p186, &p130} - p34.items = []parser{&p186, &p130, &p33} - p35.items = []parser{&p165, &p34} - var p72 = sequenceParser{id: 72, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} - var p46 = sequenceParser{id: 46, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} - var p164 = charParser{id: 164, not: false, chars: []rune{59}, ranges: [][]rune{}} - p46.items = []parser{&p164} - var p71 = sequenceParser{id: 71, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} - p71.items = []parser{&p186, &p46} - p72.items = []parser{&p186, &p46, &p71} - p187.items = []parser{&p70, &p186, &p35, &p72} - p188.items = []parser{&p186, &p187, &p186} - var b188 = sequenceBuilder{id: 188, commit: 32, allChars: false, name: "syntax", ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var b186 = choiceBuilder{id: 186, commit: 2} - var b185 = choiceBuilder{id: 185, commit: 70} - var b171 = choiceBuilder{id: 171, commit: 66} - var b63 = sequenceBuilder{id: 63, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b28 = charBuilder{} - b63.items = []builder{&b28} - var b121 = sequenceBuilder{id: 121, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b17 = charBuilder{} - b121.items = []builder{&b17} - var b79 = sequenceBuilder{id: 79, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b53 = charBuilder{} - b79.items = []builder{&b53} - var b114 = sequenceBuilder{id: 114, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b96 = charBuilder{} - b114.items = []builder{&b96} - var b141 = sequenceBuilder{id: 141, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b9 = charBuilder{} - b141.items = []builder{&b9} - var b47 = sequenceBuilder{id: 47, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b87 = charBuilder{} - b47.items = []builder{&b87} - var b40 = sequenceBuilder{id: 40, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b18 = charBuilder{} - b40.items = []builder{&b18} - b171.options = []builder{&b63, &b121, &b79, &b114, &b141, &b47, &b40} - var b90 = sequenceBuilder{id: 90, commit: 72, allChars: false, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} - var b142 = choiceBuilder{id: 142, commit: 74} - var b80 = sequenceBuilder{id: 80, commit: 74, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} - var b41 = sequenceBuilder{id: 41, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b65 = charBuilder{} - var b148 = charBuilder{} - b41.items = []builder{&b65, &b148} - var b55 = sequenceBuilder{id: 55, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b124 = charBuilder{} - b55.items = []builder{&b124} - b80.items = []builder{&b41, &b55} - var b48 = sequenceBuilder{id: 48, commit: 74, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}} - var b97 = sequenceBuilder{id: 97, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b64 = charBuilder{} - var b54 = charBuilder{} - b97.items = []builder{&b64, &b54} - var b89 = choiceBuilder{id: 89, commit: 10} - var b104 = sequenceBuilder{id: 104, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b29 = sequenceBuilder{id: 29, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b88 = charBuilder{} - b29.items = []builder{&b88} - var b122 = sequenceBuilder{id: 122, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b131 = charBuilder{} - b122.items = []builder{&b131} - b104.items = []builder{&b29, &b122} - var b159 = sequenceBuilder{id: 159, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b123 = charBuilder{} - b159.items = []builder{&b123} - b89.options = []builder{&b104, &b159} - var b19 = sequenceBuilder{id: 19, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b153 = charBuilder{} - var b24 = charBuilder{} - b19.items = []builder{&b153, &b24} - b48.items = []builder{&b97, &b89, &b19} - b142.options = []builder{&b80, &b48} - var b3 = sequenceBuilder{id: 3, commit: 10, allChars: false, ranges: [][]int{{0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}} - var b160 = choiceBuilder{id: 160, commit: 74} - var b66 = sequenceBuilder{id: 66, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b109 = charBuilder{} - b66.items = []builder{&b109} - var b180 = sequenceBuilder{id: 180, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b30 = charBuilder{} - b180.items = []builder{&b30} - var b136 = sequenceBuilder{id: 136, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b125 = charBuilder{} - b136.items = []builder{&b125} - var b118 = sequenceBuilder{id: 118, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b31 = charBuilder{} - b118.items = []builder{&b31} - var b49 = sequenceBuilder{id: 49, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b73 = charBuilder{} - b49.items = []builder{&b73} - var b182 = sequenceBuilder{id: 182, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b181 = charBuilder{} - b182.items = []builder{&b181} - b160.options = []builder{&b66, &b180, &b136, &b118, &b49, &b182} - var b137 = sequenceBuilder{id: 137, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b105 = charBuilder{} - b137.items = []builder{&b105} - b3.items = []builder{&b160, &b137, &b160, &b142} - b90.items = []builder{&b142, &b3} - b185.options = []builder{&b171, &b90} - b186.options = []builder{&b185} - var b187 = sequenceBuilder{id: 187, commit: 66, allChars: false, ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}} - var b70 = sequenceBuilder{id: 70, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}}} - var b36 = sequenceBuilder{id: 36, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b140 = charBuilder{} - b36.items = []builder{&b140} - var b69 = sequenceBuilder{id: 69, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} - b69.items = []builder{&b186, &b36} - b70.items = []builder{&b36, &b69} - var b35 = sequenceBuilder{id: 35, commit: 66, allChars: false, ranges: [][]int{{1, 1}, {0, 1}}} - var b165 = sequenceBuilder{id: 165, commit: 64, allChars: false, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} - var b95 = sequenceBuilder{id: 95, commit: 74, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} - var b42 = sequenceBuilder{id: 42, commit: 72, allChars: false, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}} - var b144 = sequenceBuilder{id: 144, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b169 = charBuilder{} - b144.items = []builder{&b169} - b42.items = []builder{&b144} - var b77 = sequenceBuilder{id: 77, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b155 = sequenceBuilder{id: 155, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b147 = charBuilder{} - b155.items = []builder{&b147} - var b52 = choiceBuilder{id: 52, commit: 66} - var b139 = sequenceBuilder{id: 139, commit: 72, allChars: true, name: "alias", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b15 = charBuilder{} - var b99 = charBuilder{} - var b174 = charBuilder{} - var b135 = charBuilder{} - var b16 = charBuilder{} - b139.items = []builder{&b15, &b99, &b174, &b135, &b16} - var b157 = sequenceBuilder{id: 157, commit: 72, allChars: true, name: "ws", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b43 = charBuilder{} - var b39 = charBuilder{} - b157.items = []builder{&b43, &b39} - var b116 = sequenceBuilder{id: 116, commit: 72, allChars: true, name: "nows", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b22 = charBuilder{} - var b145 = charBuilder{} - var b113 = charBuilder{} - var b1 = charBuilder{} - b116.items = []builder{&b22, &b145, &b113, &b1} - var b2 = sequenceBuilder{id: 2, commit: 72, allChars: true, name: "failpass", 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}}} - var b23 = charBuilder{} - var b82 = charBuilder{} - var b62 = charBuilder{} - var b59 = charBuilder{} - var b44 = charBuilder{} - var b100 = charBuilder{} - var b158 = charBuilder{} - var b103 = charBuilder{} - b2.items = []builder{&b23, &b82, &b62, &b59, &b44, &b100, &b158, &b103} - var b177 = sequenceBuilder{id: 177, commit: 72, allChars: true, name: "root", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b76 = charBuilder{} - var b83 = charBuilder{} - var b78 = charBuilder{} - var b45 = charBuilder{} - b177.items = []builder{&b76, &b83, &b78, &b45} - b52.options = []builder{&b139, &b157, &b116, &b2, &b177} - b77.items = []builder{&b155, &b52} - b95.items = []builder{&b42, &b77} - var b13 = sequenceBuilder{id: 13, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b117 = charBuilder{} - b13.items = []builder{&b117} - var b14 = choiceBuilder{id: 14, commit: 66} - var b168 = choiceBuilder{id: 168, commit: 66} - var b91 = sequenceBuilder{id: 91, commit: 72, allChars: true, name: "any-char", ranges: [][]int{{1, 1}, {1, 1}}} - var b106 = charBuilder{} - b91.items = []builder{&b106} - var b143 = sequenceBuilder{id: 143, commit: 72, allChars: false, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}} - var b111 = sequenceBuilder{id: 111, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b81 = charBuilder{} - b111.items = []builder{&b81} - var b50 = sequenceBuilder{id: 50, commit: 72, allChars: true, name: "class-not", ranges: [][]int{{1, 1}, {1, 1}}} - var b119 = charBuilder{} - b50.items = []builder{&b119} - var b149 = choiceBuilder{id: 149, commit: 10} - var b98 = choiceBuilder{id: 98, commit: 72, name: "class-char"} - var b166 = sequenceBuilder{id: 166, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b107 = charBuilder{} - b166.items = []builder{&b107} - var b110 = sequenceBuilder{id: 110, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b133 = sequenceBuilder{id: 133, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b132 = charBuilder{} - b133.items = []builder{&b132} - var b162 = sequenceBuilder{id: 162, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b161 = charBuilder{} - b162.items = []builder{&b161} - b110.items = []builder{&b133, &b162} - b98.options = []builder{&b166, &b110} - var b4 = sequenceBuilder{id: 4, commit: 72, allChars: false, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b167 = sequenceBuilder{id: 167, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b175 = charBuilder{} - b167.items = []builder{&b175} - b4.items = []builder{&b98, &b167, &b98} - b149.options = []builder{&b98, &b4} - var b5 = sequenceBuilder{id: 5, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b183 = charBuilder{} - b5.items = []builder{&b183} - b143.items = []builder{&b111, &b50, &b149, &b5} - var b84 = sequenceBuilder{id: 84, commit: 72, allChars: false, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}} - var b101 = sequenceBuilder{id: 101, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b150 = charBuilder{} - b101.items = []builder{&b150} - var b172 = choiceBuilder{id: 172, commit: 72, name: "sequence-char"} - var b67 = sequenceBuilder{id: 67, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b74 = charBuilder{} - b67.items = []builder{&b74} - var b32 = sequenceBuilder{id: 32, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} - var b108 = sequenceBuilder{id: 108, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b184 = charBuilder{} - b108.items = []builder{&b184} - var b10 = sequenceBuilder{id: 10, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b68 = charBuilder{} - b10.items = []builder{&b68} - b32.items = []builder{&b108, &b10} - b172.options = []builder{&b67, &b32} - var b25 = sequenceBuilder{id: 25, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b37 = charBuilder{} - b25.items = []builder{&b37} - b84.items = []builder{&b101, &b172, &b25} - b168.options = []builder{&b91, &b143, &b84} - var b21 = sequenceBuilder{id: 21, commit: 66, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} - var b154 = sequenceBuilder{id: 154, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b56 = charBuilder{} - b154.items = []builder{&b56} - var b120 = sequenceBuilder{id: 120, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b20 = charBuilder{} - b120.items = []builder{&b20} - b21.items = []builder{&b154, &b186, &b14, &b186, &b120} - var b8 = sequenceBuilder{id: 8, commit: 64, allChars: false, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}} - var b115 = sequenceBuilder{id: 115, commit: 72, allChars: false, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}} - var b128 = choiceBuilder{id: 128, commit: 10} - b128.options = []builder{&b168, &b42, &b21} - var b179 = choiceBuilder{id: 179, commit: 66} - var b152 = sequenceBuilder{id: 152, commit: 64, allChars: false, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} - var b170 = sequenceBuilder{id: 170, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b151 = charBuilder{} - b170.items = []builder{&b151} - var b127 = sequenceBuilder{id: 127, commit: 64, allChars: false, name: "count", ranges: [][]int{{1, 1}}} - var b51 = sequenceBuilder{id: 51, commit: 74, allChars: false, ranges: [][]int{{1, -1}, {1, -1}}} - var b176 = sequenceBuilder{id: 176, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b126 = charBuilder{} - b176.items = []builder{&b126} - b51.items = []builder{&b176} - b127.items = []builder{&b51} - var b6 = sequenceBuilder{id: 6, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b26 = charBuilder{} - b6.items = []builder{&b26} - b152.items = []builder{&b170, &b186, &b127, &b186, &b6} - var b92 = sequenceBuilder{id: 92, commit: 64, allChars: false, name: "range-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}} - var b85 = sequenceBuilder{id: 85, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b75 = charBuilder{} - b85.items = []builder{&b75} - var b102 = sequenceBuilder{id: 102, commit: 64, allChars: false, name: "range-from", ranges: [][]int{{1, 1}}} - b102.items = []builder{&b51} - var b112 = sequenceBuilder{id: 112, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b86 = charBuilder{} - b112.items = []builder{&b86} - var b138 = sequenceBuilder{id: 138, commit: 64, allChars: false, name: "range-to", ranges: [][]int{{1, 1}}} - b138.items = []builder{&b51} - var b57 = sequenceBuilder{id: 57, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b58 = charBuilder{} - b57.items = []builder{&b58} - b92.items = []builder{&b85, &b186, &b102, &b186, &b112, &b186, &b138, &b186, &b57} - var b38 = sequenceBuilder{id: 38, commit: 72, allChars: true, name: "one-or-more", ranges: [][]int{{1, 1}, {1, 1}}} - var b163 = charBuilder{} - b38.items = []builder{&b163} - var b178 = sequenceBuilder{id: 178, commit: 72, allChars: true, name: "zero-or-more", ranges: [][]int{{1, 1}, {1, 1}}} - var b93 = charBuilder{} - b178.items = []builder{&b93} - var b156 = sequenceBuilder{id: 156, commit: 72, allChars: true, name: "zero-or-one", ranges: [][]int{{1, 1}, {1, 1}}} - var b146 = charBuilder{} - b156.items = []builder{&b146} - b179.options = []builder{&b152, &b92, &b38, &b178, &b156} - b115.items = []builder{&b128, &b179} - var b7 = sequenceBuilder{id: 7, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} - b7.items = []builder{&b186, &b115} - b8.items = []builder{&b115, &b7} - var b61 = sequenceBuilder{id: 61, commit: 64, allChars: false, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} - var b94 = choiceBuilder{id: 94, commit: 66} - b94.options = []builder{&b168, &b42, &b21, &b8} - var b11 = sequenceBuilder{id: 11, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}} - var b134 = sequenceBuilder{id: 134, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b173 = charBuilder{} - b134.items = []builder{&b173} - b11.items = []builder{&b134, &b186, &b94} - var b60 = sequenceBuilder{id: 60, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} - b60.items = []builder{&b186, &b11} - b61.items = []builder{&b94, &b186, &b11, &b60} - b14.options = []builder{&b168, &b42, &b21, &b8, &b61} - b165.items = []builder{&b95, &b186, &b13, &b186, &b14} - var b34 = sequenceBuilder{id: 34, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var b130 = sequenceBuilder{id: 130, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}} - var b12 = sequenceBuilder{id: 12, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b27 = charBuilder{} - b12.items = []builder{&b27} - var b129 = sequenceBuilder{id: 129, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} - b129.items = []builder{&b186, &b12} - b130.items = []builder{&b12, &b129, &b186, &b165} - var b33 = sequenceBuilder{id: 33, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} - b33.items = []builder{&b186, &b130} - b34.items = []builder{&b186, &b130, &b33} - b35.items = []builder{&b165, &b34} - var b72 = sequenceBuilder{id: 72, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} - var b46 = sequenceBuilder{id: 46, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} - var b164 = charBuilder{} - b46.items = []builder{&b164} - var b71 = sequenceBuilder{id: 71, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} - b71.items = []builder{&b186, &b46} - b72.items = []builder{&b186, &b46, &b71} - b187.items = []builder{&b70, &b186, &b35, &b72} - b188.items = []builder{&b186, &b187, &b186} - - c := newContext(bufio.NewReader(r)) - p188.parse(c) - if c.readErr != nil { - return nil, c.readErr - } - - if err := c.finalizeParse(&p188); err != nil { - if perr, ok := err.(*ParseError); ok { - perr.Input = "" - } - - return nil, err - } - - c.offset = 0 - c.results.resetPending() - - n, _ := b188.build(c) - return n[0], nil -} diff --git a/scripts/boot.go b/scripts/boot.go index d24773c..83e20d6 100644 --- a/scripts/boot.go +++ b/scripts/boot.go @@ -7,11 +7,6 @@ import ( "github.com/aryszka/treerack" ) -const ( - syntaxPath = "syntax.treerack" - outputPath = "parser.go" -) - func main() { s := &treerack.Syntax{} @@ -19,7 +14,7 @@ func main() { log.Fatalln(err) } - if err := s.Generate(os.Stdout); err != nil { + if err := s.Generate(treerack.GeneratorOptions{PackageName: "self"}, os.Stdout); err != nil { log.Fatalln(err) } } diff --git a/scripts/createhead.go b/scripts/createhead.go new file mode 100644 index 0000000..c0460c5 --- /dev/null +++ b/scripts/createhead.go @@ -0,0 +1,102 @@ +package main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/parser" + "go/printer" + "go/token" + "io" + "log" + "os" + "strconv" + "strings" +) + +func concatGo(w io.Writer, r ...io.Reader) error { + var others []ast.Decl + imports := &ast.GenDecl{ + Tok: token.IMPORT, + Lparen: 1, + Rparen: 1, + } + + importPaths := make(map[string]bool) + for i := range r { + f, err := parser.ParseFile(token.NewFileSet(), "", r[i], 0) + if err != nil { + return err + } + + for j := range f.Decls { + d := f.Decls[j] + switch dd := d.(type) { + case *ast.GenDecl: + if dd.Tok != token.IMPORT { + others = append(others, d) + continue + } + + for k := range dd.Specs { + i := dd.Specs[k].(*ast.ImportSpec) + path := i.Path.Value + name := "" + if i.Name != nil { + name = i.Name.Name + } + + key := "(" + name + ")" + path + if importPaths[key] { + continue + } + + importPaths[key] = true + imports.Specs = append(imports.Specs, i) + } + default: + others = append(others, d) + } + } + } + + return printer.Fprint(w, token.NewFileSet(), &ast.File{ + Name: &ast.Ident{Name: ""}, + Decls: append([]ast.Decl{imports}, others...), + }) +} + +func removePackage(gO string) string { + // so we know that it's the first line + nl := strings.Index(gO, "\n") + return gO[nl+2:] +} + +func main() { + var packageName string + flag.StringVar(&packageName, "package", "treerack", "package name of the generated code file") + flag.Parse() + + var files []io.Reader + for _, fn := range flag.Args() { + f, err := os.Open(fn) + if err != nil { + log.Fatalln(err) + } + + defer f.Close() + files = append(files, f) + } + + var headCode bytes.Buffer + if err := concatGo(&headCode, files...); err != nil { + log.Fatalln(err) + } + + code := headCode.String() + code = removePackage(code) + quotedCode := strconv.Quote(code) + + fmt.Printf("package %s\n\n// generated with scripts/createhead.go\nconst headCode=%s", packageName, quotedCode) +} diff --git a/self/self.go b/self/self.go new file mode 100644 index 0000000..f20e804 --- /dev/null +++ b/self/self.go @@ -0,0 +1,1345 @@ +/* +This file was generated by treerack (https://github.com/aryszka/treerack). + +The contents of this file fall under different licenses. + +The code between the "// head" and "// eo head" lines falls under the same +license as the source code of treerack (https://github.com/aryszka/treerack), +unless explicitly stated otherwise, if treerack's license allows changing the +license of this source code. + +Treerack's license: MIT https://opensource.org/licenses/MIT +where YEAR=2018, COPYRIGHT HOLDER=Arpad Ryszka (arpad.ryszka@gmail.com) + +The rest of the content of this file falls under the same license as the one +that the user of treerack generating this file declares for it, or it is +unlicensed. +*/ + +package self + +import ( + "bufio" + "errors" + "fmt" + "io" + "strconv" + "strings" + "unicode" +) + +type charParser struct { + name string + id int + not bool + chars []rune + ranges [][]rune +} +type charBuilder struct { + name string + id int +} + +func (p *charParser) nodeName() string { + return p.name +} +func (p *charParser) nodeID() int { + return p.id +} +func (p *charParser) commitType() CommitType { + return Alias +} +func matchChar(chars []rune, ranges [][]rune, not bool, char rune) bool { + for _, ci := range chars { + if ci == char { + return !not + } + } + for _, ri := range ranges { + if char >= ri[0] && char <= ri[1] { + return !not + } + } + return not +} +func (p *charParser) match(t rune) bool { + return matchChar(p.chars, p.ranges, p.not, t) +} +func (p *charParser) parse(c *context) { + if tok, ok := c.token(); !ok || !p.match(tok) { + if c.offset > c.failOffset { + c.failOffset = c.offset + c.failingParser = nil + } + c.fail(c.offset) + return + } + c.success(c.offset + 1) +} +func (b *charBuilder) nodeName() string { + return b.name +} +func (b *charBuilder) nodeID() int { + return b.id +} +func (b *charBuilder) build(c *context) ([]*Node, bool) { + return nil, false +} + +type sequenceParser struct { + name string + id int + commit CommitType + items []parser + ranges [][]int + generalizations []int + allChars bool +} +type sequenceBuilder struct { + name string + id int + commit CommitType + items []builder + ranges [][]int + allChars bool +} + +func (p *sequenceParser) nodeName() string { + return p.name +} +func (p *sequenceParser) nodeID() int { + return p.id +} +func (p *sequenceParser) commitType() CommitType { + return p.commit +} +func (p *sequenceParser) parse(c *context) { + if !p.allChars { + if c.results.pending(c.offset, p.id) { + c.fail(c.offset) + return + } + c.results.markPending(c.offset, p.id) + } + var ( + currentCount int + parsed bool + ) + itemIndex := 0 + from := c.offset + to := c.offset + for itemIndex < len(p.items) { + p.items[itemIndex].parse(c) + if !c.matchLast { + if currentCount >= p.ranges[itemIndex][0] { + itemIndex++ + currentCount = 0 + continue + } + if c.failingParser == nil && p.commit&userDefined != 0 && p.commit&Whitespace == 0 && p.commit&FailPass == 0 { + c.failingParser = p + } + c.fail(from) + if !p.allChars { + c.results.unmarkPending(from, p.id) + } + return + } + parsed = c.offset > to + if parsed { + currentCount++ + } + to = c.offset + if !parsed || p.ranges[itemIndex][1] > 0 && currentCount == p.ranges[itemIndex][1] { + itemIndex++ + currentCount = 0 + } + } + for _, g := range p.generalizations { + if c.results.pending(from, g) { + c.results.setMatch(from, g, to) + } + } + if to > c.failOffset { + c.failOffset = -1 + c.failingParser = nil + } + c.results.setMatch(from, p.id, to) + c.success(to) + if !p.allChars { + c.results.unmarkPending(from, p.id) + } +} +func (b *sequenceBuilder) nodeName() string { + return b.name +} +func (b *sequenceBuilder) nodeID() int { + return b.id +} +func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { + to, ok := c.results.longestMatch(c.offset, b.id) + if !ok { + return nil, false + } + from := c.offset + parsed := to > from + if b.allChars { + c.offset = to + if b.commit&Alias != 0 { + return nil, true + } + return []*Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true + } else if parsed { + c.results.dropMatchTo(c.offset, b.id, to) + } else { + if c.results.pending(c.offset, b.id) { + return nil, false + } + c.results.markPending(c.offset, b.id) + } + var ( + itemIndex int + currentCount int + nodes []*Node + ) + for itemIndex < len(b.items) { + itemFrom := c.offset + n, ok := b.items[itemIndex].build(c) + if !ok { + itemIndex++ + currentCount = 0 + continue + } + if c.offset > itemFrom { + nodes = append(nodes, n...) + currentCount++ + if b.ranges[itemIndex][1] > 0 && currentCount == b.ranges[itemIndex][1] { + itemIndex++ + currentCount = 0 + } + continue + } + if currentCount < b.ranges[itemIndex][0] { + for i := 0; i < b.ranges[itemIndex][0]-currentCount; i++ { + nodes = append(nodes, n...) + } + } + itemIndex++ + currentCount = 0 + } + if !parsed { + c.results.unmarkPending(from, b.id) + } + if b.commit&Alias != 0 { + return nodes, true + } + return []*Node{{Name: b.name, From: from, To: to, Nodes: nodes, tokens: c.tokens}}, true +} + +type choiceParser struct { + name string + id int + commit CommitType + options []parser + generalizations []int +} +type choiceBuilder struct { + name string + id int + commit CommitType + options []builder +} + +func (p *choiceParser) nodeName() string { + return p.name +} +func (p *choiceParser) nodeID() int { + return p.id +} +func (p *choiceParser) commitType() CommitType { + return p.commit +} +func (p *choiceParser) parse(c *context) { + if c.fromResults(p) { + return + } + if c.results.pending(c.offset, p.id) { + c.fail(c.offset) + return + } + c.results.markPending(c.offset, p.id) + var ( + match bool + optionIndex int + foundMatch bool + failingParser parser + ) + from := c.offset + to := c.offset + initialFailOffset := c.failOffset + initialFailingParser := c.failingParser + failOffset := initialFailOffset + for { + foundMatch = false + optionIndex = 0 + for optionIndex < len(p.options) { + p.options[optionIndex].parse(c) + optionIndex++ + if !c.matchLast { + if c.failOffset > failOffset { + failOffset = c.failOffset + failingParser = c.failingParser + } + } + if !c.matchLast || match && c.offset <= to { + c.offset = from + continue + } + match = true + foundMatch = true + to = c.offset + c.offset = from + c.results.setMatch(from, p.id, to) + } + if !foundMatch { + break + } + } + if match { + if failOffset > to { + c.failOffset = failOffset + c.failingParser = failingParser + } else if to > initialFailOffset { + c.failOffset = -1 + c.failingParser = nil + } else { + c.failOffset = initialFailOffset + c.failingParser = initialFailingParser + } + c.success(to) + c.results.unmarkPending(from, p.id) + return + } + if failOffset > initialFailOffset { + c.failOffset = failOffset + c.failingParser = failingParser + if c.failingParser == nil && p.commitType()&userDefined != 0 && p.commitType()&Whitespace == 0 && p.commitType()&FailPass == 0 { + c.failingParser = p + } + } + c.results.setNoMatch(from, p.id) + c.fail(from) + c.results.unmarkPending(from, p.id) +} +func (b *choiceBuilder) nodeName() string { + return b.name +} +func (b *choiceBuilder) nodeID() int { + return b.id +} +func (b *choiceBuilder) build(c *context) ([]*Node, bool) { + to, ok := c.results.longestMatch(c.offset, b.id) + if !ok { + return nil, false + } + from := c.offset + parsed := to > from + if parsed { + c.results.dropMatchTo(c.offset, b.id, to) + } else { + if c.results.pending(c.offset, b.id) { + return nil, false + } + c.results.markPending(c.offset, b.id) + } + var option builder + for _, o := range b.options { + if c.results.hasMatchTo(c.offset, o.nodeID(), to) { + option = o + break + } + } + n, _ := option.build(c) + if !parsed { + c.results.unmarkPending(from, b.id) + } + if b.commit&Alias != 0 { + return n, true + } + return []*Node{{Name: b.name, From: from, To: to, Nodes: n, tokens: c.tokens}}, true +} + +type idSet struct{ ids []uint } + +func divModBits(id int) (int, int) { + return id / strconv.IntSize, id % strconv.IntSize +} +func (s *idSet) set(id int) { + d, m := divModBits(id) + if d >= len(s.ids) { + if d < cap(s.ids) { + s.ids = s.ids[:d+1] + } else { + s.ids = s.ids[:cap(s.ids)] + for i := cap(s.ids); i <= d; i++ { + s.ids = append(s.ids, 0) + } + } + } + s.ids[d] |= 1 << uint(m) +} +func (s *idSet) unset(id int) { + d, m := divModBits(id) + if d >= len(s.ids) { + return + } + s.ids[d] &^= 1 << uint(m) +} +func (s *idSet) has(id int) bool { + d, m := divModBits(id) + if d >= len(s.ids) { + return false + } + return s.ids[d]&(1< offset { + return ints + } + if cap(ints) > offset { + ints = ints[:offset+1] + return ints + } + ints = ints[:cap(ints)] + for i := len(ints); i <= offset; i++ { + ints = append(ints, nil) + } + return ints +} +func ensureOffsetIDs(ids []*idSet, offset int) []*idSet { + if len(ids) > offset { + return ids + } + if cap(ids) > offset { + ids = ids[:offset+1] + return ids + } + ids = ids[:cap(ids)] + for i := len(ids); i <= offset; i++ { + ids = append(ids, nil) + } + return ids +} +func (r *results) setMatch(offset, id, to int) { + r.match = ensureOffsetInts(r.match, offset) + for i := 0; i < len(r.match[offset]); i += 2 { + if r.match[offset][i] != id || r.match[offset][i+1] != to { + continue + } + return + } + r.match[offset] = append(r.match[offset], id, to) +} +func (r *results) setNoMatch(offset, id int) { + if len(r.match) > offset { + for i := 0; i < len(r.match[offset]); i += 2 { + if r.match[offset][i] != id { + continue + } + return + } + } + r.noMatch = ensureOffsetIDs(r.noMatch, offset) + if r.noMatch[offset] == nil { + r.noMatch[offset] = &idSet{} + } + r.noMatch[offset].set(id) +} +func (r *results) hasMatchTo(offset, id, to int) bool { + if len(r.match) <= offset { + return false + } + for i := 0; i < len(r.match[offset]); i += 2 { + if r.match[offset][i] != id { + continue + } + if r.match[offset][i+1] == to { + return true + } + } + return false +} +func (r *results) longestMatch(offset, id int) (int, bool) { + if len(r.match) <= offset { + return 0, false + } + var found bool + to := -1 + for i := 0; i < len(r.match[offset]); i += 2 { + if r.match[offset][i] != id { + continue + } + if r.match[offset][i+1] > to { + to = r.match[offset][i+1] + } + found = true + } + return to, found +} +func (r *results) longestResult(offset, id int) (int, bool, bool) { + if len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) { + return 0, false, true + } + to, ok := r.longestMatch(offset, id) + return to, ok, ok +} +func (r *results) dropMatchTo(offset, id, to int) { + for i := 0; i < len(r.match[offset]); i += 2 { + if r.match[offset][i] != id { + continue + } + if r.match[offset][i+1] == to { + r.match[offset][i] = -1 + return + } + } +} +func (r *results) resetPending() { + r.isPending = nil +} +func (r *results) pending(offset, id int) bool { + if len(r.isPending) <= id { + return false + } + for i := range r.isPending[id] { + if r.isPending[id][i] == offset { + return true + } + } + return false +} +func (r *results) markPending(offset, id int) { + r.isPending = ensureOffsetInts(r.isPending, id) + for i := range r.isPending[id] { + if r.isPending[id][i] == -1 { + r.isPending[id][i] = offset + return + } + } + r.isPending[id] = append(r.isPending[id], offset) +} +func (r *results) unmarkPending(offset, id int) { + for i := range r.isPending[id] { + if r.isPending[id][i] == offset { + r.isPending[id][i] = -1 + break + } + } +} + +type context struct { + reader io.RuneReader + offset int + readOffset int + consumed int + failOffset int + failingParser parser + readErr error + eof bool + results *results + tokens []rune + matchLast bool +} + +func newContext(r io.RuneReader) *context { + return &context{reader: r, results: &results{}, failOffset: -1} +} +func (c *context) read() bool { + if c.eof || c.readErr != nil { + return false + } + token, n, err := c.reader.ReadRune() + if err != nil { + if err == io.EOF { + if n == 0 { + c.eof = true + return false + } + } else { + c.readErr = err + return false + } + } + c.readOffset++ + if token == unicode.ReplacementChar { + c.readErr = ErrInvalidUnicodeCharacter + return false + } + c.tokens = append(c.tokens, token) + return true +} +func (c *context) token() (rune, bool) { + if c.offset == c.readOffset { + if !c.read() { + return 0, false + } + } + return c.tokens[c.offset], true +} +func (c *context) fromResults(p parser) bool { + to, m, ok := c.results.longestResult(c.offset, p.nodeID()) + if !ok { + return false + } + if m { + c.success(to) + } else { + c.fail(c.offset) + } + return true +} +func (c *context) success(to int) { + c.offset = to + c.matchLast = true + if to > c.consumed { + c.consumed = to + } +} +func (c *context) fail(offset int) { + c.offset = offset + c.matchLast = false +} +func findLine(tokens []rune, offset int) (line, column int) { + tokens = tokens[:offset] + for i := range tokens { + column++ + if tokens[i] == '\n' { + column = 0 + line++ + } + } + return +} +func (c *context) parseError(p parser) error { + definition := p.nodeName() + flagIndex := strings.Index(definition, ":") + if flagIndex > 0 { + definition = definition[:flagIndex] + } + if c.failingParser == nil { + c.failOffset = c.consumed + } + line, col := findLine(c.tokens, c.failOffset) + return &ParseError{Offset: c.failOffset, Line: line, Column: col, Definition: definition} +} +func (c *context) finalizeParse(root parser) error { + fp := c.failingParser + if fp == nil { + fp = root + } + to, match, found := c.results.longestResult(0, root.nodeID()) + if !found || !match || found && match && to < c.readOffset { + return c.parseError(fp) + } + c.read() + if c.eof { + return nil + } + if c.readErr != nil { + return c.readErr + } + return c.parseError(root) +} + +type Node struct { + Name string + Nodes []*Node + From, To int + tokens []rune +} + +func (n *Node) Tokens() []rune { + defer func() { + if err := recover(); err != nil { + println(len(n.tokens), n.From, n.To) + panic(err) + } + }() + return n.tokens +} +func (n *Node) String() string { + return fmt.Sprintf("%s:%d:%d:%s", n.Name, n.From, n.To, n.Text()) +} +func (n *Node) Text() string { + return string(n.Tokens()[n.From:n.To]) +} + +type CommitType int + +const ( + None CommitType = 0 + Alias CommitType = 1 << iota + Whitespace + NoWhitespace + FailPass + Root + userDefined +) + +type formatFlags int + +const ( + formatNone formatFlags = 0 + formatPretty formatFlags = 1 << iota + formatIncludeComments +) + +type ParseError struct { + Input string + Offset int + Line int + Column int + Definition string +} +type parser interface { + nodeName() string + nodeID() int + commitType() CommitType + parse(*context) +} +type builder interface { + nodeName() string + nodeID() int + build(*context) ([]*Node, bool) +} + +var ErrInvalidUnicodeCharacter = errors.New("invalid unicode character") + +func (pe *ParseError) Error() string { + return fmt.Sprintf("%s:%d:%d:parse failed, parsing: %s", pe.Input, pe.Line+1, pe.Column+1, pe.Definition) +} +func parse(r io.Reader, p parser, b builder) (*Node, error) { + c := newContext(bufio.NewReader(r)) + p.parse(c) + if c.readErr != nil { + return nil, c.readErr + } + if err := c.finalizeParse(p); err != nil { + if perr, ok := err.(*ParseError); ok { + perr.Input = "" + } + return nil, err + } + c.offset = 0 + c.results.resetPending() + n, _ := b.build(c) + return n[0], nil +} + +func Parse(r io.Reader) (*Node, error) { + var p188 = sequenceParser{id: 188, commit: 32, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} + var p186 = choiceParser{id: 186, commit: 2, generalizations: []int{}} + var p185 = choiceParser{id: 185, commit: 70, name: "wsc", generalizations: []int{186}} + var p17 = choiceParser{id: 17, commit: 66, name: "wschar", generalizations: []int{185, 186}} + var p109 = sequenceParser{id: 109, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{17, 185, 186}} + var p108 = charParser{id: 108, not: false, chars: []rune{32}, ranges: [][]rune{}} + p109.items = []parser{&p108} + var p170 = sequenceParser{id: 170, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{17, 185, 186}} + var p137 = charParser{id: 137, not: false, chars: []rune{9}, ranges: [][]rune{}} + p170.items = []parser{&p137} + var p54 = sequenceParser{id: 54, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{17, 185, 186}} + var p147 = charParser{id: 147, not: false, chars: []rune{10}, ranges: [][]rune{}} + p54.items = []parser{&p147} + var p64 = sequenceParser{id: 64, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{17, 185, 186}} + var p157 = charParser{id: 157, not: false, chars: []rune{8}, ranges: [][]rune{}} + p64.items = []parser{&p157} + var p72 = sequenceParser{id: 72, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{17, 185, 186}} + var p121 = charParser{id: 121, not: false, chars: []rune{12}, ranges: [][]rune{}} + p72.items = []parser{&p121} + var p19 = sequenceParser{id: 19, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{17, 185, 186}} + var p16 = charParser{id: 16, not: false, chars: []rune{13}, ranges: [][]rune{}} + p19.items = []parser{&p16} + var p5 = sequenceParser{id: 5, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{17, 185, 186}} + var p73 = charParser{id: 73, not: false, chars: []rune{11}, ranges: [][]rune{}} + p5.items = []parser{&p73} + p17.options = []parser{&p109, &p170, &p54, &p64, &p72, &p19, &p5} + var p58 = sequenceParser{id: 58, commit: 72, allChars: false, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{185, 186}} + var p43 = choiceParser{id: 43, commit: 74, name: "comment-segment", generalizations: []int{}} + var p144 = sequenceParser{id: 144, commit: 74, allChars: false, name: "line-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{43}} + var p138 = sequenceParser{id: 138, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} + var p42 = charParser{id: 42, not: false, chars: []rune{47}, ranges: [][]rune{}} + var p35 = charParser{id: 35, not: false, chars: []rune{47}, ranges: [][]rune{}} + p138.items = []parser{&p42, &p35} + var p30 = sequenceParser{id: 30, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p166 = charParser{id: 166, not: true, chars: []rune{10}, ranges: [][]rune{}} + p30.items = []parser{&p166} + p144.items = []parser{&p138, &p30} + var p90 = sequenceParser{id: 90, commit: 74, allChars: false, name: "block-comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{43}} + var p129 = sequenceParser{id: 129, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} + var p158 = charParser{id: 158, not: false, chars: []rune{47}, ranges: [][]rune{}} + var p95 = charParser{id: 95, not: false, chars: []rune{42}, ranges: [][]rune{}} + p129.items = []parser{&p158, &p95} + var p6 = choiceParser{id: 6, commit: 10, generalizations: []int{}} + var p153 = sequenceParser{id: 153, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{6}} + var p101 = sequenceParser{id: 101, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p148 = charParser{id: 148, not: false, chars: []rune{42}, ranges: [][]rune{}} + p101.items = []parser{&p148} + var p13 = sequenceParser{id: 13, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p142 = charParser{id: 142, not: true, chars: []rune{47}, ranges: [][]rune{}} + p13.items = []parser{&p142} + p153.items = []parser{&p101, &p13} + var p143 = sequenceParser{id: 143, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{6}} + var p83 = charParser{id: 83, not: true, chars: []rune{42}, ranges: [][]rune{}} + p143.items = []parser{&p83} + p6.options = []parser{&p153, &p143} + var p89 = sequenceParser{id: 89, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} + var p96 = charParser{id: 96, not: false, chars: []rune{42}, ranges: [][]rune{}} + var p130 = charParser{id: 130, not: false, chars: []rune{47}, ranges: [][]rune{}} + p89.items = []parser{&p96, &p130} + p90.items = []parser{&p129, &p6, &p89} + p43.options = []parser{&p144, &p90} + var p31 = sequenceParser{id: 31, commit: 10, allChars: false, ranges: [][]int{{0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{}} + var p57 = choiceParser{id: 57, commit: 74, name: "ws-no-nl", generalizations: []int{}} + var p50 = sequenceParser{id: 50, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{57}} + var p167 = charParser{id: 167, not: false, chars: []rune{32}, ranges: [][]rune{}} + p50.items = []parser{&p167} + var p151 = sequenceParser{id: 151, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{57}} + var p114 = charParser{id: 114, not: false, chars: []rune{9}, ranges: [][]rune{}} + p151.items = []parser{&p114} + var p145 = sequenceParser{id: 145, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{57}} + var p36 = charParser{id: 36, not: false, chars: []rune{8}, ranges: [][]rune{}} + p145.items = []parser{&p36} + var p140 = sequenceParser{id: 140, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{57}} + var p122 = charParser{id: 122, not: false, chars: []rune{12}, ranges: [][]rune{}} + p140.items = []parser{&p122} + var p178 = sequenceParser{id: 178, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{57}} + var p77 = charParser{id: 77, not: false, chars: []rune{13}, ranges: [][]rune{}} + p178.items = []parser{&p77} + var p66 = sequenceParser{id: 66, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{57}} + var p37 = charParser{id: 37, not: false, chars: []rune{11}, ranges: [][]rune{}} + p66.items = []parser{&p37} + p57.options = []parser{&p50, &p151, &p145, &p140, &p178, &p66} + var p141 = sequenceParser{id: 141, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p51 = charParser{id: 51, not: false, chars: []rune{10}, ranges: [][]rune{}} + p141.items = []parser{&p51} + p31.items = []parser{&p57, &p141, &p57, &p43} + p58.items = []parser{&p43, &p31} + p185.options = []parser{&p17, &p58} + p186.options = []parser{&p185} + var p187 = sequenceParser{id: 187, commit: 66, allChars: false, name: "syntax:wsroot", ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}, generalizations: []int{}} + var p182 = sequenceParser{id: 182, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{}} + var p120 = sequenceParser{id: 120, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p119 = charParser{id: 119, not: false, chars: []rune{59}, ranges: [][]rune{}} + p120.items = []parser{&p119} + var p181 = sequenceParser{id: 181, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} + p181.items = []parser{&p186, &p120} + p182.items = []parser{&p120, &p181} + var p165 = sequenceParser{id: 165, commit: 66, allChars: false, name: "definitions", ranges: [][]int{{1, 1}, {0, 1}}, generalizations: []int{}} + var p46 = sequenceParser{id: 46, commit: 64, allChars: false, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{}} + var p18 = sequenceParser{id: 18, commit: 74, allChars: false, name: "definition-name", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} + var p8 = sequenceParser{id: 8, commit: 72, allChars: false, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{15, 21, 171}} + var p7 = sequenceParser{id: 7, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p154 = charParser{id: 154, 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}, ranges: [][]rune{}} + p7.items = []parser{&p154} + p8.items = []parser{&p7} + var p24 = sequenceParser{id: 24, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{}} + var p69 = sequenceParser{id: 69, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p162 = charParser{id: 162, not: false, chars: []rune{58}, ranges: [][]rune{}} + p69.items = []parser{&p162} + var p56 = choiceParser{id: 56, commit: 66, name: "flag", generalizations: []int{}} + var p169 = sequenceParser{id: 169, commit: 72, allChars: true, name: "alias", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{56}} + var p175 = charParser{id: 175, not: false, chars: []rune{97}, ranges: [][]rune{}} + var p68 = charParser{id: 68, not: false, chars: []rune{108}, ranges: [][]rune{}} + var p4 = charParser{id: 4, not: false, chars: []rune{105}, ranges: [][]rune{}} + var p22 = charParser{id: 22, not: false, chars: []rune{97}, ranges: [][]rune{}} + var p97 = charParser{id: 97, not: false, chars: []rune{115}, ranges: [][]rune{}} + p169.items = []parser{&p175, &p68, &p4, &p22, &p97} + var p11 = sequenceParser{id: 11, commit: 72, allChars: true, name: "ws", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{56}} + var p150 = charParser{id: 150, not: false, chars: []rune{119}, ranges: [][]rune{}} + var p45 = charParser{id: 45, not: false, chars: []rune{115}, ranges: [][]rune{}} + p11.items = []parser{&p150, &p45} + var p23 = sequenceParser{id: 23, commit: 72, allChars: true, name: "nows", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{56}} + var p136 = charParser{id: 136, not: false, chars: []rune{110}, ranges: [][]rune{}} + var p55 = charParser{id: 55, not: false, chars: []rune{111}, ranges: [][]rune{}} + var p33 = charParser{id: 33, not: false, chars: []rune{119}, ranges: [][]rune{}} + var p39 = charParser{id: 39, not: false, chars: []rune{115}, ranges: [][]rune{}} + p23.items = []parser{&p136, &p55, &p33, &p39} + var p12 = sequenceParser{id: 12, commit: 72, allChars: true, name: "failpass", 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{56}} + var p81 = charParser{id: 81, not: false, chars: []rune{102}, ranges: [][]rune{}} + var p62 = charParser{id: 62, not: false, chars: []rune{97}, ranges: [][]rune{}} + var p156 = charParser{id: 156, not: false, chars: []rune{105}, ranges: [][]rune{}} + var p74 = charParser{id: 74, not: false, chars: []rune{108}, ranges: [][]rune{}} + var p118 = charParser{id: 118, not: false, chars: []rune{112}, ranges: [][]rune{}} + var p40 = charParser{id: 40, not: false, chars: []rune{97}, ranges: [][]rune{}} + var p75 = charParser{id: 75, not: false, chars: []rune{115}, ranges: [][]rune{}} + var p113 = charParser{id: 113, not: false, chars: []rune{115}, ranges: [][]rune{}} + p12.items = []parser{&p81, &p62, &p156, &p74, &p118, &p40, &p75, &p113} + var p29 = sequenceParser{id: 29, commit: 72, allChars: true, name: "root", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{56}} + var p76 = charParser{id: 76, not: false, chars: []rune{114}, ranges: [][]rune{}} + var p176 = charParser{id: 176, not: false, chars: []rune{111}, ranges: [][]rune{}} + var p107 = charParser{id: 107, not: false, chars: []rune{111}, ranges: [][]rune{}} + var p128 = charParser{id: 128, not: false, chars: []rune{116}, ranges: [][]rune{}} + p29.items = []parser{&p76, &p176, &p107, &p128} + p56.options = []parser{&p169, &p11, &p23, &p12, &p29} + p24.items = []parser{&p69, &p56} + p18.items = []parser{&p8, &p24} + var p177 = sequenceParser{id: 177, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p63 = charParser{id: 63, not: false, chars: []rune{61}, ranges: [][]rune{}} + p177.items = []parser{&p63} + var p15 = choiceParser{id: 15, commit: 66, name: "expression", generalizations: []int{}} + var p88 = choiceParser{id: 88, commit: 66, name: "terminal", generalizations: []int{15, 21, 171}} + var p179 = sequenceParser{id: 179, commit: 72, allChars: true, name: "any-char", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{88, 15, 21, 171}} + var p67 = charParser{id: 67, not: false, chars: []rune{46}, ranges: [][]rune{}} + p179.items = []parser{&p67} + var p173 = sequenceParser{id: 173, commit: 72, allChars: false, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}, generalizations: []int{88, 15, 21, 171}} + var p131 = sequenceParser{id: 131, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p20 = charParser{id: 20, not: false, chars: []rune{91}, ranges: [][]rune{}} + p131.items = []parser{&p20} + var p87 = sequenceParser{id: 87, commit: 72, allChars: true, name: "class-not", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p91 = charParser{id: 91, not: false, chars: []rune{94}, ranges: [][]rune{}} + p87.items = []parser{&p91} + var p110 = choiceParser{id: 110, commit: 10, generalizations: []int{}} + var p65 = choiceParser{id: 65, commit: 72, name: "class-char", generalizations: []int{110}} + var p1 = sequenceParser{id: 1, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{65, 110}} + var p102 = charParser{id: 102, not: true, chars: []rune{92, 91, 93, 94, 45}, ranges: [][]rune{}} + p1.items = []parser{&p102} + var p38 = sequenceParser{id: 38, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{65, 110}} + var p116 = sequenceParser{id: 116, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p28 = charParser{id: 28, not: false, chars: []rune{92}, ranges: [][]rune{}} + p116.items = []parser{&p28} + var p172 = sequenceParser{id: 172, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p123 = charParser{id: 123, not: true, chars: []rune{}, ranges: [][]rune{}} + p172.items = []parser{&p123} + p38.items = []parser{&p116, &p172} + p65.options = []parser{&p1, &p38} + var p117 = sequenceParser{id: 117, commit: 72, allChars: false, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{110}} + var p159 = sequenceParser{id: 159, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p115 = charParser{id: 115, not: false, chars: []rune{45}, ranges: [][]rune{}} + p159.items = []parser{&p115} + p117.items = []parser{&p65, &p159, &p65} + p110.options = []parser{&p65, &p117} + var p103 = sequenceParser{id: 103, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p132 = charParser{id: 132, not: false, chars: []rune{93}, ranges: [][]rune{}} + p103.items = []parser{&p132} + p173.items = []parser{&p131, &p87, &p110, &p103} + var p3 = sequenceParser{id: 3, commit: 72, allChars: false, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{88, 15, 21, 171}} + var p152 = sequenceParser{id: 152, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p84 = charParser{id: 84, not: false, chars: []rune{34}, ranges: [][]rune{}} + p152.items = []parser{&p84} + var p52 = choiceParser{id: 52, commit: 72, name: "sequence-char", generalizations: []int{}} + var p32 = sequenceParser{id: 32, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{52}} + var p14 = charParser{id: 14, not: true, chars: []rune{92, 34}, ranges: [][]rune{}} + p32.items = []parser{&p14} + var p160 = sequenceParser{id: 160, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}, generalizations: []int{52}} + var p2 = sequenceParser{id: 2, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p124 = charParser{id: 124, not: false, chars: []rune{92}, ranges: [][]rune{}} + p2.items = []parser{&p124} + var p133 = sequenceParser{id: 133, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p47 = charParser{id: 47, not: true, chars: []rune{}, ranges: [][]rune{}} + p133.items = []parser{&p47} + p160.items = []parser{&p2, &p133} + p52.options = []parser{&p32, &p160} + var p125 = sequenceParser{id: 125, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p48 = charParser{id: 48, not: false, chars: []rune{34}, ranges: [][]rune{}} + p125.items = []parser{&p48} + p3.items = []parser{&p152, &p52, &p125} + p88.options = []parser{&p179, &p173, &p3} + var p174 = sequenceParser{id: 174, commit: 66, allChars: false, name: "group", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{15, 21, 171}} + var p85 = sequenceParser{id: 85, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p149 = charParser{id: 149, not: false, chars: []rune{40}, ranges: [][]rune{}} + p85.items = []parser{&p149} + var p25 = sequenceParser{id: 25, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p79 = charParser{id: 79, not: false, chars: []rune{41}, ranges: [][]rune{}} + p25.items = []parser{&p79} + p174.items = []parser{&p85, &p186, &p15, &p186, &p25} + var p106 = sequenceParser{id: 106, commit: 64, allChars: false, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}, generalizations: []int{15, 171}} + var p61 = sequenceParser{id: 61, commit: 72, allChars: false, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}, generalizations: []int{}} + var p21 = choiceParser{id: 21, commit: 10, generalizations: []int{}} + p21.options = []parser{&p88, &p8, &p174} + var p10 = choiceParser{id: 10, commit: 66, name: "quantity", generalizations: []int{}} + var p139 = sequenceParser{id: 139, commit: 64, allChars: false, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}, generalizations: []int{10}} + var p27 = sequenceParser{id: 27, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p9 = charParser{id: 9, not: false, chars: []rune{123}, ranges: [][]rune{}} + p27.items = []parser{&p9} + var p86 = sequenceParser{id: 86, commit: 64, allChars: false, name: "count", ranges: [][]int{{1, 1}}, generalizations: []int{}} + var p92 = sequenceParser{id: 92, commit: 74, allChars: false, name: "number", ranges: [][]int{{1, -1}, {1, -1}}, generalizations: []int{}} + var p134 = sequenceParser{id: 134, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p126 = charParser{id: 126, not: false, chars: []rune{}, ranges: [][]rune{{48, 57}}} + p134.items = []parser{&p126} + p92.items = []parser{&p134} + p86.items = []parser{&p92} + var p93 = sequenceParser{id: 93, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p78 = charParser{id: 78, not: false, chars: []rune{125}, ranges: [][]rune{}} + p93.items = []parser{&p78} + p139.items = []parser{&p27, &p186, &p86, &p186, &p93} + var p146 = sequenceParser{id: 146, commit: 64, allChars: false, 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{10}} + var p44 = sequenceParser{id: 44, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p94 = charParser{id: 94, not: false, chars: []rune{123}, ranges: [][]rune{}} + p44.items = []parser{&p94} + var p127 = sequenceParser{id: 127, commit: 64, allChars: false, name: "range-from", ranges: [][]int{{1, 1}}, generalizations: []int{}} + p127.items = []parser{&p92} + var p49 = sequenceParser{id: 49, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p59 = charParser{id: 59, not: false, chars: []rune{44}, ranges: [][]rune{}} + p49.items = []parser{&p59} + var p26 = sequenceParser{id: 26, commit: 64, allChars: false, name: "range-to", ranges: [][]int{{1, 1}}, generalizations: []int{}} + p26.items = []parser{&p92} + var p135 = sequenceParser{id: 135, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p53 = charParser{id: 53, not: false, chars: []rune{125}, ranges: [][]rune{}} + p135.items = []parser{&p53} + p146.items = []parser{&p44, &p186, &p127, &p186, &p49, &p186, &p26, &p186, &p135} + var p161 = sequenceParser{id: 161, commit: 72, allChars: true, name: "one-or-more", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{10}} + var p60 = charParser{id: 60, not: false, chars: []rune{43}, ranges: [][]rune{}} + p161.items = []parser{&p60} + var p104 = sequenceParser{id: 104, commit: 72, allChars: true, name: "zero-or-more", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{10}} + var p111 = charParser{id: 111, not: false, chars: []rune{42}, ranges: [][]rune{}} + p104.items = []parser{&p111} + var p155 = sequenceParser{id: 155, commit: 72, allChars: true, name: "zero-or-one", ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{10}} + var p98 = charParser{id: 98, not: false, chars: []rune{63}, ranges: [][]rune{}} + p155.items = []parser{&p98} + p10.options = []parser{&p139, &p146, &p161, &p104, &p155} + p61.items = []parser{&p21, &p10} + var p105 = sequenceParser{id: 105, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} + p105.items = []parser{&p186, &p61} + p106.items = []parser{&p61, &p105} + var p100 = sequenceParser{id: 100, commit: 64, allChars: false, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}, generalizations: []int{15}} + var p171 = choiceParser{id: 171, commit: 66, name: "option", generalizations: []int{}} + p171.options = []parser{&p88, &p8, &p174, &p106} + var p168 = sequenceParser{id: 168, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}, generalizations: []int{}} + var p80 = sequenceParser{id: 80, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p112 = charParser{id: 112, not: false, chars: []rune{124}, ranges: [][]rune{}} + p80.items = []parser{&p112} + p168.items = []parser{&p80, &p186, &p171} + var p99 = sequenceParser{id: 99, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} + p99.items = []parser{&p186, &p168} + p100.items = []parser{&p171, &p186, &p168, &p99} + p15.options = []parser{&p88, &p8, &p174, &p106, &p100} + p46.items = []parser{&p18, &p186, &p177, &p186, &p15} + var p164 = sequenceParser{id: 164, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} + var p71 = sequenceParser{id: 71, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}, generalizations: []int{}} + var p34 = sequenceParser{id: 34, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p180 = charParser{id: 180, not: false, chars: []rune{59}, ranges: [][]rune{}} + p34.items = []parser{&p180} + var p70 = sequenceParser{id: 70, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} + p70.items = []parser{&p186, &p34} + p71.items = []parser{&p34, &p70, &p186, &p46} + var p163 = sequenceParser{id: 163, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} + p163.items = []parser{&p186, &p71} + p164.items = []parser{&p186, &p71, &p163} + p165.items = []parser{&p46, &p164} + var p184 = sequenceParser{id: 184, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}, generalizations: []int{}} + var p82 = sequenceParser{id: 82, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}, generalizations: []int{}} + var p41 = charParser{id: 41, not: false, chars: []rune{59}, ranges: [][]rune{}} + p82.items = []parser{&p41} + var p183 = sequenceParser{id: 183, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}, generalizations: []int{}} + p183.items = []parser{&p186, &p82} + p184.items = []parser{&p186, &p82, &p183} + p187.items = []parser{&p182, &p186, &p165, &p184} + p188.items = []parser{&p186, &p187, &p186} + var b188 = sequenceBuilder{id: 188, commit: 32, allChars: false, name: "syntax", ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var b186 = choiceBuilder{id: 186, commit: 2} + var b185 = choiceBuilder{id: 185, commit: 70} + var b17 = choiceBuilder{id: 17, commit: 66} + var b109 = sequenceBuilder{id: 109, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b108 = charBuilder{} + b109.items = []builder{&b108} + var b170 = sequenceBuilder{id: 170, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b137 = charBuilder{} + b170.items = []builder{&b137} + var b54 = sequenceBuilder{id: 54, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b147 = charBuilder{} + b54.items = []builder{&b147} + var b64 = sequenceBuilder{id: 64, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b157 = charBuilder{} + b64.items = []builder{&b157} + var b72 = sequenceBuilder{id: 72, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b121 = charBuilder{} + b72.items = []builder{&b121} + var b19 = sequenceBuilder{id: 19, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b16 = charBuilder{} + b19.items = []builder{&b16} + var b5 = sequenceBuilder{id: 5, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b73 = charBuilder{} + b5.items = []builder{&b73} + b17.options = []builder{&b109, &b170, &b54, &b64, &b72, &b19, &b5} + var b58 = sequenceBuilder{id: 58, commit: 72, allChars: false, name: "comment", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} + var b43 = choiceBuilder{id: 43, commit: 74} + var b144 = sequenceBuilder{id: 144, commit: 74, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} + var b138 = sequenceBuilder{id: 138, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b42 = charBuilder{} + var b35 = charBuilder{} + b138.items = []builder{&b42, &b35} + var b30 = sequenceBuilder{id: 30, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b166 = charBuilder{} + b30.items = []builder{&b166} + b144.items = []builder{&b138, &b30} + var b90 = sequenceBuilder{id: 90, commit: 74, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}} + var b129 = sequenceBuilder{id: 129, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b158 = charBuilder{} + var b95 = charBuilder{} + b129.items = []builder{&b158, &b95} + var b6 = choiceBuilder{id: 6, commit: 10} + var b153 = sequenceBuilder{id: 153, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b101 = sequenceBuilder{id: 101, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b148 = charBuilder{} + b101.items = []builder{&b148} + var b13 = sequenceBuilder{id: 13, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b142 = charBuilder{} + b13.items = []builder{&b142} + b153.items = []builder{&b101, &b13} + var b143 = sequenceBuilder{id: 143, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b83 = charBuilder{} + b143.items = []builder{&b83} + b6.options = []builder{&b153, &b143} + var b89 = sequenceBuilder{id: 89, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b96 = charBuilder{} + var b130 = charBuilder{} + b89.items = []builder{&b96, &b130} + b90.items = []builder{&b129, &b6, &b89} + b43.options = []builder{&b144, &b90} + var b31 = sequenceBuilder{id: 31, commit: 10, allChars: false, ranges: [][]int{{0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}} + var b57 = choiceBuilder{id: 57, commit: 74} + var b50 = sequenceBuilder{id: 50, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b167 = charBuilder{} + b50.items = []builder{&b167} + var b151 = sequenceBuilder{id: 151, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b114 = charBuilder{} + b151.items = []builder{&b114} + var b145 = sequenceBuilder{id: 145, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b36 = charBuilder{} + b145.items = []builder{&b36} + var b140 = sequenceBuilder{id: 140, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b122 = charBuilder{} + b140.items = []builder{&b122} + var b178 = sequenceBuilder{id: 178, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b77 = charBuilder{} + b178.items = []builder{&b77} + var b66 = sequenceBuilder{id: 66, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b37 = charBuilder{} + b66.items = []builder{&b37} + b57.options = []builder{&b50, &b151, &b145, &b140, &b178, &b66} + var b141 = sequenceBuilder{id: 141, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b51 = charBuilder{} + b141.items = []builder{&b51} + b31.items = []builder{&b57, &b141, &b57, &b43} + b58.items = []builder{&b43, &b31} + b185.options = []builder{&b17, &b58} + b186.options = []builder{&b185} + var b187 = sequenceBuilder{id: 187, commit: 66, allChars: false, ranges: [][]int{{0, 1}, {0, -1}, {0, 1}, {0, 1}}} + var b182 = sequenceBuilder{id: 182, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}}} + var b120 = sequenceBuilder{id: 120, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b119 = charBuilder{} + b120.items = []builder{&b119} + var b181 = sequenceBuilder{id: 181, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} + b181.items = []builder{&b186, &b120} + b182.items = []builder{&b120, &b181} + var b165 = sequenceBuilder{id: 165, commit: 66, allChars: false, ranges: [][]int{{1, 1}, {0, 1}}} + var b46 = sequenceBuilder{id: 46, commit: 64, allChars: false, name: "definition", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} + var b18 = sequenceBuilder{id: 18, commit: 74, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} + var b8 = sequenceBuilder{id: 8, commit: 72, allChars: false, name: "symbol", ranges: [][]int{{1, -1}, {1, -1}}} + var b7 = sequenceBuilder{id: 7, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b154 = charBuilder{} + b7.items = []builder{&b154} + b8.items = []builder{&b7} + var b24 = sequenceBuilder{id: 24, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b69 = sequenceBuilder{id: 69, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b162 = charBuilder{} + b69.items = []builder{&b162} + var b56 = choiceBuilder{id: 56, commit: 66} + var b169 = sequenceBuilder{id: 169, commit: 72, allChars: true, name: "alias", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b175 = charBuilder{} + var b68 = charBuilder{} + var b4 = charBuilder{} + var b22 = charBuilder{} + var b97 = charBuilder{} + b169.items = []builder{&b175, &b68, &b4, &b22, &b97} + var b11 = sequenceBuilder{id: 11, commit: 72, allChars: true, name: "ws", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b150 = charBuilder{} + var b45 = charBuilder{} + b11.items = []builder{&b150, &b45} + var b23 = sequenceBuilder{id: 23, commit: 72, allChars: true, name: "nows", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b136 = charBuilder{} + var b55 = charBuilder{} + var b33 = charBuilder{} + var b39 = charBuilder{} + b23.items = []builder{&b136, &b55, &b33, &b39} + var b12 = sequenceBuilder{id: 12, commit: 72, allChars: true, name: "failpass", 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}}} + var b81 = charBuilder{} + var b62 = charBuilder{} + var b156 = charBuilder{} + var b74 = charBuilder{} + var b118 = charBuilder{} + var b40 = charBuilder{} + var b75 = charBuilder{} + var b113 = charBuilder{} + b12.items = []builder{&b81, &b62, &b156, &b74, &b118, &b40, &b75, &b113} + var b29 = sequenceBuilder{id: 29, commit: 72, allChars: true, name: "root", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b76 = charBuilder{} + var b176 = charBuilder{} + var b107 = charBuilder{} + var b128 = charBuilder{} + b29.items = []builder{&b76, &b176, &b107, &b128} + b56.options = []builder{&b169, &b11, &b23, &b12, &b29} + b24.items = []builder{&b69, &b56} + b18.items = []builder{&b8, &b24} + var b177 = sequenceBuilder{id: 177, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b63 = charBuilder{} + b177.items = []builder{&b63} + var b15 = choiceBuilder{id: 15, commit: 66} + var b88 = choiceBuilder{id: 88, commit: 66} + var b179 = sequenceBuilder{id: 179, commit: 72, allChars: true, name: "any-char", ranges: [][]int{{1, 1}, {1, 1}}} + var b67 = charBuilder{} + b179.items = []builder{&b67} + var b173 = sequenceBuilder{id: 173, commit: 72, allChars: false, name: "char-class", ranges: [][]int{{1, 1}, {0, 1}, {0, -1}, {1, 1}, {1, 1}, {0, 1}, {0, -1}, {1, 1}}} + var b131 = sequenceBuilder{id: 131, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b20 = charBuilder{} + b131.items = []builder{&b20} + var b87 = sequenceBuilder{id: 87, commit: 72, allChars: true, name: "class-not", ranges: [][]int{{1, 1}, {1, 1}}} + var b91 = charBuilder{} + b87.items = []builder{&b91} + var b110 = choiceBuilder{id: 110, commit: 10} + var b65 = choiceBuilder{id: 65, commit: 72, name: "class-char"} + var b1 = sequenceBuilder{id: 1, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b102 = charBuilder{} + b1.items = []builder{&b102} + var b38 = sequenceBuilder{id: 38, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b116 = sequenceBuilder{id: 116, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b28 = charBuilder{} + b116.items = []builder{&b28} + var b172 = sequenceBuilder{id: 172, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b123 = charBuilder{} + b172.items = []builder{&b123} + b38.items = []builder{&b116, &b172} + b65.options = []builder{&b1, &b38} + var b117 = sequenceBuilder{id: 117, commit: 72, allChars: false, name: "char-range", ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b159 = sequenceBuilder{id: 159, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b115 = charBuilder{} + b159.items = []builder{&b115} + b117.items = []builder{&b65, &b159, &b65} + b110.options = []builder{&b65, &b117} + var b103 = sequenceBuilder{id: 103, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b132 = charBuilder{} + b103.items = []builder{&b132} + b173.items = []builder{&b131, &b87, &b110, &b103} + var b3 = sequenceBuilder{id: 3, commit: 72, allChars: false, name: "char-sequence", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {1, 1}, {0, -1}, {1, 1}}} + var b152 = sequenceBuilder{id: 152, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b84 = charBuilder{} + b152.items = []builder{&b84} + var b52 = choiceBuilder{id: 52, commit: 72, name: "sequence-char"} + var b32 = sequenceBuilder{id: 32, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b14 = charBuilder{} + b32.items = []builder{&b14} + var b160 = sequenceBuilder{id: 160, commit: 10, allChars: false, ranges: [][]int{{1, 1}, {1, 1}, {1, 1}, {1, 1}}} + var b2 = sequenceBuilder{id: 2, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b124 = charBuilder{} + b2.items = []builder{&b124} + var b133 = sequenceBuilder{id: 133, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b47 = charBuilder{} + b133.items = []builder{&b47} + b160.items = []builder{&b2, &b133} + b52.options = []builder{&b32, &b160} + var b125 = sequenceBuilder{id: 125, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b48 = charBuilder{} + b125.items = []builder{&b48} + b3.items = []builder{&b152, &b52, &b125} + b88.options = []builder{&b179, &b173, &b3} + var b174 = sequenceBuilder{id: 174, commit: 66, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} + var b85 = sequenceBuilder{id: 85, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b149 = charBuilder{} + b85.items = []builder{&b149} + var b25 = sequenceBuilder{id: 25, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b79 = charBuilder{} + b25.items = []builder{&b79} + b174.items = []builder{&b85, &b186, &b15, &b186, &b25} + var b106 = sequenceBuilder{id: 106, commit: 64, allChars: false, name: "sequence", ranges: [][]int{{1, 1}, {0, -1}}} + var b61 = sequenceBuilder{id: 61, commit: 72, allChars: false, name: "item", ranges: [][]int{{1, 1}, {0, 1}, {1, 1}, {0, 1}}} + var b21 = choiceBuilder{id: 21, commit: 10} + b21.options = []builder{&b88, &b8, &b174} + var b10 = choiceBuilder{id: 10, commit: 66} + var b139 = sequenceBuilder{id: 139, commit: 64, allChars: false, name: "count-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}, {1, 1}}} + var b27 = sequenceBuilder{id: 27, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b9 = charBuilder{} + b27.items = []builder{&b9} + var b86 = sequenceBuilder{id: 86, commit: 64, allChars: false, name: "count", ranges: [][]int{{1, 1}}} + var b92 = sequenceBuilder{id: 92, commit: 74, allChars: false, ranges: [][]int{{1, -1}, {1, -1}}} + var b134 = sequenceBuilder{id: 134, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b126 = charBuilder{} + b134.items = []builder{&b126} + b92.items = []builder{&b134} + b86.items = []builder{&b92} + var b93 = sequenceBuilder{id: 93, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b78 = charBuilder{} + b93.items = []builder{&b78} + b139.items = []builder{&b27, &b186, &b86, &b186, &b93} + var b146 = sequenceBuilder{id: 146, commit: 64, allChars: false, name: "range-quantifier", ranges: [][]int{{1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}, {0, -1}, {0, 1}, {0, -1}, {1, 1}}} + var b44 = sequenceBuilder{id: 44, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b94 = charBuilder{} + b44.items = []builder{&b94} + var b127 = sequenceBuilder{id: 127, commit: 64, allChars: false, name: "range-from", ranges: [][]int{{1, 1}}} + b127.items = []builder{&b92} + var b49 = sequenceBuilder{id: 49, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b59 = charBuilder{} + b49.items = []builder{&b59} + var b26 = sequenceBuilder{id: 26, commit: 64, allChars: false, name: "range-to", ranges: [][]int{{1, 1}}} + b26.items = []builder{&b92} + var b135 = sequenceBuilder{id: 135, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b53 = charBuilder{} + b135.items = []builder{&b53} + b146.items = []builder{&b44, &b186, &b127, &b186, &b49, &b186, &b26, &b186, &b135} + var b161 = sequenceBuilder{id: 161, commit: 72, allChars: true, name: "one-or-more", ranges: [][]int{{1, 1}, {1, 1}}} + var b60 = charBuilder{} + b161.items = []builder{&b60} + var b104 = sequenceBuilder{id: 104, commit: 72, allChars: true, name: "zero-or-more", ranges: [][]int{{1, 1}, {1, 1}}} + var b111 = charBuilder{} + b104.items = []builder{&b111} + var b155 = sequenceBuilder{id: 155, commit: 72, allChars: true, name: "zero-or-one", ranges: [][]int{{1, 1}, {1, 1}}} + var b98 = charBuilder{} + b155.items = []builder{&b98} + b10.options = []builder{&b139, &b146, &b161, &b104, &b155} + b61.items = []builder{&b21, &b10} + var b105 = sequenceBuilder{id: 105, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} + b105.items = []builder{&b186, &b61} + b106.items = []builder{&b61, &b105} + var b100 = sequenceBuilder{id: 100, commit: 64, allChars: false, name: "choice", ranges: [][]int{{1, 1}, {0, -1}, {1, 1}, {0, -1}}} + var b171 = choiceBuilder{id: 171, commit: 66} + b171.options = []builder{&b88, &b8, &b174, &b106} + var b168 = sequenceBuilder{id: 168, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {1, 1}}} + var b80 = sequenceBuilder{id: 80, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b112 = charBuilder{} + b80.items = []builder{&b112} + b168.items = []builder{&b80, &b186, &b171} + var b99 = sequenceBuilder{id: 99, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} + b99.items = []builder{&b186, &b168} + b100.items = []builder{&b171, &b186, &b168, &b99} + b15.options = []builder{&b88, &b8, &b174, &b106, &b100} + b46.items = []builder{&b18, &b186, &b177, &b186, &b15} + var b164 = sequenceBuilder{id: 164, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var b71 = sequenceBuilder{id: 71, commit: 2, allChars: false, ranges: [][]int{{1, 1}, {0, -1}, {0, -1}, {1, 1}}} + var b34 = sequenceBuilder{id: 34, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b180 = charBuilder{} + b34.items = []builder{&b180} + var b70 = sequenceBuilder{id: 70, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} + b70.items = []builder{&b186, &b34} + b71.items = []builder{&b34, &b70, &b186, &b46} + var b163 = sequenceBuilder{id: 163, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} + b163.items = []builder{&b186, &b71} + b164.items = []builder{&b186, &b71, &b163} + b165.items = []builder{&b46, &b164} + var b184 = sequenceBuilder{id: 184, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}, {0, -1}}} + var b82 = sequenceBuilder{id: 82, commit: 10, allChars: true, ranges: [][]int{{1, 1}, {1, 1}}} + var b41 = charBuilder{} + b82.items = []builder{&b41} + var b183 = sequenceBuilder{id: 183, commit: 2, allChars: false, ranges: [][]int{{0, -1}, {1, 1}}} + b183.items = []builder{&b186, &b82} + b184.items = []builder{&b186, &b82, &b183} + b187.items = []builder{&b182, &b186, &b165, &b184} + b188.items = []builder{&b186, &b187, &b186} + + return parse(r, &p188, &b188) +} diff --git a/sequence.go b/sequence.go index 0338b5e..8dd26fc 100644 --- a/sequence.go +++ b/sequence.go @@ -1,27 +1,5 @@ package treerack -import ( - "fmt" - "io" - "strconv" -) - -type sequenceDefinition struct { - name string - id int - commit CommitType - originalItems []SequenceItem - items []SequenceItem - itemDefs []definition - ranges [][]int - generalizations []int - sbuilder *sequenceBuilder - sparser *sequenceParser - allChars bool - validated bool - initialized bool -} - type sequenceParser struct { name string id int @@ -41,263 +19,6 @@ type sequenceBuilder struct { allChars bool } -func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition { - original := make([]SequenceItem, len(items)) - for i := range items { - original[i] = items[i] - } - - return &sequenceDefinition{ - name: name, - commit: ct, - items: items, - originalItems: original, - } -} - -func (d *sequenceDefinition) nodeName() string { return d.name } -func (d *sequenceDefinition) setName(n string) { d.name = n } -func (d *sequenceDefinition) nodeID() int { return d.id } -func (d *sequenceDefinition) setID(id int) { d.id = id } -func (d *sequenceDefinition) commitType() CommitType { return d.commit } -func (d *sequenceDefinition) setCommitType(ct CommitType) { d.commit = ct } - -func normalizeItemRange(item SequenceItem) SequenceItem { - if item.Min == 0 && item.Max == 0 { - item.Min, item.Max = 1, 1 - return item - } - - if item.Min <= 0 { - item.Min = 0 - } - - if item.Max <= 0 { - item.Max = -1 - } - - return item -} - -func (d *sequenceDefinition) initRanges() { - for i, item := range d.items { - item = normalizeItemRange(item) - d.items[i] = item - d.ranges = append(d.ranges, []int{item.Min, item.Max}) - } -} - -func (d *sequenceDefinition) preinit() { - d.initRanges() -} - -func (d *sequenceDefinition) validate(r *registry) error { - if d.validated { - return nil - } - - d.validated = true - for i := range d.items { - ii, ok := r.definition(d.items[i].Name) - if !ok { - return parserNotFound(d.items[i].Name) - } - - if err := ii.validate(r); err != nil { - return err - } - } - - return nil -} - -func (d *sequenceDefinition) createBuilder() { - d.sbuilder = &sequenceBuilder{ - name: d.name, - id: d.id, - commit: d.commit, - ranges: d.ranges, - } -} - -func (d *sequenceDefinition) initItems(r *registry) { - allChars := true - for _, item := range d.items { - def := r.definitions[item.Name] - d.itemDefs = append(d.itemDefs, def) - def.init(r) - d.sbuilder.items = append(d.sbuilder.items, def.builder()) - if allChars { - if _, isChar := def.(*charParser); !isChar { - allChars = false - } - } - } - - d.sbuilder.allChars = allChars - d.allChars = allChars -} - -func (d *sequenceDefinition) init(r *registry) { - if d.initialized { - return - } - - d.initialized = true - d.initRanges() - d.createBuilder() - d.initItems(r) -} - -func (d *sequenceDefinition) addGeneralization(g int) { - if intsContain(d.generalizations, g) { - return - } - - d.generalizations = append(d.generalizations, g) -} - -func (d *sequenceDefinition) createParser() { - d.sparser = &sequenceParser{ - name: d.name, - id: d.id, - commit: d.commit, - generalizations: d.generalizations, - allChars: d.allChars, - ranges: d.ranges, - } -} - -func (d *sequenceDefinition) createItemParsers() { - for _, item := range d.itemDefs { - pi := item.parser() - d.sparser.items = append(d.sparser.items, pi) - } -} - -func (d *sequenceDefinition) parser() parser { - if d.sparser != nil { - return d.sparser - } - - d.createParser() - d.createItemParsers() - return d.sparser -} - -func (d *sequenceDefinition) builder() builder { return d.sbuilder } - -func (d *sequenceDefinition) isCharSequence(r *registry) bool { - for i := range d.originalItems { - item := normalizeItemRange(d.originalItems[i]) - if item.Min != 1 || item.Max != 1 { - return false - } - - itemDef, _ := r.definition(d.originalItems[i].Name) - c, ok := itemDef.(*charParser) - if !ok || !c.isSingleChar() { - return false - } - } - - return true -} - -func (d *sequenceDefinition) format(r *registry, f formatFlags) string { - if d.isCharSequence(r) { - if len(d.originalItems) == 1 { - itemDef, _ := r.definition(d.originalItems[0].Name) - c, _ := itemDef.(*charParser) - return c.format(r, f) - } - - var chars []rune - for i := range d.originalItems { - itemDef, _ := r.definition(d.originalItems[i].Name) - c, _ := itemDef.(*charParser) - chars = append(chars, c.chars[0]) - } - - chars = escape(charClassEscape, []rune(charClassBanned), chars) - return string(append([]rune{'"'}, append(chars, '"')...)) - } - - var chars []rune - for i := range d.originalItems { - if len(chars) > 0 { - chars = append(chars, ' ') - } - - item := normalizeItemRange(d.originalItems[i]) - needsQuantifier := item.Min != 1 || item.Max != 1 - - itemDef, _ := r.definition(item.Name) - isSymbol := itemDef.commitType()&userDefined != 0 - - ch, isChoice := itemDef.(*choiceDefinition) - isChoiceOfMultiple := isChoice && len(ch.options) > 1 - - seq, isSequence := itemDef.(*sequenceDefinition) - isSequenceOfMultiple := isSequence && len(seq.originalItems) > 1 && !seq.isCharSequence(r) - - needsGrouping := isChoiceOfMultiple || isSequenceOfMultiple - - if isSymbol { - chars = append(chars, []rune(itemDef.nodeName())...) - } else { - if needsGrouping { - chars = append(chars, '(') - } - - chars = append(chars, []rune(itemDef.format(r, f))...) - - if needsGrouping { - chars = append(chars, ')') - } - } - - if !needsQuantifier { - continue - } - - if item.Min == 0 && item.Max == 1 { - chars = append(chars, '?') - continue - } - - if item.Min == 0 && item.Max < 0 { - chars = append(chars, '*') - continue - } - - if item.Min == 1 && item.Max < 0 { - chars = append(chars, '+') - continue - } - - chars = append(chars, '{') - - if item.Min == item.Max { - chars = append(chars, []rune(strconv.Itoa(item.Min))...) - } else { - if item.Min > 0 { - chars = append(chars, []rune(strconv.Itoa(item.Min))...) - } - - chars = append(chars, ',') - - if item.Max >= 0 { - chars = append(chars, []rune(strconv.Itoa(item.Max))...) - } - } - - chars = append(chars, '}') - } - - return string(chars) -} - func (p *sequenceParser) nodeName() string { return p.name } func (p *sequenceParser) nodeID() int { return p.id } func (p *sequenceParser) commitType() CommitType { return p.commit } @@ -376,57 +97,6 @@ func (p *sequenceParser) parse(c *context) { } } -func (p *sequenceParser) generate(w io.Writer, done map[string]bool) error { - if done[p.name] { - return nil - } - - done[p.name] = true - - var err error - fprintf := func(f string, args ...interface{}) { - if err != nil { - return - } - - _, err = fmt.Fprintf(w, f, args...) - } - - fprintf("var p%d = sequenceParser{", p.id) - fprintf("id: %d, commit: %d, allChars: %t,", p.id, p.commit, p.allChars) - if p.commit&userDefined != 0 { - fprintf("name: \"%s\",", p.name) - } - - fprintf("ranges: [][]int{") - for i := range p.ranges { - fprintf("{%d, %d},", p.ranges[i][0], p.ranges[i][1]) - } - - fprintf("},") - - fprintf("generalizations: []int{") - for i := range p.generalizations { - fprintf("%d,", p.generalizations[i]) - } - - fprintf("}};") - - for i := range p.items { - if err := p.items[i].generate(w, done); err != nil { - return err - } - } - - fprintf("p%d.items = []parser{", p.id) - for i := range p.items { - fprintf("&p%d,", p.items[i].nodeID()) - } - - fprintf("};") - return err -} - func (b *sequenceBuilder) nodeName() string { return b.name } func (b *sequenceBuilder) nodeID() int { return b.id } @@ -514,47 +184,3 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) { tokens: c.tokens, }}, true } - -func (b *sequenceBuilder) generate(w io.Writer, done map[string]bool) error { - if done[b.name] { - return nil - } - - done[b.name] = true - - var err error - fprintf := func(f string, args ...interface{}) { - if err != nil { - return - } - - _, err = fmt.Fprintf(w, f, args...) - } - - fprintf("var b%d = sequenceBuilder{", b.id) - fprintf("id: %d, commit: %d, allChars: %t,", b.id, b.commit, b.allChars) - if b.commit&Alias == 0 { - fprintf("name: \"%s\",", b.name) - } - - fprintf("ranges: [][]int{") - for i := range b.ranges { - fprintf("{%d, %d},", b.ranges[i][0], b.ranges[i][1]) - } - - fprintf("}};") - - for i := range b.items { - if err := b.items[i].generate(w, done); err != nil { - return err - } - } - - fprintf("b%d.items = []builder{", b.id) - for i := range b.items { - fprintf("&b%d,", b.items[i].nodeID()) - } - - fprintf("};") - return err -} diff --git a/sequencedefine.go b/sequencedefine.go new file mode 100644 index 0000000..dede5e3 --- /dev/null +++ b/sequencedefine.go @@ -0,0 +1,375 @@ +package treerack + +import ( + "fmt" + "io" + "strconv" +) + +type sequenceDefinition struct { + name string + id int + commit CommitType + originalItems []SequenceItem + items []SequenceItem + itemDefs []definition + ranges [][]int + generalizations []int + sbuilder *sequenceBuilder + sparser *sequenceParser + allChars bool + validated bool + initialized bool +} + +func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition { + original := make([]SequenceItem, len(items)) + for i := range items { + original[i] = items[i] + } + + return &sequenceDefinition{ + name: name, + commit: ct, + items: items, + originalItems: original, + } +} + +func (d *sequenceDefinition) nodeName() string { return d.name } +func (d *sequenceDefinition) setName(n string) { d.name = n } +func (d *sequenceDefinition) nodeID() int { return d.id } +func (d *sequenceDefinition) setID(id int) { d.id = id } +func (d *sequenceDefinition) commitType() CommitType { return d.commit } +func (d *sequenceDefinition) setCommitType(ct CommitType) { d.commit = ct } + +func normalizeItemRange(item SequenceItem) SequenceItem { + if item.Min == 0 && item.Max == 0 { + item.Min, item.Max = 1, 1 + return item + } + + if item.Min <= 0 { + item.Min = 0 + } + + if item.Max <= 0 { + item.Max = -1 + } + + return item +} + +func (d *sequenceDefinition) initRanges() { + for i, item := range d.items { + item = normalizeItemRange(item) + d.items[i] = item + d.ranges = append(d.ranges, []int{item.Min, item.Max}) + } +} + +func (d *sequenceDefinition) preinit() { + d.initRanges() +} + +func (d *sequenceDefinition) validate(r *registry) error { + if d.validated { + return nil + } + + d.validated = true + for i := range d.items { + ii, ok := r.definition(d.items[i].Name) + if !ok { + return parserNotFound(d.items[i].Name) + } + + if err := ii.validate(r); err != nil { + return err + } + } + + return nil +} + +func (d *sequenceDefinition) createBuilder() { + d.sbuilder = &sequenceBuilder{ + name: d.name, + id: d.id, + commit: d.commit, + ranges: d.ranges, + } +} + +func (d *sequenceDefinition) initItems(r *registry) { + allChars := true + for _, item := range d.items { + def := r.definitions[item.Name] + d.itemDefs = append(d.itemDefs, def) + def.init(r) + d.sbuilder.items = append(d.sbuilder.items, def.builder()) + if allChars { + if _, isChar := def.(*charParser); !isChar { + allChars = false + } + } + } + + d.sbuilder.allChars = allChars + d.allChars = allChars +} + +func (d *sequenceDefinition) init(r *registry) { + if d.initialized { + return + } + + d.initialized = true + d.initRanges() + d.createBuilder() + d.initItems(r) +} + +func (d *sequenceDefinition) addGeneralization(g int) { + if intsContain(d.generalizations, g) { + return + } + + d.generalizations = append(d.generalizations, g) +} + +func (d *sequenceDefinition) createParser() { + d.sparser = &sequenceParser{ + name: d.name, + id: d.id, + commit: d.commit, + generalizations: d.generalizations, + allChars: d.allChars, + ranges: d.ranges, + } +} + +func (d *sequenceDefinition) createItemParsers() { + for _, item := range d.itemDefs { + pi := item.parser() + d.sparser.items = append(d.sparser.items, pi) + } +} + +func (d *sequenceDefinition) parser() parser { + if d.sparser != nil { + return d.sparser + } + + d.createParser() + d.createItemParsers() + return d.sparser +} + +func (d *sequenceDefinition) builder() builder { return d.sbuilder } + +func (d *sequenceDefinition) isCharSequence(r *registry) bool { + for i := range d.originalItems { + item := normalizeItemRange(d.originalItems[i]) + if item.Min != 1 || item.Max != 1 { + return false + } + + itemDef, _ := r.definition(d.originalItems[i].Name) + c, ok := itemDef.(*charParser) + if !ok || !c.isSingleChar() { + return false + } + } + + return true +} + +func (d *sequenceDefinition) format(r *registry, f formatFlags) string { + if d.isCharSequence(r) { + if len(d.originalItems) == 1 { + itemDef, _ := r.definition(d.originalItems[0].Name) + c, _ := itemDef.(*charParser) + return c.format(r, f) + } + + var chars []rune + for i := range d.originalItems { + itemDef, _ := r.definition(d.originalItems[i].Name) + c, _ := itemDef.(*charParser) + chars = append(chars, c.chars[0]) + } + + chars = escape(charClassEscape, []rune(charClassBanned), chars) + return string(append([]rune{'"'}, append(chars, '"')...)) + } + + var chars []rune + for i := range d.originalItems { + if len(chars) > 0 { + chars = append(chars, ' ') + } + + item := normalizeItemRange(d.originalItems[i]) + needsQuantifier := item.Min != 1 || item.Max != 1 + + itemDef, _ := r.definition(item.Name) + isSymbol := itemDef.commitType()&userDefined != 0 + + ch, isChoice := itemDef.(*choiceDefinition) + isChoiceOfMultiple := isChoice && len(ch.options) > 1 + + seq, isSequence := itemDef.(*sequenceDefinition) + isSequenceOfMultiple := isSequence && len(seq.originalItems) > 1 && !seq.isCharSequence(r) + + needsGrouping := isChoiceOfMultiple || isSequenceOfMultiple + + if isSymbol { + chars = append(chars, []rune(itemDef.nodeName())...) + } else { + if needsGrouping { + chars = append(chars, '(') + } + + chars = append(chars, []rune(itemDef.format(r, f))...) + + if needsGrouping { + chars = append(chars, ')') + } + } + + if !needsQuantifier { + continue + } + + if item.Min == 0 && item.Max == 1 { + chars = append(chars, '?') + continue + } + + if item.Min == 0 && item.Max < 0 { + chars = append(chars, '*') + continue + } + + if item.Min == 1 && item.Max < 0 { + chars = append(chars, '+') + continue + } + + chars = append(chars, '{') + + if item.Min == item.Max { + chars = append(chars, []rune(strconv.Itoa(item.Min))...) + } else { + if item.Min > 0 { + chars = append(chars, []rune(strconv.Itoa(item.Min))...) + } + + chars = append(chars, ',') + + if item.Max >= 0 { + chars = append(chars, []rune(strconv.Itoa(item.Max))...) + } + } + + chars = append(chars, '}') + } + + return string(chars) +} + +func (p *sequenceParser) generate(w io.Writer, done map[string]bool) error { + if done[p.name] { + return nil + } + + done[p.name] = true + + var err error + fprintf := func(f string, args ...interface{}) { + if err != nil { + return + } + + _, err = fmt.Fprintf(w, f, args...) + } + + fprintf("var p%d = sequenceParser{", p.id) + fprintf("id: %d, commit: %d, allChars: %t,", p.id, p.commit, p.allChars) + if p.commit&userDefined != 0 { + fprintf("name: \"%s\",", p.name) + } + + fprintf("ranges: [][]int{") + for i := range p.ranges { + fprintf("{%d, %d},", p.ranges[i][0], p.ranges[i][1]) + } + + fprintf("},") + + fprintf("generalizations: []int{") + for i := range p.generalizations { + fprintf("%d,", p.generalizations[i]) + } + + fprintf("}};") + + for i := range p.items { + if err := p.items[i].(generator).generate(w, done); err != nil { + return err + } + } + + fprintf("p%d.items = []parser{", p.id) + for i := range p.items { + fprintf("&p%d,", p.items[i].nodeID()) + } + + fprintf("};") + return err +} + +func (b *sequenceBuilder) generate(w io.Writer, done map[string]bool) error { + if done[b.name] { + return nil + } + + done[b.name] = true + + var err error + fprintf := func(f string, args ...interface{}) { + if err != nil { + return + } + + _, err = fmt.Fprintf(w, f, args...) + } + + fprintf("var b%d = sequenceBuilder{", b.id) + fprintf("id: %d, commit: %d, allChars: %t,", b.id, b.commit, b.allChars) + if b.commit&Alias == 0 { + fprintf("name: \"%s\",", b.name) + } + + fprintf("ranges: [][]int{") + for i := range b.ranges { + fprintf("{%d, %d},", b.ranges[i][0], b.ranges[i][1]) + } + + fprintf("}};") + + for i := range b.items { + if err := b.items[i].(generator).generate(w, done); err != nil { + return err + } + } + + fprintf("b%d.items = []builder{", b.id) + for i := range b.items { + fprintf("&b%d,", b.items[i].nodeID()) + } + + fprintf("};") + return err +} diff --git a/syntax.go b/syntax.go index cdf5043..21db0d0 100644 --- a/syntax.go +++ b/syntax.go @@ -1,31 +1,11 @@ package treerack import ( - "bufio" "errors" "fmt" "io" -) -type CommitType int - -const ( - None CommitType = 0 - Alias CommitType = 1 << iota - Whitespace - NoWhitespace - FailPass - Root - - userDefined -) - -type formatFlags int - -const ( - formatNone formatFlags = 0 - formatPretty formatFlags = 1 << iota - formatIncludeComments + "github.com/aryszka/treerack/self" ) // if min=0&&max=0, it means min=1,max=1 @@ -36,33 +16,6 @@ type SequenceItem struct { Min, Max int } -// ParseError is returned when the input text doesn't match -// the used syntax during parsing. -type ParseError struct { - - // Input is the name of the input file or if not - // available. - Input string - - // Offset is the index of the right-most failing - // token in the input text. - Offset int - - // Line tells the line index of the right-most failing - // token in the input text. - // - // It is zero-based, and for error reporting, it is - // recommended to increment it by one. - Line int - - // Column tells the column index of the right-most failing - // token in the input text. - Column int - - // Definition tells the right-most unmatched parser definition. - Definition string -} - type Syntax struct { registry *registry initialized bool @@ -73,6 +26,15 @@ type Syntax struct { builder builder } +type GeneratorOptions struct { + PackageName string +} + +// applied in a non-type-checked way +type generator interface { + generate(io.Writer, map[string]bool) error +} + type definition interface { nodeName() string setName(string) @@ -89,36 +51,16 @@ type definition interface { format(*registry, formatFlags) string } -type parser interface { - nodeName() string - nodeID() int - commitType() CommitType - parse(*context) - generate(io.Writer, map[string]bool) error -} - -type builder interface { - nodeName() string - nodeID() int - build(*context) ([]*Node, bool) - generate(io.Writer, map[string]bool) error -} - var ( - ErrSyntaxInitialized = errors.New("syntax initialized") - ErrInitFailed = errors.New("init failed") - ErrNoParsersDefined = errors.New("no parsers defined") - ErrInvalidInput = errors.New("invalid input") - ErrInvalidUnicodeCharacter = errors.New("invalid unicode character") - ErrInvalidEscapeCharacter = errors.New("invalid escape character") - ErrUnexpectedCharacter = errors.New("unexpected character") - ErrInvalidSyntax = errors.New("invalid syntax") - ErrRootAlias = errors.New("root node cannot be an alias") - ErrRootWhitespace = errors.New("root node cannot be a whitespace") - ErrRootFailPass = errors.New("root node cannot pass failing definition") - ErrNotImplemented = errors.New("not implemented") - ErrMultipleRoots = errors.New("multiple roots") - ErrInvalidSymbolName = errors.New("invalid symbol name") + ErrSyntaxInitialized = errors.New("syntax initialized") + ErrInitFailed = errors.New("init failed") + ErrNoParsersDefined = errors.New("no parsers defined") + ErrInvalidEscapeCharacter = errors.New("invalid escape character") + ErrRootAlias = errors.New("root node cannot be an alias") + ErrRootWhitespace = errors.New("root node cannot be a whitespace") + ErrRootFailPass = errors.New("root node cannot pass failing definition") + ErrMultipleRoots = errors.New("multiple roots") + ErrInvalidSymbolName = errors.New("invalid symbol name") ) func duplicateDefinition(name string) error { @@ -215,6 +157,10 @@ func isValidSymbol(n string) bool { } +// func (pe *ParseError) Verbose() string { +// return "" +// } + func intsContain(is []int, i int) bool { for _, ii := range is { if ii == i { @@ -225,20 +171,6 @@ func intsContain(is []int, i int) bool { return false } -func (pe *ParseError) Error() string { - return fmt.Sprintf( - "%s:%d:%d:parse failed, parsing: %s", - pe.Input, - pe.Line+1, - pe.Column+1, - pe.Definition, - ) -} - -// func (pe *ParseError) Verbose() string { -// return "" -// } - func (s *Syntax) applyRoot(d definition) error { explicitRoot := d.commitType()&Root != 0 if explicitRoot && s.explicitRoot { @@ -369,16 +301,12 @@ func (s *Syntax) ReadSyntax(r io.Reader) error { return ErrSyntaxInitialized } - b, err := bootSyntax() - if err != nil { - return err - } - - n, err := b.Parse(r) + sn, err := self.Parse(r) if err != nil { return err } + n := mapSelfNode(sn) return define(s, n) } @@ -430,59 +358,68 @@ func (s *Syntax) Init() error { return nil } -func (s *Syntax) Generate(w io.Writer) error { +func (s *Syntax) Generate(o GeneratorOptions, w io.Writer) error { if err := s.Init(); err != nil { return err } - if _, err := fmt.Fprint(w, ` -package treerack - -import ( - "bufio" - "io" -) - -func parsegen(r io.Reader) (*Node, error) { -`); err != nil { - return err + if o.PackageName == "" { + o.PackageName = "main" } + var err error + fprintf := func(f string, args ...interface{}) { + if err != nil { + return + } + + _, err = fmt.Fprintf(w, f, args...) + } + + fprint := func(args ...interface{}) { + if err != nil { + return + } + + _, err = fmt.Fprint(w, args...) + } + + fprintln := func() { + fprint("\n") + } + + fprint(gendoc) + fprintln() + fprintln() + + fprintf("package %s", o.PackageName) + fprintln() + fprintln() + + // generate headCode with scripts/createhead.go + fprint(headCode) + fprintln() + fprintln() + + fprint(`func Parse(r io.Reader) (*Node, error) {`) + fprintln() + done := make(map[string]bool) - if err := s.parser.generate(w, done); err != nil { + if err := s.parser.(generator).generate(w, done); err != nil { return err } done = make(map[string]bool) - if err := s.builder.generate(w, done); err != nil { + if err := s.builder.(generator).generate(w, done); err != nil { return err } - if _, err := fmt.Fprintf(w, ` - - c := newContext(bufio.NewReader(r)) - p%d.parse(c) - if c.readErr != nil { - return nil, c.readErr - } - - if err := c.finalizeParse(&p%d); err != nil { - if perr, ok := err.(*ParseError); ok { - perr.Input = "" - } - - return nil, err - } - - c.offset = 0 - c.results.resetPending() - - n, _ := b%d.build(c) - return n[0], nil -} - `, s.parser.nodeID(), s.parser.nodeID(), s.builder.nodeID()); err != nil { - return err - } + fprintln() + fprintln() + fprintf(`return parse(r, &p%d, &b%d)`, s.parser.nodeID(), s.builder.nodeID()) + fprintln() + fprint(`}`) + fprintln() return nil } @@ -492,23 +429,5 @@ func (s *Syntax) Parse(r io.Reader) (*Node, error) { return nil, err } - c := newContext(bufio.NewReader(r)) - s.parser.parse(c) - if c.readErr != nil { - return nil, c.readErr - } - - if err := c.finalizeParse(s.parser); err != nil { - if perr, ok := err.(*ParseError); ok { - perr.Input = "" - } - - return nil, err - } - - c.offset = 0 - c.results.resetPending() - - n, _ := s.builder.build(c) - return n[0], nil + return parse(r, s.parser, s.builder) } diff --git a/syntax_test.go b/syntax_test.go index 15a87e9..90605b8 100644 --- a/syntax_test.go +++ b/syntax_test.go @@ -376,7 +376,7 @@ func TestGenerateSyntax(t *testing.T) { return } - if err := s.Generate(bytes.NewBuffer(nil)); err == nil { + if err := s.Generate(GeneratorOptions{}, bytes.NewBuffer(nil)); err == nil { t.Error(err) } }) @@ -388,7 +388,7 @@ func TestGenerateSyntax(t *testing.T) { return } - if err := s.Generate(bytes.NewBuffer(nil)); err == nil { + if err := s.Generate(GeneratorOptions{}, bytes.NewBuffer(nil)); err == nil { t.Error(err) } }) diff --git a/syntaxhead.go b/syntaxhead.go new file mode 100644 index 0000000..c79def7 --- /dev/null +++ b/syntaxhead.go @@ -0,0 +1,103 @@ +package treerack + +import ( + "bufio" + "errors" + "fmt" + "io" +) + +type CommitType int + +const ( + None CommitType = 0 + Alias CommitType = 1 << iota + Whitespace + NoWhitespace + FailPass + Root + + userDefined +) + +type formatFlags int + +const ( + formatNone formatFlags = 0 + formatPretty formatFlags = 1 << iota + formatIncludeComments +) + +// ParseError is returned when the input text doesn't match +// the used syntax during parsing. +type ParseError struct { + + // Input is the name of the input file or if not + // available. + Input string + + // Offset is the index of the right-most failing + // token in the input text. + Offset int + + // Line tells the line index of the right-most failing + // token in the input text. + // + // It is zero-based, and for error reporting, it is + // recommended to increment it by one. + Line int + + // Column tells the column index of the right-most failing + // token in the input text. + Column int + + // Definition tells the right-most unmatched parser definition. + Definition string +} + +type parser interface { + nodeName() string + nodeID() int + commitType() CommitType + parse(*context) +} + +type builder interface { + nodeName() string + nodeID() int + build(*context) ([]*Node, bool) +} + +var ErrInvalidUnicodeCharacter = errors.New("invalid unicode character") + +func (pe *ParseError) Error() string { + return fmt.Sprintf( + "%s:%d:%d:parse failed, parsing: %s", + pe.Input, + pe.Line+1, + pe.Column+1, + pe.Definition, + ) +} + +func parse(r io.Reader, p parser, b builder) (*Node, error) { + c := newContext(bufio.NewReader(r)) + p.parse(c) + if c.readErr != nil { + return nil, c.readErr + } + + if err := c.finalizeParse(p); err != nil { + if perr, ok := err.(*ParseError); ok { + perr.Input = "" + } + + return nil, err + } + + c.offset = 0 + c.results.resetPending() + + n, _ := b.build(c) + return n[0], nil +}