remove randomness from code generation

This commit is contained in:
Arpad Ryszka 2018-01-09 03:53:20 +01:00
parent 9c97d790ab
commit d6dde78f74
9 changed files with 658 additions and 625 deletions

View File

@ -18,7 +18,7 @@ build: $(SOURCES)
install: $(SOURCES) install: $(SOURCES)
go install ./cmd/treerack go install ./cmd/treerack
head: $(SOURCES) head: $(SOURCES) fmt
go run scripts/createhead.go -- \ go run scripts/createhead.go -- \
char.go \ char.go \
sequence.go \ sequence.go \
@ -29,19 +29,54 @@ head: $(SOURCES)
nodehead.go \ nodehead.go \
syntaxhead.go \ syntaxhead.go \
> head.go > head.go
@gofmt -s -w head.go
generate: $(SOURCES) $(PARSERS) head install generate: $(SOURCES) $(PARSERS) fmt head install
treerack generate -export -package-name self < syntax.treerack > self/self.go.next treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go{.next,} @mv self/self.go{.next,}
@gofmt -s -w self/self.go @gofmt -s -w self/self.go
regenerate: $(SOURCES) $(PARSERS) head install regenerate: $(SOURCES) $(PARSERS) fmt head install
treerack generate -export -package-name self < syntax.treerack > self/self.go.next treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go{.next,} @mv self/self.go{.next,}
treerack generate -export -package-name self < syntax.treerack > self/self.go.next treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go{.next,} @mv self/self.go{.next,}
@gofmt -s -w self/self.go @gofmt -s -w self/self.go
check-generate: $(SOURCES) $(PARSERS)
@echo checking head
@mv head.go head.go.backup
@go run scripts/createhead.go -- \
char.go \
sequence.go \
choice.go \
idset.go \
results.go \
context.go \
nodehead.go \
syntaxhead.go \
> head.go
@gofmt -s -w head.go
@if ! diff head.go head.go.backup > /dev/null; then \
mv head.go.backup head.go; \
echo head does not match; \
false; \
fi
@echo checking self
@mv self/self.go self/self.go.backup
@treerack generate -export -package-name self < syntax.treerack > self/self.go.next
@mv self/self.go{.next,}
@gofmt -s -w self/self.go
@if ! diff self/self.go self/self.go.backup > /dev/null; then \
mv self/self.go.backup self/self.go; \
echo self does not match; \
false; \
fi
@echo ok
@mv head.go.backup head.go
@mv self/self.go.backup self/self.go
check: imports build $(PARSERS) check: imports build $(PARSERS)
go test -test.short -run ^Test go test -test.short -run ^Test
go test ./cmd/treerack -test.short -run ^Test go test ./cmd/treerack -test.short -run ^Test
@ -90,7 +125,7 @@ checkfmt: $(SOURCES)
vet: vet:
go vet ./... go vet ./...
precommit: regenerate fmt vet build checkall precommit: fmt check-generate vet build checkall
clean: clean:
rm -f *.test rm -f *.test

View File

@ -41,7 +41,7 @@ func (d *choiceDefinition) validate(r *registry) error {
d.validated = true d.validated = true
for i := range d.options { for i := range d.options {
o, ok := r.definitions[d.options[i]] o, ok := r.definition[d.options[i]]
if !ok { if !ok {
return parserNotFound(d.options[i]) return parserNotFound(d.options[i])
} }
@ -64,7 +64,7 @@ func (d *choiceDefinition) createBuilder() {
func (d *choiceDefinition) initOptions(r *registry) { func (d *choiceDefinition) initOptions(r *registry) {
for _, o := range d.options { for _, o := range d.options {
def := r.definitions[o] def := r.definition[o]
d.optionDefs = append(d.optionDefs, def) d.optionDefs = append(d.optionDefs, def)
def.init(r) def.init(r)
d.cbuilder.options = append(d.cbuilder.options, def.builder()) d.cbuilder.options = append(d.cbuilder.options, def.builder())
@ -128,7 +128,7 @@ func (d *choiceDefinition) format(r *registry, f formatFlags) string {
chars = append(chars, []rune(" | ")...) chars = append(chars, []rune(" | ")...)
} }
optionDef, _ := r.definition(d.options[i]) optionDef := r.definition[d.options[i]]
if optionDef.commitType()&userDefined != 0 { if optionDef.commitType()&userDefined != 0 {
chars = append(chars, []rune(optionDef.nodeName())...) chars = append(chars, []rune(optionDef.nodeName())...)
} else { } else {

View File

@ -30,7 +30,7 @@ func testDefinitionFormatItem(t *testing.T, treerack *Syntax, f formatFlags, tes
t.Fatal(err) t.Fatal(err)
} }
def, ok := s.registry.definition("def") def, ok := s.registry.definition["def"]
if !ok { if !ok {
t.Fatal("failed to register definition") t.Fatal("failed to register definition")
} }

View File

@ -1,9 +1,10 @@
[next] [next]
no random generator output and generator output check no random generator output and generator output check
errors errors
spellcheck generator 1
linting
releasing releasing
parser
generator 2
formatter formatter
report unused parsers report unused parsers
parse hashed, storing only the results parse hashed, storing only the results
@ -15,14 +16,23 @@ test error report on invalid flag
input name: may be just dropped because completely controlled by the client input name: may be just dropped because completely controlled by the client
input name needed in command to differentiate between syntax and input in check and parse subcommands input name needed in command to differentiate between syntax and input in check and parse subcommands
[generator 1]
allchars: can have char sequence
make generator output non-random (track parsers in a list in definition order)
fix the license in the output
[releasing]
spellcheck
linting
convert notes into issues
try to remove some files
[parser] [parser]
custom tokens custom tokens
indentation indentation
streaming support // ReadNode(io.Reader) streaming support // ReadNode(io.Reader)
[generator] [generator 2]
allchars: can have char sequence
make generator output non-random (track parsers in a list in definition order)
js js
[optimization] [optimization]

View File

@ -2,12 +2,13 @@ package treerack
type registry struct { type registry struct {
idSeed int idSeed int
definitions map[string]definition definition map[string]definition
definitions []definition
} }
func newRegistry(defs ...definition) *registry { func newRegistry(defs ...definition) *registry {
r := &registry{ r := &registry{
definitions: make(map[string]definition), definition: make(map[string]definition),
} }
for _, def := range defs { for _, def := range defs {
@ -17,13 +18,8 @@ func newRegistry(defs ...definition) *registry {
return r return r
} }
func (r *registry) definition(name string) (definition, bool) {
d, ok := r.definitions[name]
return d, ok
}
func (r *registry) setDefinition(d definition) error { func (r *registry) setDefinition(d definition) error {
if _, ok := r.definitions[d.nodeName()]; ok { if _, ok := r.definition[d.nodeName()]; ok {
return duplicateDefinition(d.nodeName()) return duplicateDefinition(d.nodeName())
} }
@ -31,15 +27,7 @@ func (r *registry) setDefinition(d definition) error {
id := r.idSeed id := r.idSeed
d.setID(id) d.setID(id)
r.definitions[d.nodeName()] = d r.definition[d.nodeName()] = d
r.definitions = append(r.definitions, d)
return nil return nil
} }
func (r *registry) getDefinitions() []definition {
var defs []definition
for _, def := range r.definitions {
defs = append(defs, def)
}
return defs
}

File diff suppressed because it is too large Load Diff

View File

@ -79,7 +79,7 @@ func (d *sequenceDefinition) validate(r *registry) error {
d.validated = true d.validated = true
for i := range d.items { for i := range d.items {
ii, ok := r.definition(d.items[i].Name) ii, ok := r.definition[d.items[i].Name]
if !ok { if !ok {
return parserNotFound(d.items[i].Name) return parserNotFound(d.items[i].Name)
} }
@ -104,7 +104,7 @@ func (d *sequenceDefinition) createBuilder() {
func (d *sequenceDefinition) initItems(r *registry) { func (d *sequenceDefinition) initItems(r *registry) {
allChars := true allChars := true
for _, item := range d.items { for _, item := range d.items {
def := r.definitions[item.Name] def := r.definition[item.Name]
d.itemDefs = append(d.itemDefs, def) d.itemDefs = append(d.itemDefs, def)
def.init(r) def.init(r)
d.sbuilder.items = append(d.sbuilder.items, def.builder()) d.sbuilder.items = append(d.sbuilder.items, def.builder())
@ -175,7 +175,7 @@ func (d *sequenceDefinition) isCharSequence(r *registry) bool {
return false return false
} }
itemDef, _ := r.definition(d.originalItems[i].Name) itemDef := r.definition[d.originalItems[i].Name]
c, ok := itemDef.(*charParser) c, ok := itemDef.(*charParser)
if !ok || !c.isSingleChar() { if !ok || !c.isSingleChar() {
return false return false
@ -188,14 +188,14 @@ func (d *sequenceDefinition) isCharSequence(r *registry) bool {
func (d *sequenceDefinition) format(r *registry, f formatFlags) string { func (d *sequenceDefinition) format(r *registry, f formatFlags) string {
if d.isCharSequence(r) { if d.isCharSequence(r) {
if len(d.originalItems) == 1 { if len(d.originalItems) == 1 {
itemDef, _ := r.definition(d.originalItems[0].Name) itemDef := r.definition[d.originalItems[0].Name]
c, _ := itemDef.(*charParser) c, _ := itemDef.(*charParser)
return c.format(r, f) return c.format(r, f)
} }
var chars []rune var chars []rune
for i := range d.originalItems { for i := range d.originalItems {
itemDef, _ := r.definition(d.originalItems[i].Name) itemDef := r.definition[d.originalItems[i].Name]
c, _ := itemDef.(*charParser) c, _ := itemDef.(*charParser)
chars = append(chars, c.chars[0]) chars = append(chars, c.chars[0])
} }
@ -213,7 +213,7 @@ func (d *sequenceDefinition) format(r *registry, f formatFlags) string {
item := normalizeItemRange(d.originalItems[i]) item := normalizeItemRange(d.originalItems[i])
needsQuantifier := item.Min != 1 || item.Max != 1 needsQuantifier := item.Min != 1 || item.Max != 1
itemDef, _ := r.definition(item.Name) itemDef := r.definition[item.Name]
isSymbol := itemDef.commitType()&userDefined != 0 isSymbol := itemDef.commitType()&userDefined != 0
ch, isChoice := itemDef.(*choiceDefinition) ch, isChoice := itemDef.(*choiceDefinition)

View File

@ -264,8 +264,8 @@ func (s *Syntax) Init() error {
return ErrRootFailPass return ErrRootFailPass
} }
defs := s.registry.getDefinitions() defs := s.registry.definitions
for i := range defs { for i := range s.registry.definitions {
defs[i].preinit() defs[i].preinit()
} }

View File

@ -104,7 +104,7 @@ func TestInit(t *testing.T) {
} }
s.Init() s.Init()
if len(s.registry.definitions["a"].(*sequenceDefinition).generalizations) != 1 { if len(s.registry.definition["a"].(*sequenceDefinition).generalizations) != 1 {
t.Error("invalid number of generalizations") t.Error("invalid number of generalizations")
} }
}) })
@ -291,7 +291,7 @@ func TestDefinition(t *testing.T) {
t.Error(err) t.Error(err)
} }
if _, ok := s.registry.definition("a"); !ok { if _, ok := s.registry.definition["a"]; !ok {
t.Error("definition failed") t.Error("definition failed")
} }
}) })
@ -301,7 +301,7 @@ func TestDefinition(t *testing.T) {
t.Error(err) t.Error(err)
} }
if _, ok := s.registry.definition("b"); !ok { if _, ok := s.registry.definition["b"]; !ok {
t.Error("definition failed") t.Error("definition failed")
} }
}) })
@ -311,7 +311,7 @@ func TestDefinition(t *testing.T) {
t.Error(err) t.Error(err)
} }
if _, ok := s.registry.definition("c"); !ok { if _, ok := s.registry.definition["c"]; !ok {
t.Error("definition failed") t.Error("definition failed")
} }
}) })
@ -321,7 +321,7 @@ func TestDefinition(t *testing.T) {
t.Error(err) t.Error(err)
} }
if _, ok := s.registry.definition("d"); !ok { if _, ok := s.registry.definition["d"]; !ok {
t.Error("definition failed") t.Error("definition failed")
} }
}) })
@ -331,7 +331,7 @@ func TestDefinition(t *testing.T) {
t.Error(err) t.Error(err)
} }
if _, ok := s.registry.definition("e"); !ok { if _, ok := s.registry.definition["e"]; !ok {
t.Error("definition failed") t.Error("definition failed")
} }
}) })